From 730eeb17fc7d0128227de01d31c3681b63118529 Mon Sep 17 00:00:00 2001 From: Mark Kurtz Date: Wed, 1 Oct 2025 08:05:07 -0400 Subject: [PATCH 1/3] Initial state for datasets rework to enable multimodal and more complicated combinations --- src/guidellm/__init__.py | 3 + src/guidellm/__main__.py | 97 ++- src/guidellm/backends/__init__.py | 2 + src/guidellm/backends/backend.py | 1 + src/guidellm/backends/objects.py | 152 ++-- src/guidellm/backends/openai.py | 652 ++++++------------ src/guidellm/benchmark/aggregator.py | 227 +++--- src/guidellm/benchmark/entrypoints.py | 268 +++---- src/guidellm/benchmark/objects.py | 8 +- src/guidellm/benchmark/profile.py | 5 +- src/guidellm/data/__init__.py | 52 +- src/guidellm/data/datasets.py | 88 +++ src/guidellm/data/deserializers/__init__.py | 51 ++ .../data/deserializers/deserializer.py | 81 +++ src/guidellm/data/deserializers/file.py | 221 ++++++ .../data/deserializers/huggingface.py | 75 ++ src/guidellm/data/deserializers/memory.py | 191 +++++ src/guidellm/data/deserializers/synthetic.py | 255 +++++++ src/guidellm/data/formatters/__init__.py | 47 ++ src/guidellm/data/formatters/environment.py | 63 ++ src/guidellm/data/formatters/filters.py | 324 +++++++++ src/guidellm/data/formatters/globals.py | 9 + src/guidellm/data/formatters/objects.py | 92 +++ src/guidellm/data/formatters/templates.py | 182 +++++ src/guidellm/data/loaders.py | 93 +++ src/guidellm/data/objects.py | 230 ++++++ src/guidellm/data/preprocessors/__init__.py | 7 + src/guidellm/data/preprocessors/mappers.py | 115 +++ src/guidellm/data/preprocessors/objects.py | 20 + src/guidellm/data/prideandprejudice.txt.gz | Bin 241795 -> 0 bytes src/guidellm/data/utils.py | 161 +++++ src/guidellm/dataset/__init__.py | 22 - src/guidellm/dataset/creator.py | 213 ------ src/guidellm/dataset/entrypoints.py | 42 -- src/guidellm/dataset/file.py | 92 --- src/guidellm/dataset/hf_datasets.py | 62 -- src/guidellm/dataset/in_memory.py | 132 ---- src/guidellm/dataset/synthetic.py | 287 -------- src/guidellm/logger.py | 2 +- src/guidellm/preprocess/dataset.py | 7 +- src/guidellm/request/__init__.py | 18 - src/guidellm/request/loader.py | 284 -------- src/guidellm/request/request.py | 79 --- src/guidellm/request/types.py | 10 - src/guidellm/scheduler/scheduler.py | 2 +- src/guidellm/scheduler/worker_group.py | 9 +- 46 files changed, 2949 insertions(+), 2084 deletions(-) create mode 100644 src/guidellm/data/datasets.py create mode 100644 src/guidellm/data/deserializers/__init__.py create mode 100644 src/guidellm/data/deserializers/deserializer.py create mode 100644 src/guidellm/data/deserializers/file.py create mode 100644 src/guidellm/data/deserializers/huggingface.py create mode 100644 src/guidellm/data/deserializers/memory.py create mode 100644 src/guidellm/data/deserializers/synthetic.py create mode 100644 src/guidellm/data/formatters/__init__.py create mode 100644 src/guidellm/data/formatters/environment.py create mode 100644 src/guidellm/data/formatters/filters.py create mode 100644 src/guidellm/data/formatters/globals.py create mode 100644 src/guidellm/data/formatters/objects.py create mode 100644 src/guidellm/data/formatters/templates.py create mode 100644 src/guidellm/data/loaders.py create mode 100644 src/guidellm/data/objects.py create mode 100644 src/guidellm/data/preprocessors/__init__.py create mode 100644 src/guidellm/data/preprocessors/mappers.py create mode 100644 src/guidellm/data/preprocessors/objects.py delete mode 100644 src/guidellm/data/prideandprejudice.txt.gz create mode 100644 src/guidellm/data/utils.py delete mode 100644 src/guidellm/dataset/__init__.py delete mode 100644 src/guidellm/dataset/creator.py delete mode 100644 src/guidellm/dataset/entrypoints.py delete mode 100644 src/guidellm/dataset/file.py delete mode 100644 src/guidellm/dataset/hf_datasets.py delete mode 100644 src/guidellm/dataset/in_memory.py delete mode 100644 src/guidellm/dataset/synthetic.py delete mode 100644 src/guidellm/request/__init__.py delete mode 100644 src/guidellm/request/loader.py delete mode 100644 src/guidellm/request/request.py delete mode 100644 src/guidellm/request/types.py diff --git a/src/guidellm/__init__.py b/src/guidellm/__init__.py index f2206e94..dde6e937 100644 --- a/src/guidellm/__init__.py +++ b/src/guidellm/__init__.py @@ -7,6 +7,8 @@ import logging import os +from datasets.utils.logging import disable_progress_bar + with ( open(os.devnull, "w") as devnull, # noqa: PTH123 contextlib.redirect_stderr(devnull), @@ -19,6 +21,7 @@ os.environ["TOKENIZERS_PARALLELISM"] = "false" # Silence warnings for tokenizers hf_logging.set_verbosity_error() logging.getLogger("transformers").setLevel(logging.ERROR) + disable_progress_bar() from .logger import configure_logger, logger from .settings import ( diff --git a/src/guidellm/__main__.py b/src/guidellm/__main__.py index 13a748d5..82632bc8 100644 --- a/src/guidellm/__main__.py +++ b/src/guidellm/__main__.py @@ -56,6 +56,11 @@ from guidellm.benchmark.scenario import ( GenerativeTextScenario, ) +from guidellm.data import ( + GenerativeDatasetArgs, + GenerativeRequestFormatter, + GenerativeRequestType, +) from guidellm.mock_server import MockServer, MockServerConfig from guidellm.preprocess.dataset import ShortPromptStrategy, process_dataset from guidellm.scheduler import StrategyType @@ -143,6 +148,7 @@ def benchmark(): @click.option( "--data", type=str, + multiple=True, help=( "The HuggingFace dataset ID, a path to a HuggingFace dataset, " "a path to a data file csv, json, jsonl, or txt, " @@ -197,9 +203,7 @@ def benchmark(): default=None, help=( "A JSON string containing any arguments to pass to the backend as a " - "dict with **kwargs. Headers can be removed by setting their value to " - "null. For example: " - """'{"headers": {"Authorization": null, "Custom-Header": "Custom-Value"}}'""" + "dict with **kwargs." ), ) @click.option( @@ -234,19 +238,72 @@ def benchmark(): @click.option( "--data-args", default=None, - callback=cli_tools.parse_json, + callback=( + lambda _ctx, _param, value: [ + GenerativeDatasetArgs.model_validate_json(val) + if val + else GenerativeDatasetArgs() + for val in value + ] + if value + else None + ), help=( "A JSON string containing any arguments to pass to the dataset creation " "as a dict with **kwargs." ), ) +@click.option( + "--data-samples", + default=-1, + type=int, + help=( + "The number of samples to use from the dataset. If -1 (default), will use all " + "samples in the dataset." + ), +) @click.option( "--data-sampler", default=None, - type=click.Choice(["random"]), + type=click.Choice(["shuffle"]), + help="The data sampler type to use.", +) +@click.option( + "--data-request-type", + default="text_completions", + type=str, + help=( + "The type of request to create for each data sample. " + f"For example, {list(get_literal_vals(GenerativeRequestType))}." + ), +) +@click.option( + "--data-request-template", + default=None, + help=( + "A Jinja2 template string or path to a Jinja2 template file to use for " + "creating requests from the data samples. If not provided, will use a " + "default template based on the request type." + ), +) +@click.option( + "--data-request-extras", + default=None, + callback=cli_tools.parse_json, + help=("A JSON string of extra data to include with each data request."), +) +@click.option( + "--data-request-nonstreaming", + is_flag=True, + help="Set this flag to disable streaming for the data requests.", +) +@click.option( + "--dataloader_kwargs", + default=None, + callback=cli_tools.parse_json, help=( - "The data sampler type to use. 'random' will add a random shuffle on the data. " - "Defaults to None" + "A JSON string containing any arguments to pass to the dataloader constructor " + "as a dict with **kwargs." ), ) # Output configuration @@ -387,7 +444,13 @@ def run( processor, processor_args, data_args, + data_samples, data_sampler, + data_request_type, + data_request_template, + data_request_extras, + data_request_nonstreaming, + dataloader_kwargs, # Output configuration output_path, output_formats, @@ -420,7 +483,8 @@ def run( asyncio.run( benchmark_generative_text( target=target, - data=data, + data=list(data), + # Benchmark configuration profile=profile, rate=rate, random_seed=random_seed, @@ -432,7 +496,22 @@ def run( processor=processor, processor_args=processor_args, data_args=data_args, - data_sampler=data_sampler, + data_samples=data_samples, + data_column_mapper=None, # use default + data_request_formatter=GenerativeRequestFormatter( + request_type=data_request_type, + request_template=data_request_template, + request_extras=data_request_extras, + request_defaults=( + {} # disable defaults if non-streaming + if data_request_nonstreaming + else None + ), + ), + data_preprocessors=None, # no preprocessors through CLI for now + dataloader_sampler=data_sampler, + dataloader_collate_fn=None, # use default + dataloader_kwargs=dataloader_kwargs, # Output configuration output_path=output_path, output_formats=[ diff --git a/src/guidellm/backends/__init__.py b/src/guidellm/backends/__init__.py index 064722ac..4bcf5683 100644 --- a/src/guidellm/backends/__init__.py +++ b/src/guidellm/backends/__init__.py @@ -13,6 +13,7 @@ GenerationRequest, GenerationRequestTimings, GenerationResponse, + GenerationTokenStats, ) from .openai import OpenAIHTTPBackend @@ -22,5 +23,6 @@ "GenerationRequest", "GenerationRequestTimings", "GenerationResponse", + "GenerationTokenStats", "OpenAIHTTPBackend", ] diff --git a/src/guidellm/backends/backend.py b/src/guidellm/backends/backend.py index 8f91d5e7..a7d82979 100644 --- a/src/guidellm/backends/backend.py +++ b/src/guidellm/backends/backend.py @@ -115,5 +115,6 @@ def requests_limit(self) -> int | None: async def default_model(self) -> str | None: """ :return: The default model name or identifier for generation requests. + None if no default model is available. """ ... diff --git a/src/guidellm/backends/objects.py b/src/guidellm/backends/objects.py index 05280940..88d25949 100644 --- a/src/guidellm/backends/objects.py +++ b/src/guidellm/backends/objects.py @@ -6,62 +6,51 @@ implementations. """ -import uuid -from typing import Any, Literal, Optional +from __future__ import annotations + +from typing import Literal from pydantic import Field +from guidellm.data import ( + GenerationRequest, + GenerationRequestArguments, + GenerationRequestTimings, +) from guidellm.scheduler import ( - MeasuredRequestTimings, SchedulerMessagingPydanticRegistry, ) from guidellm.utils import StandardBaseModel __all__ = [ "GenerationRequest", + "GenerationRequestArguments", "GenerationRequestTimings", "GenerationResponse", + "GenerationTokenStats", ] @SchedulerMessagingPydanticRegistry.register() -class GenerationRequest(StandardBaseModel): - """Request model for backend generation operations.""" +class GenerationTokenStats(StandardBaseModel): + """Token statistics for generation requests and responses.""" - request_id: str = Field( - default_factory=lambda: str(uuid.uuid4()), - description="Unique identifier for the request.", - ) - request_type: Literal["text_completions", "chat_completions"] = Field( - default="text_completions", - description=( - "Type of request. 'text_completions' uses backend.text_completions(), " - "'chat_completions' uses backend.chat_completions()." - ), - ) - content: Any = Field( - description=( - "Request content. For text_completions: string or list of strings. " - "For chat_completions: string, list of messages, or raw content " - "(set raw_content=True in params)." - ) - ) - params: dict[str, Any] = Field( - default_factory=dict, - description=( - "Additional parameters passed to backend methods. " - "Common: max_tokens, temperature, stream." - ), + request: int | None = Field( + default=None, description="Number of tokens in the original request." ) - stats: dict[Literal["prompt_tokens"], int] = Field( - default_factory=dict, - description="Request statistics including prompt token count.", - ) - constraints: dict[Literal["output_tokens"], int] = Field( - default_factory=dict, - description="Request constraints such as maximum output tokens.", + response: int | None = Field( + default=None, description="Number of tokens in the generated response." ) + def value( + self, preference: Literal["request", "response"] | None = None + ) -> int | None: + if preference == "request": + return self.request + if preference == "response": + return self.response + return self.response if self.response is not None else self.request + @SchedulerMessagingPydanticRegistry.register() class GenerationResponse(StandardBaseModel): @@ -70,87 +59,32 @@ class GenerationResponse(StandardBaseModel): request_id: str = Field( description="Unique identifier matching the original GenerationRequest." ) - request_args: dict[str, Any] = Field( + request_args: GenerationRequestArguments = Field( description="Arguments passed to the backend for this request." ) - value: Optional[str] = Field( + text: str | None = Field( default=None, - description="Complete generated text content. None for streaming responses.", - ) - delta: Optional[str] = Field( - default=None, description="Incremental text content for streaming responses." + description="The generated response text.", ) iterations: int = Field( default=0, description="Number of generation iterations completed." ) - request_prompt_tokens: Optional[int] = Field( - default=None, description="Token count from the original request prompt." - ) - request_output_tokens: Optional[int] = Field( - default=None, - description="Expected output token count from the original request.", - ) - response_prompt_tokens: Optional[int] = Field( - default=None, description="Actual prompt token count reported by the backend." + + prompt_stats: GenerationTokenStats = Field( + default_factory=GenerationTokenStats, + description="Token statistics from the prompt.", ) - response_output_tokens: Optional[int] = Field( - default=None, description="Actual output token count reported by the backend." + output_stats: GenerationTokenStats = Field( + default_factory=GenerationTokenStats, + description="Token statistics from the generated output.", ) - @property - def prompt_tokens(self) -> Optional[int]: - """ - :return: The number of prompt tokens used in the request - (response_prompt_tokens if available, otherwise request_prompt_tokens). - """ - return self.response_prompt_tokens or self.request_prompt_tokens - - @property - def output_tokens(self) -> Optional[int]: - """ - :return: The number of output tokens generated in the response - (response_output_tokens if available, otherwise request_output_tokens). - """ - return self.response_output_tokens or self.request_output_tokens - - @property - def total_tokens(self) -> Optional[int]: - """ - :return: The total number of tokens used in the request and response. - Sum of prompt_tokens and output_tokens. - """ - if self.prompt_tokens is None or self.output_tokens is None: - return None - return self.prompt_tokens + self.output_tokens - - def preferred_prompt_tokens( - self, preferred_source: Literal["request", "response"] - ) -> Optional[int]: - if preferred_source == "request": - return self.request_prompt_tokens or self.response_prompt_tokens - else: - return self.response_prompt_tokens or self.request_prompt_tokens - - def preferred_output_tokens( - self, preferred_source: Literal["request", "response"] - ) -> Optional[int]: - if preferred_source == "request": - return self.request_output_tokens or self.response_output_tokens - else: - return self.response_output_tokens or self.request_output_tokens - - -@SchedulerMessagingPydanticRegistry.register() -@MeasuredRequestTimings.register("generation_request_timings") -class GenerationRequestTimings(MeasuredRequestTimings): - """Timing model for tracking generation request lifecycle events.""" + def total_tokens( + self, preference: Literal["request", "response"] | None = None + ) -> int | None: + prompt_tokens = self.prompt_stats.value(preference=preference) + output_tokens = self.output_stats.value(preference=preference) - timings_type: Literal["generation_request_timings"] = "generation_request_timings" - first_iteration: Optional[float] = Field( - default=None, - description="Unix timestamp when the first generation iteration began.", - ) - last_iteration: Optional[float] = Field( - default=None, - description="Unix timestamp when the last generation iteration completed.", - ) + if prompt_tokens is None and output_tokens is None: + return None + return (prompt_tokens or 0) + (output_tokens or 0) diff --git a/src/guidellm/backends/openai.py b/src/guidellm/backends/openai.py index ce83076f..22394afe 100644 --- a/src/guidellm/backends/openai.py +++ b/src/guidellm/backends/openai.py @@ -10,17 +10,15 @@ OpenAIHTTPBackend: HTTP backend for OpenAI-compatible API servers. """ -import base64 -import contextlib -import copy +from __future__ import annotations + +import asyncio import json import time from collections.abc import AsyncIterator -from pathlib import Path -from typing import Any, ClassVar, Optional, Union +from typing import Any, cast import httpx -from PIL import Image from pydantic import dataclasses from guidellm.backends.backend import Backend @@ -28,9 +26,18 @@ GenerationRequest, GenerationRequestTimings, GenerationResponse, + GenerationTokenStats, ) from guidellm.scheduler import ScheduledRequestInfo +try: + import orjson + + HAS_ORJSON = True +except ImportError: + orjson = None + HAS_ORJSON = False + __all__ = ["OpenAIHTTPBackend", "UsageStats"] @@ -38,8 +45,18 @@ class UsageStats: """Token usage statistics for generation requests.""" - prompt_tokens: Optional[int] = None - output_tokens: Optional[int] = None + prompt_tokens: int | None = None + output_tokens: int | None = None + + +open_ai_paths: dict[str, str] = { + "health": "health", + "models": "v1/models", + "text_completions": "v1/completions", + "chat_completions": "v1/chat/completions", + "audio_transcriptions": "v1/audio/transcriptions", + "audio_translations": "v1/audio/translations", +} @Backend.register("openai_http") @@ -66,78 +83,34 @@ class OpenAIHTTPBackend(Backend): await backend.process_shutdown() """ - HEALTH_PATH: ClassVar[str] = "/health" - MODELS_PATH: ClassVar[str] = "/v1/models" - TEXT_COMPLETIONS_PATH: ClassVar[str] = "/v1/completions" - CHAT_COMPLETIONS_PATH: ClassVar[str] = "/v1/chat/completions" - - MODELS_KEY: ClassVar[str] = "models" - TEXT_COMPLETIONS_KEY: ClassVar[str] = "text_completions" - CHAT_COMPLETIONS_KEY: ClassVar[str] = "chat_completions" - def __init__( self, target: str, - model: Optional[str] = None, - api_key: Optional[str] = None, - organization: Optional[str] = None, - project: Optional[str] = None, + model: str | None = None, timeout: float = 60.0, http2: bool = True, follow_redirects: bool = True, - max_output_tokens: Optional[int] = None, - stream_response: bool = True, - extra_query: Optional[dict] = None, - extra_body: Optional[dict] = None, - remove_from_body: Optional[list[str]] = None, - headers: Optional[dict] = None, verify: bool = False, + validate_backend: bool | str | dict[str, Any] = True, ): - """ - Initialize OpenAI HTTP backend. - - :param target: Target URL for the OpenAI server (e.g., "http://localhost:8000"). - :param model: Model to use for requests. If None, uses first available model. - :param api_key: API key for authentication. Adds Authorization header - if provided. - :param organization: Organization ID. Adds OpenAI-Organization header - if provided. - :param project: Project ID. Adds OpenAI-Project header if provided. - :param timeout: Request timeout in seconds. Defaults to 60 seconds. - :param http2: Whether to use HTTP/2. Defaults to True. - :param follow_redirects: Whether to follow redirects. Default True. - :param max_output_tokens: Maximum tokens for completions. If None, none is set. - :param stream_response: Whether to stream responses by default. Can be - overridden per request. Defaults to True. - :param extra_query: Additional query parameters. Both general and - endpoint-specific with type keys supported. - :param extra_body: Additional body parameters. Both general and - endpoint-specific with type keys supported. - :param remove_from_body: Parameter names to remove from request bodies. - :param headers: Additional HTTP headers. - :param verify: Whether to verify SSL certificates. Default False. - """ super().__init__(type_="openai_http") # Request Values self.target = target.rstrip("/").removesuffix("/v1") self.model = model - self.headers = self._build_headers(api_key, organization, project, headers) # Store configuration self.timeout = timeout self.http2 = http2 self.follow_redirects = follow_redirects self.verify = verify - self.max_output_tokens = max_output_tokens - self.stream_response = stream_response - self.extra_query = extra_query or {} - self.extra_body = extra_body or {} - self.remove_from_body = remove_from_body or [] + self.validate_backend: dict[str, Any] | None = self._resolve_validate_kwargs( + validate_backend + ) # Runtime state self._in_process = False - self._async_client: Optional[httpx.AsyncClient] = None + self._async_client: httpx.AsyncClient | None = None @property def info(self) -> dict[str, Any]: @@ -147,20 +120,12 @@ def info(self) -> dict[str, Any]: return { "target": self.target, "model": self.model, - "headers": self.headers, "timeout": self.timeout, "http2": self.http2, "follow_redirects": self.follow_redirects, "verify": self.verify, - "max_output_tokens": self.max_output_tokens, - "stream_response": self.stream_response, - "extra_query": self.extra_query, - "extra_body": self.extra_body, - "remove_from_body": self.remove_from_body, - "health_path": self.HEALTH_PATH, - "models_path": self.MODELS_PATH, - "text_completions_path": self.TEXT_COMPLETIONS_PATH, - "chat_completions_path": self.CHAT_COMPLETIONS_PATH, + "openai_paths": open_ai_paths, + "validate_backend": self.validate_backend, } async def process_startup(self): @@ -206,45 +171,17 @@ async def validate(self): """ self._check_in_process() - if self.model: - with contextlib.suppress(httpx.TimeoutException, httpx.HTTPStatusError): - # Model is set, use /health endpoint as first check - target = f"{self.target}{self.HEALTH_PATH}" - headers = self._get_headers() - response = await self._async_client.get(target, headers=headers) # type: ignore [union-attr] - response.raise_for_status() - - return - - with contextlib.suppress(httpx.TimeoutException, httpx.HTTPStatusError): - # Check if models endpoint is available next - models = await self.available_models() - if models and not self.model: - self.model = models[0] - elif not self.model: - raise RuntimeError( - "No model available and could not set a default model " - "from the server's available models." - ) - + if not self.validate_backend: return - with contextlib.suppress(httpx.TimeoutException, httpx.HTTPStatusError): - # Last check, fall back on dummy request to text completions - async for _, __ in self.text_completions( - prompt="Validate backend", - request_id="validate", - output_token_count=1, - stream_response=False, - ): - pass - - return - - raise RuntimeError( - "Backend validation failed. Could not connect to the server or " - "validate the backend configuration." - ) + try: + response = await self._async_client.request(**self.validate_backend) + response.raise_for_status() + except Exception as exc: + raise RuntimeError( + "Backend validation request failed. Could not connect to the server " + "or validate the backend configuration." + ) from exc async def available_models(self) -> list[str]: """ @@ -256,15 +193,13 @@ async def available_models(self) -> list[str]: """ self._check_in_process() - target = f"{self.target}{self.MODELS_PATH}" - headers = self._get_headers() - params = self._get_params(self.MODELS_KEY) - response = await self._async_client.get(target, headers=headers, params=params) # type: ignore [union-attr] + target = f"{self.target}/{open_ai_paths['models']}" + response = await self._async_client.get(target) response.raise_for_status() return [item["id"] for item in response.json()["data"]] - async def default_model(self) -> Optional[str]: + async def default_model(self) -> str | None: """ Get the default model for this backend. @@ -276,11 +211,11 @@ async def default_model(self) -> Optional[str]: models = await self.available_models() return models[0] if models else None - async def resolve( + async def resolve( # noqa: C901 self, request: GenerationRequest, request_info: ScheduledRequestInfo, - history: Optional[list[tuple[GenerationRequest, GenerationResponse]]] = None, + history: list[tuple[GenerationRequest, GenerationResponse]] | None = None, ) -> AsyncIterator[tuple[GenerationResponse, ScheduledRequestInfo]]: """ Process a generation request and yield progressive responses. @@ -300,350 +235,207 @@ async def resolve( "Multi-turn requests with conversation history are not yet supported" ) - response = GenerationResponse( - request_id=request.request_id, - request_args={ - "request_type": request.request_type, - "output_token_count": request.constraints.get("output_tokens"), - **request.params, - }, - value="", - request_prompt_tokens=request.stats.get("prompt_tokens"), - request_output_tokens=request.constraints.get("output_tokens"), - ) request_info.request_timings = GenerationRequestTimings() - request_info.request_timings.request_start = time.time() - - completion_method = ( - self.text_completions - if request.request_type == "text_completions" - else self.chat_completions - ) - completion_kwargs = ( - { - "prompt": request.content, - "request_id": request.request_id, - "output_token_count": request.constraints.get("output_tokens"), - "stream_response": request.params.get("stream", self.stream_response), - **request.params, - } - if request.request_type == "text_completions" - else { - "content": request.content, - "request_id": request.request_id, - "output_token_count": request.constraints.get("output_tokens"), - "stream_response": request.params.get("stream", self.stream_response), - **request.params, - } + request.arguments.url = ( + request.arguments.url or f"{self.target}/{request.arguments.path}" + if request.arguments.path is not None + else f"{self.target}/{open_ai_paths[request.request_type]}" ) + request_info.request_timings.request_start = time.time() - async for delta, usage_stats in completion_method(**completion_kwargs): - if request_info.request_timings.request_start is None: - request_info.request_timings.request_start = time.time() - - if delta is not None: - if request_info.request_timings.first_iteration is None: - request_info.request_timings.first_iteration = time.time() - response.value += delta # type: ignore [operator] - response.delta = delta - request_info.request_timings.last_iteration = time.time() - response.iterations += 1 - - if usage_stats is not None: - request_info.request_timings.request_end = time.time() - response.response_output_tokens = usage_stats.output_tokens - response.response_prompt_tokens = usage_stats.prompt_tokens - - yield response, request_info - - if request_info.request_timings.request_end is None: - request_info.request_timings.request_end = time.time() - response.delta = None - yield response, request_info - - async def text_completions( - self, - prompt: Union[str, list[str]], - request_id: Optional[str], # noqa: ARG002 - output_token_count: Optional[int] = None, - stream_response: bool = True, - **kwargs, - ) -> AsyncIterator[tuple[Optional[str], Optional[UsageStats]]]: - """ - Generate text completions using the /v1/completions endpoint. - - :param prompt: Text prompt(s) for completion. Single string or list. - :param request_id: Request identifier for tracking. - :param output_token_count: Maximum tokens to generate. Overrides default - if specified. - :param stream_response: Whether to stream response progressively. - :param kwargs: Additional request parameters (temperature, top_p, etc.). - :yields: Tuples of (generated_text, usage_stats). First yield is (None, None). - :raises RuntimeError: If backend is not initialized. - :raises HTTPError: If API request fails. - """ - self._check_in_process() - target = f"{self.target}{self.TEXT_COMPLETIONS_PATH}" - headers = self._get_headers() - params = self._get_params(self.TEXT_COMPLETIONS_KEY) - body = self._get_body( - endpoint_type=self.TEXT_COMPLETIONS_KEY, - request_kwargs=kwargs, - max_output_tokens=output_token_count, - prompt=prompt, - ) - yield None, None # Initial yield for async iterator to signal start - - if not stream_response: - response = await self._async_client.post( # type: ignore [union-attr] - target, - headers=headers, - params=params, - json=body, + if not request.arguments.stream: + response = await self._async_client.request( + request.arguments.method or "POST", + request.arguments.url, + content=request.arguments.content_body, + files=request.arguments.files, + json=request.arguments.json_body, + params=request.arguments.params, + headers=request.arguments.headers, ) response.raise_for_status() data = response.json() + prompt_stats, output_stats = self._extract_response_stats(data, request) + request_info.request_timings.request_end = time.time() + yield ( - self._get_completions_text_content(data), - self._get_completions_usage_stats(data), + GenerationResponse( + request_id=request.request_id, + request_args=request.arguments, + text=self._extract_response_text(data), + iterations=0, + prompt_stats=prompt_stats, + output_stats=output_stats, + ), + request_info, ) return - body.update({"stream": True, "stream_options": {"include_usage": True}}) - async with self._async_client.stream( # type: ignore [union-attr] - "POST", - target, - headers=headers, - params=params, - json=body, - ) as stream: - stream.raise_for_status() - async for line in stream.aiter_lines(): - if not line or not line.strip().startswith("data:"): - continue - if line.strip() == "data: [DONE]": - break - data = json.loads(line.strip()[len("data: ") :]) - yield ( - self._get_completions_text_content(data), - self._get_completions_usage_stats(data), - ) - - async def chat_completions( - self, - content: Union[ - str, - list[Union[str, dict[str, Union[str, dict[str, str]]], Path, Image.Image]], - Any, - ], - request_id: Optional[str] = None, # noqa: ARG002 - output_token_count: Optional[int] = None, - raw_content: bool = False, - stream_response: bool = True, - **kwargs, - ) -> AsyncIterator[tuple[Optional[str], Optional[UsageStats]]]: - """ - Generate chat completions using the /v1/chat/completions endpoint. - - Supports multimodal inputs including text and images with message formatting. - - :param content: Chat content - string, list of mixed content, or raw content - when raw_content=True. - :param request_id: Request identifier (currently unused). - :param output_token_count: Maximum tokens to generate. Overrides default - if specified. - :param raw_content: If True, passes content directly without formatting. - :param stream_response: Whether to stream response progressively. - :param kwargs: Additional request parameters (temperature, top_p, tools, etc.). - :yields: Tuples of (generated_text, usage_stats). First yield is (None, None). - :raises RuntimeError: If backend is not initialized. - :raises HTTPError: If API request fails. - """ - self._check_in_process() - target = f"{self.target}{self.CHAT_COMPLETIONS_PATH}" - headers = self._get_headers() - params = self._get_params(self.CHAT_COMPLETIONS_KEY) - body = self._get_body( - endpoint_type=self.CHAT_COMPLETIONS_KEY, - request_kwargs=kwargs, - max_output_tokens=output_token_count, - messages=self._get_chat_messages(content) if not raw_content else content, - **kwargs, - ) - yield None, None # Initial yield for async iterator to signal start + deltas = [] + prompt_stats = None + output_stats = None + end_reached = False + + try: + async with self._async_client.stream( + request.arguments.method or "POST", + request.arguments.url, + content=request.arguments.content_body, + files=request.arguments.files, + json=request.arguments.json_body, + params=request.arguments.params, + headers=request.arguments.headers, + ) as stream: + stream.raise_for_status() + buffer = bytearray() + + async for chunk in stream.aiter_bytes(): + if not chunk or end_reached: + continue + buffer.extend(chunk) + + while (start := buffer.find(b"data:")) != -1 and ( + end := buffer.find(b"\n", start) + ) != -1: + line = buffer[start + len(b"data:") : end].strip() + buffer = buffer[end + 1 :] + + if not line: + continue + + if line == b"[DONE]": + if request_info.request_timings.request_end is None: + request_info.request_timings.request_end = time.time() + end_reached = True + break + + data = ( + json.loads(line) if not HAS_ORJSON else orjson.loads(line) + ) + + if "usage" in data and data["usage"] is not None: + request_info.request_timings.request_end = time.time() + prompt_stats, output_stats = self._extract_response_stats( + data, request + ) + else: + if request_info.request_timings.first_iteration is None: + request_info.request_timings.first_iteration = ( + time.time() + ) + request_info.request_timings.last_iteration = time.time() + deltas.append(self._extract_response_text(data)) - if not stream_response: - response = await self._async_client.post( # type: ignore [union-attr] - target, headers=headers, params=params, json=body - ) - response.raise_for_status() - data = response.json() yield ( - self._get_completions_text_content(data), - self._get_completions_usage_stats(data), + GenerationResponse( + request_id=request.request_id, + request_args=request.arguments, + text="".join(deltas) if deltas else None, + iterations=len(deltas), + prompt_stats=prompt_stats or GenerationTokenStats(), + output_stats=output_stats or GenerationTokenStats(), + ), + request_info, ) - return - - body.update({"stream": True, "stream_options": {"include_usage": True}}) - async with self._async_client.stream( # type: ignore [union-attr] - "POST", target, headers=headers, params=params, json=body - ) as stream: - stream.raise_for_status() - async for line in stream.aiter_lines(): - if not line or not line.strip().startswith("data:"): - continue - if line.strip() == "data: [DONE]": - break - data = json.loads(line.strip()[len("data: ") :]) - yield ( - self._get_completions_text_content(data), - self._get_completions_usage_stats(data), - ) - - def _build_headers( - self, - api_key: Optional[str], - organization: Optional[str], - project: Optional[str], - user_headers: Optional[dict], - ) -> dict[str, str]: - headers = {} - - if api_key: - headers["Authorization"] = ( - f"Bearer {api_key}" if not api_key.startswith("Bearer") else api_key + except asyncio.CancelledError as err: + yield ( # Ensure we yield what we have so far before stopping + GenerationResponse( + request_id=request.request_id, + request_args=request.arguments, + text="".join(deltas) if deltas else None, + iterations=len(deltas), + prompt_stats=prompt_stats or GenerationTokenStats(), + output_stats=output_stats or GenerationTokenStats(), + ), + request_info, ) - if organization: - headers["OpenAI-Organization"] = organization - if project: - headers["OpenAI-Project"] = project - if user_headers: - headers.update(user_headers) + raise err - return {key: val for key, val in headers.items() if val is not None} + def _extract_response_text(self, data: dict) -> str: + if not data: + return None - def _check_in_process(self): - if not self._in_process or self._async_client is None: - raise RuntimeError( - "Backend not started up for process, cannot process requests." - ) + object_type = data.get("object") or data.get("type") - def _get_headers(self) -> dict[str, str]: - return { - "Content-Type": "application/json", - **self.headers, - } + if object_type == "text_completion": + return data.get("choices", [{}])[0].get("text", "") - def _get_params(self, endpoint_type: str) -> dict[str, str]: - if endpoint_type in self.extra_query: - return copy.deepcopy(self.extra_query[endpoint_type]) - return copy.deepcopy(self.extra_query) + if object_type == "chat.completion": + return data.get("choices", [{}])[0].get("message", {}).get("content", "") - def _get_chat_messages( - self, - content: Union[ - str, - list[Union[str, dict[str, Union[str, dict[str, str]]], Path, Image.Image]], - Any, - ], - ) -> list[dict[str, Any]]: - if isinstance(content, str): - return [{"role": "user", "content": content}] - - if not isinstance(content, list): - raise ValueError(f"Unsupported content type: {type(content)}") - - resolved_content = [] - for item in content: - if isinstance(item, dict): - resolved_content.append(item) - elif isinstance(item, str): - resolved_content.append({"type": "text", "text": item}) - elif isinstance(item, (Image.Image, Path)): - resolved_content.append(self._get_chat_message_media_item(item)) - else: - raise ValueError(f"Unsupported content item type: {type(item)}") - - return [{"role": "user", "content": resolved_content}] - - def _get_chat_message_media_item( - self, item: Union[Path, Image.Image] - ) -> dict[str, Any]: - if isinstance(item, Image.Image): - encoded = base64.b64encode(item.tobytes()).decode("utf-8") - return { - "type": "image", - "image": {"url": f"data:image/jpeg;base64,{encoded}"}, - } + if object_type == "chat.completion.chunk": + return data.get("choices", [{}])[0].get("delta", {}).get("content", "") - # Handle file paths - suffix = item.suffix.lower() - if suffix in [".jpg", ".jpeg"]: - image = Image.open(item) - encoded = base64.b64encode(image.tobytes()).decode("utf-8") - return { - "type": "image", - "image": {"url": f"data:image/jpeg;base64,{encoded}"}, - } - elif suffix == ".wav": - encoded = base64.b64encode(item.read_bytes()).decode("utf-8") - return { - "type": "input_audio", - "input_audio": {"data": encoded, "format": "wav"}, - } - else: - raise ValueError(f"Unsupported file type: {suffix}") + if "text" in data: + return data.get("text", "") - def _get_body( - self, - endpoint_type: str, - request_kwargs: Optional[dict[str, Any]], - max_output_tokens: Optional[int] = None, - **kwargs, - ) -> dict[str, Any]: - # Start with endpoint-specific extra body parameters - extra_body: dict = self.extra_body.get(endpoint_type, self.extra_body) - - body = copy.deepcopy(extra_body) - body.update(request_kwargs or {}) - body.update(kwargs) - body["model"] = self.model - - # Handle token limits - max_tokens = max_output_tokens or self.max_output_tokens - if max_tokens is not None: - body.update( - { - "max_tokens": max_tokens, - "max_completion_tokens": max_tokens, - } - ) - # Set stop conditions only for request-level limits - if max_output_tokens: - body.update({"stop": None, "ignore_eos": True}) + if "delta" in data: + return data.get("delta", "") - if self.remove_from_body: - for key in self.remove_from_body: - body.pop(key, None) + raise ValueError(f"Unsupported response format: {data}") - return {key: val for key, val in body.items() if val is not None} + def _extract_response_stats( + self, data: dict, request: GenerationRequest + ) -> tuple[GenerationTokenStats, GenerationTokenStats]: + prompt_stats = GenerationTokenStats() + output_stats = GenerationTokenStats() - def _get_completions_text_content(self, data: dict) -> Optional[str]: - if not data.get("choices"): - return None + if not data or not (usage := cast("dict", data.get("usage"))): + return prompt_stats, output_stats - choice: dict = data["choices"][0] - return ( - choice.get("text") - or choice.get("delta", {}).get("content") - or choice.get("message", {}).get("content") + prompt_stats.request = request.stats.get("prompt_tokens") + prompt_stats.response = usage.get("prompt_tokens", usage.get("input_tokens")) + prompt_token_details = usage.get( + "prompt_tokens_details", usage.get("input_tokens_details") + ) + if prompt_token_details: + for key, val in prompt_token_details.items(): + setattr(prompt_stats, key, val) + + output_stats.request = request.stats.get("output_tokens") + output_stats.response = usage.get( + "completion_tokens", usage.get("output_tokens") + ) + output_token_details = usage.get( + "completion_tokens_details", usage.get("output_tokens_details") ) + if output_token_details: + for key, val in output_token_details.items(): + setattr(output_stats, key, val) - def _get_completions_usage_stats(self, data: dict) -> Optional[UsageStats]: - if not data.get("usage"): + return prompt_stats, output_stats + + def _resolve_validate_kwargs( + self, validate_backend: bool | str | dict[str, Any] + ) -> dict[str, Any] | None: + if not (validate_kwargs := validate_backend): return None - return UsageStats( - prompt_tokens=data["usage"].get("prompt_tokens"), - output_tokens=data["usage"].get("completion_tokens"), - ) + if validate_kwargs is True: + validate_kwargs = "health" + + if isinstance(validate_kwargs, str) and validate_kwargs in open_ai_paths: + validate_kwargs = f"{self.target}/{open_ai_paths[validate_kwargs]}" + + if isinstance(validate_kwargs, str): + validate_kwargs = { + "method": "GET", + "url": validate_kwargs, + } + + if not isinstance(validate_kwargs, dict) or "url" not in validate_kwargs: + raise ValueError( + "validate_backend must be a boolean, string, or dictionary and contain " + f"a target URL. Got: {validate_kwargs}" + ) + + if "method" not in validate_kwargs: + validate_kwargs["method"] = "GET" + + return validate_kwargs + + def _check_in_process(self): + if not self._in_process or self._async_client is None: + raise RuntimeError( + "Backend not started up for process, cannot process requests." + ) diff --git a/src/guidellm/benchmark/aggregator.py b/src/guidellm/benchmark/aggregator.py index e965c482..3040ad36 100644 --- a/src/guidellm/benchmark/aggregator.py +++ b/src/guidellm/benchmark/aggregator.py @@ -532,116 +532,117 @@ def __call__( :return: Updated aggregation state for progress reporting. """ _ = (request,) # unused - if request_info.status not in {"completed", "errored", "cancelled"}: - # Only compile progress stats for processed requests - return None - state["updated_generative_stats"] = True - start_time = scheduler_state.start_time - end_time = ( - safe_getattr(request_info.request_timings, "request_end") - or request_info.scheduler_timings.resolve_end + # Request Concurrency + state.set_metric( + key="requests", + value=scheduler_state.processing_requests, + type_="avg", ) - duration = end_time - start_time if end_time else None - - for prefix in (request_info.status, None): - requests_count = ( - scheduler_state.processed_requests - if prefix is None - else scheduler_state.successful_requests - if request_info.status == "completed" - else scheduler_state.cancelled_requests - if request_info.status == "cancelled" - else scheduler_state.errored_requests + + if request_info.status in {"completed", "errored", "cancelled"}: + # Only compile progress stats for processed requests + state["updated_generative_stats"] = True + start_time = scheduler_state.start_time + end_time = ( + safe_getattr(request_info.request_timings, "request_end") + or request_info.scheduler_timings.resolve_end ) + duration = end_time - start_time if end_time else None + + for prefix in (request_info.status, None): + requests_count = ( + scheduler_state.processed_requests + if prefix is None + else scheduler_state.successful_requests + if request_info.status == "completed" + else scheduler_state.cancelled_requests + if request_info.status == "cancelled" + else scheduler_state.errored_requests + ) - # Requests per Second - if duration is not None: - state.set_metric( - key="requests", - value=safe_divide(requests_count, duration), - type_="rate", + # Requests per Second + if duration is not None: + state.set_metric( + key="requests", + value=safe_divide(requests_count, duration), + type_="rate", + prefix=prefix, + ) + + # Request Latency + state.add_metric( + key="request_latency", + value=safe_getattr(request_info.request_timings, "request_end"), + start_val=safe_getattr( + request_info.request_timings, "request_start" + ), prefix=prefix, ) - # Request Concurrency - state.set_metric( - key="requests", - value=scheduler_state.processing_requests, - type_="avg", - prefix=prefix, - ) - - # Request Latency - state.add_metric( - key="request_latency", - value=safe_getattr(request_info.request_timings, "request_end"), - start_val=safe_getattr(request_info.request_timings, "request_start"), - prefix=prefix, - ) - - # Time to First Token - state.add_metric( - key="time_to_first_token", - value=safe_getattr(request_info.request_timings, "first_iteration"), - start_val=safe_getattr(request_info.request_timings, "request_start"), - prefix=prefix, - ) + # Time to First Token + state.add_metric( + key="time_to_first_token", + value=safe_getattr(request_info.request_timings, "first_iteration"), + start_val=safe_getattr( + request_info.request_timings, "request_start" + ), + prefix=prefix, + ) - output_tokens = safe_getattr(response, "output_tokens") - prompt_tokens = safe_getattr(response, "prompt_tokens") + output_tokens = response.output_stats.value() if response else None + prompt_tokens = response.prompt_stats.value() if response else None + total_tokens = response.total_tokens() if response else None - # Inter Token Latency - state.add_metric( - key="inter_token_latency", - value=safe_getattr(request_info.request_timings, "last_iteration"), - start_val=safe_getattr(request_info.request_timings, "first_iteration"), - count=( - output_tokens - 1 if output_tokens and output_tokens > 1 else None - ), - prefix=prefix, - ) + # Inter Token Latency + state.add_metric( + key="inter_token_latency", + value=safe_getattr(request_info.request_timings, "last_iteration"), + start_val=safe_getattr( + request_info.request_timings, "first_iteration" + ), + count=( + output_tokens - 1 + if output_tokens and output_tokens > 1 + else None + ), + prefix=prefix, + ) - # Time per Output Token - state.add_metric( - key="time_per_output_token", - value=safe_getattr(request_info.request_timings, "request_start"), - start_val=safe_getattr(request_info.request_timings, "last_iteration"), - count=output_tokens, - prefix=prefix, - ) + # Time per Output Token + state.add_metric( + key="time_per_output_token", + value=safe_getattr(request_info.request_timings, "request_start"), + start_val=safe_getattr( + request_info.request_timings, "last_iteration" + ), + count=output_tokens, + prefix=prefix, + ) - # Prompt Tokens - state.add_metric( - key="prompt_tokens", - value=prompt_tokens, - duration=duration, - prefix=prefix, - ) + # Prompt Tokens + state.add_metric( + key="prompt_tokens", + value=prompt_tokens, + duration=duration, + prefix=prefix, + ) - # Output Tokens - state.add_metric( - key="output_tokens", - value=output_tokens, - duration=duration, - prefix=prefix, - ) + # Output Tokens + state.add_metric( + key="output_tokens", + value=output_tokens, + duration=duration, + prefix=prefix, + ) - # Total Tokens - state.add_metric( - key="total_tokens", - value=( - prompt_tokens + output_tokens - if all_defined(prompt_tokens, output_tokens) - else prompt_tokens - if all_defined(prompt_tokens) - else output_tokens - if all_defined(output_tokens) - else None - ), - duration=duration, - prefix=prefix, - ) + # Total Tokens + state.add_metric( + key="total_tokens", + value=total_tokens, + duration=duration, + prefix=prefix, + ) return state @@ -929,29 +930,29 @@ def _is_in_cooldown( @classmethod def _create_generative_request_stats( cls, - response: GenerationResponse, + response: GenerationResponse | None, request: GenerationRequest, request_info: ScheduledRequestInfo, ) -> GenerativeRequestStats: - prompt_tokens = response.preferred_prompt_tokens( - settings.preferred_prompt_tokens_source - ) - output_tokens = response.preferred_output_tokens( - settings.preferred_output_tokens_source - ) - return GenerativeRequestStats( request_id=request.request_id, request_type=request.request_type, - prompt=str(request.content), - request_args=response.request_args, - output=response.value, - iterations=response.iterations, - prompt_tokens=prompt_tokens, - output_tokens=output_tokens, + request_args=request.arguments, + output=response.text if response else None, + iterations=response.iterations if response else 0, + prompt_tokens=( + response.prompt_stats.value(settings.preferred_prompt_tokens_source) + if response + else None + ), + output_tokens=( + response.output_stats.value(settings.preferred_output_tokens_source) + if response + else None + ), total_tokens=( - prompt_tokens + output_tokens - if prompt_tokens is not None and output_tokens is not None + response.total_tokens(settings.preferred_output_tokens_source) + if response else None ), scheduler_info=request_info, diff --git a/src/guidellm/benchmark/entrypoints.py b/src/guidellm/benchmark/entrypoints.py index 828402d8..23bc985a 100644 --- a/src/guidellm/benchmark/entrypoints.py +++ b/src/guidellm/benchmark/entrypoints.py @@ -1,11 +1,11 @@ from __future__ import annotations -from collections.abc import Iterable from pathlib import Path from typing import Any, Literal -from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict +from torch.utils.data import Sampler from transformers import ( # type: ignore[import] + AutoTokenizer, PreTrainedTokenizerBase, ) @@ -26,6 +26,7 @@ from guidellm.benchmark.benchmarker import Benchmarker from guidellm.benchmark.objects import GenerativeBenchmark, GenerativeBenchmarksReport from guidellm.benchmark.output import ( + GenerativeBenchmarkerConsole, GenerativeBenchmarkerOutput, ) from guidellm.benchmark.profile import Profile, ProfileType @@ -33,8 +34,14 @@ BenchmarkerProgress, BenchmarkerProgressGroup, ) -from guidellm.benchmark.scenario import GenerativeTextScenario, Scenario -from guidellm.request import GenerativeRequestLoader +from guidellm.data import ( + DatasetPreprocessor, + GenerativeColumnMapper, + GenerativeDataLoader, + GenerativeRequestCollator, + GenerativeRequestFormatter, +) +from guidellm.data.objects import GenerativeDatasetArgs from guidellm.scheduler import ( ConstraintInitializer, NonDistributedEnvironment, @@ -44,7 +51,6 @@ __all__ = [ "benchmark_generative_text", - "benchmark_with_scenario", "reimport_benchmarks_report", ] @@ -52,113 +58,13 @@ _CURRENT_WORKING_DIR = Path.cwd() -# Data types - -DataType = ( - Iterable[str] - | Iterable[dict[str, Any]] - | Dataset - | DatasetDict - | IterableDataset - | IterableDatasetDict - | str - | Path -) - -OutputFormatType = ( - tuple[str, ...] - | list[str] - | dict[str, str | dict[str, Any] | GenerativeBenchmarkerOutput] - | None -) - - -# Helper functions - -async def initialize_backend( - backend: BackendType | Backend, - target: str, - model: str | None, - backend_kwargs: dict[str, Any] | None, -) -> Backend: - backend = ( - Backend.create( - backend, target=target, model=model, **(backend_kwargs or {}) - ) - if not isinstance(backend, Backend) - else backend - ) - await backend.process_startup() - await backend.validate() - return backend - - -async def resolve_profile( - constraint_inputs: dict[str, int | float], - profile: Profile | str | None, - rate: list[float] | None, - random_seed: int, - constraints: dict[str, ConstraintInitializer | Any], -): - for key, val in constraint_inputs.items(): - if val is not None: - constraints[key] = val - if not isinstance(profile, Profile): - if isinstance(profile, str): - profile = Profile.create( - rate_type=profile, - rate=rate, - random_seed=random_seed, - constraints={**constraints}, - ) - else: - raise ValueError(f"Expected string for profile; got {type(profile)}") - - elif constraints: - raise ValueError( - "Constraints must be empty when providing a Profile instance. " - f"Provided constraints: {constraints} ; provided profile: {profile}" - ) - return profile - -async def resolve_output_formats( - output_formats: OutputFormatType, - output_path: str | Path | None, -) -> dict[str, GenerativeBenchmarkerOutput]: - output_formats = GenerativeBenchmarkerOutput.resolve( - output_formats=(output_formats or {}), output_path=output_path - ) - return output_formats - -async def finalize_outputs( - report: GenerativeBenchmarksReport, - resolved_output_formats: dict[str, GenerativeBenchmarkerOutput] -): - output_format_results = {} - for key, output in resolved_output_formats.items(): - output_result = await output.finalize(report) - output_format_results[key] = output_result - return output_format_results - - -# Complete entrypoints - -async def benchmark_with_scenario(scenario: Scenario, **kwargs): - """ - Run a benchmark using a scenario and specify any extra arguments - """ - - if isinstance(scenario, GenerativeTextScenario): - return await benchmark_generative_text(**vars(scenario), **kwargs) - else: - raise ValueError(f"Unsupported Scenario type {type(scenario)}") - - # @validate_call(config={"arbitrary_types_allowed": True}) -async def benchmark_generative_text( # noqa: C901 +async def benchmark_generative_text( # noqa: C901, PLR0915 + # Required target: str, - data: DataType, - profile: StrategyType | ProfileType | Profile, + data: list[Any], + # Benchmark configuration + profile: StrategyType | ProfileType | Profile = "sweep", rate: float | list[float] | None = None, random_seed: int = 42, # Backend configuration @@ -168,11 +74,22 @@ async def benchmark_generative_text( # noqa: C901 # Data configuration processor: str | Path | PreTrainedTokenizerBase | None = None, processor_args: dict[str, Any] | None = None, - data_args: dict[str, Any] | None = None, - data_sampler: Literal["random"] | None = None, + data_args: list[GenerativeDatasetArgs] | None = None, + data_samples: int = -1, + data_column_mapper: GenerativeColumnMapper | None = None, + data_preprocessors: list[DatasetPreprocessor] | None = None, + data_request_formatter: GenerativeRequestFormatter | None = None, + dataloader_sampler: Sampler[int] | Literal["shuffle"] | None = None, + dataloader_collate_fn: GenerativeRequestCollator | None = None, + dataloader_kwargs: dict[str, Any] | None = None, # Output configuration output_path: str | Path | None = _CURRENT_WORKING_DIR, - output_formats: OutputFormatType = ("console", "json", "html", "csv"), + output_formats: ( + tuple[str, ...] + | list[str] + | dict[str, str | dict[str, Any] | GenerativeBenchmarkerOutput] + | None + ) = ("console", "json", "html", "csv"), # Updates configuration progress: tuple[str, ...] | list[str] | list[BenchmarkerProgress] | None = None, print_updates: bool = False, @@ -196,7 +113,16 @@ async def benchmark_generative_text( # noqa: C901 with console.print_update_step( title=f"Initializing backend {backend}" ) as console_step: - backend = await initialize_backend(backend, target, model, backend_kwargs) + backend = ( + Backend.create( + backend, target=target, model=model, **(backend_kwargs or {}) + ) + if not isinstance(backend, Backend) + else backend + ) + console_step.update(f"{backend.__class__.__name__} backend initialized") + await backend.process_startup() + await backend.validate() console_step.finish( title=f"{backend.__class__.__name__} backend initialized", details=backend.info, @@ -236,19 +162,36 @@ async def benchmark_generative_text( # noqa: C901 with console.print_update_step( title=f"Initializing request loader from {data}" ) as console_step: - request_loader = GenerativeRequestLoader( + + def processor_factory() -> PreTrainedTokenizerBase: + nonlocal processor + if isinstance(processor, PreTrainedTokenizerBase): + return processor + else: + processor = AutoTokenizer.from_pretrained( + processor, + **(processor_args or {}), + ) + return processor + + request_loader = GenerativeDataLoader( data=data, data_args=data_args, - processor=processor, - processor_args=processor_args, - shuffle=data_sampler == "random", + data_samples=data_samples, + processor_factory=processor_factory, + column_mapper=data_column_mapper or GenerativeColumnMapper(), + preprocessors=data_preprocessors or [], + request_formatter=data_request_formatter or GenerativeRequestFormatter(), + sampler=dataloader_sampler, + collate_fn=dataloader_collate_fn, random_seed=random_seed, + **(dataloader_kwargs or {}), ) - unique_requests = request_loader.num_unique_items(raise_err=False) console_step.finish( title=( - f"Request loader initialized with {unique_requests} unique requests " - f"from {data}" + f"Request loader initialized with " + f"{data_samples if data_samples > 0 else 'inf'} " + f"unique requests from {data}" ), details=InfoMixin.extract_from_obj(request_loader), status_level="success", @@ -257,19 +200,27 @@ async def benchmark_generative_text( # noqa: C901 with console.print_update_step( title=f"Resolving profile {profile}" ) as console_step: - profile = await resolve_profile( - { - "max_seconds": max_seconds, - "max_requests": max_requests, - "max_errors": max_errors, - "max_error_rate": max_error_rate, - "max_global_error_rate": max_global_error_rate, - }, - profile, - rate, - random_seed, - constraints, - ) + for key, val in { + "max_seconds": max_seconds, + "max_requests": max_requests, + "max_errors": max_errors, + "max_error_rate": max_error_rate, + "max_global_error_rate": max_global_error_rate, + }.items(): + if val is not None: + constraints[key] = val + if not isinstance(profile, Profile): + profile = Profile.create( + rate_type=profile, + rate=rate, + random_seed=random_seed, + constraints={**constraints}, + ) + elif constraints: + raise ValueError( + "Constraints must be empty when providing a Profile instance. " + f"Provided constraints: {constraints} ; provided profile: {profile}" + ) console_step.finish( title=f"{profile.__class__.__name__} profile resolved", details=InfoMixin.extract_from_obj(profile), @@ -296,10 +247,12 @@ async def benchmark_generative_text( # noqa: C901 ) with console.print_update_step(title="Resolving output formats") as console_step: - resolved_output_formats = await resolve_output_formats(output_formats, output_path) + output_formats = GenerativeBenchmarkerOutput.resolve( + output_formats=(output_formats or {}), output_path=output_path + ) console_step.finish( title="Output formats resolved", - details={key: str(val) for key, val in resolved_output_formats.items()}, + details={key: str(val) for key, val in output_formats.items()}, status_level="success", ) @@ -335,11 +288,14 @@ async def benchmark_generative_text( # noqa: C901 if benchmark: report.benchmarks.append(benchmark) - output_format_results = await finalize_outputs(report, resolved_output_formats) + output_format_results = {} + for key, output in output_formats.items(): + output_result = await output.finalize(report) + output_format_results[key] = output_result console.print("\n\n") console.print_update( - title=f"Benchmarking complete; generated {len(report.benchmarks)} benchmark(s)", + title=f"Benchmarking complete, generated {len(report.benchmarks)} benchmark(s)", status="success", ) for key, value in output_format_results.items(): @@ -348,34 +304,20 @@ async def benchmark_generative_text( # noqa: C901 return report, output_format_results -async def reimport_benchmarks_report( - file: Path, - output_path: Path | None, - output_formats: OutputFormatType = ("console", "json", "html", "csv"), -) -> tuple[GenerativeBenchmarksReport, dict[str, Any]]: +def reimport_benchmarks_report(file: Path, output_path: Path | None) -> None: """ The command-line entry point for re-importing and displaying an - existing benchmarks report. Can also specify an output format. + existing benchmarks report. Can also specify Assumes the file provided exists. """ + report = GenerativeBenchmarksReport.load_file(file) + console_output = GenerativeBenchmarkerConsole() + console_output.finalize(report) console = Console() - with console.print_update_step( - title=f"Loading benchmarks from {file}" - ) as console_step: - report = GenerativeBenchmarksReport.load_file(file) - console_step.finish(f"Import of old benchmarks complete; loaded {len(report.benchmarks)} benchmark(s)") - - with console.print_update_step(title="Resolving output formats") as console_step: - resolved_output_formats = await resolve_output_formats(output_formats, output_path) - console_step.finish( - title="Output formats resolved", - details={key: str(val) for key, val in resolved_output_formats.items()}, - status_level="success", - ) - - output_format_results = await finalize_outputs(report, resolved_output_formats) - for key, value in output_format_results.items(): - console.print_update(title=f" {key:<8}: {value}", status="debug") - - return report, output_format_results + if output_path: + with console.print_update_step( + title=f"Saving benchmarks report to {output_path}..." + ) as console_step: + saved_path = report.save_file(output_path) + console_step.finish(title=f"Benchmarks report saved to {saved_path}") diff --git a/src/guidellm/benchmark/objects.py b/src/guidellm/benchmark/objects.py index 8afabba9..a9b5ff79 100644 --- a/src/guidellm/benchmark/objects.py +++ b/src/guidellm/benchmark/objects.py @@ -34,6 +34,9 @@ from guidellm.benchmark.profile import ( Profile, ) +from guidellm.data import ( + GenerationRequestArguments, +) from guidellm.scheduler import ( ScheduledRequestInfo, SchedulerState, @@ -214,9 +217,8 @@ class GenerativeRequestStats(BenchmarkRequestStats): request_type: Literal["text_completions", "chat_completions"] = Field( description="Type of generative request: text or chat completion" ) - prompt: str = Field(description="Input text prompt for generation") - request_args: dict[str, Any] = Field( - description="Generation parameters and configuration options" + request_args: GenerationRequestArguments | None = Field( + default=None, description="Arguments passed to the backend for this request" ) output: str | None = Field( description="Generated text output, if request completed successfully" diff --git a/src/guidellm/benchmark/profile.py b/src/guidellm/benchmark/profile.py index d2f9d70c..fd2a3850 100644 --- a/src/guidellm/benchmark/profile.py +++ b/src/guidellm/benchmark/profile.py @@ -681,7 +681,10 @@ def next_strategy( prev_benchmark.metrics.requests_per_second.successful.mean ) if self.synchronous_rate <= 0 and self.throughput_rate <= 0: - raise RuntimeError("Invalid rates in sweep; aborting. Were there any successful requests?") + raise RuntimeError( + "Invalid rates in sweep; aborting. " + "Were there any successful requests?" + ) self.measured_rates = list( np.linspace( self.synchronous_rate, diff --git a/src/guidellm/data/__init__.py b/src/guidellm/data/__init__.py index 8a48204e..282c5b59 100644 --- a/src/guidellm/data/__init__.py +++ b/src/guidellm/data/__init__.py @@ -1,4 +1,48 @@ -""" -Required for python < 3.12 -https://docs.python.org/3/library/importlib.resources.html#importlib.resources.files -""" +from .datasets import GenerativeRequestsDataset +from .deserializers import ( + DataNotSupportedError, + DatasetDeserializer, + DatasetDeserializerFactory, +) +from .formatters import ( + GenerativeRequestFormatter, + JinjaEnvironmentMixin, + JinjaFiltersRegistry, + JinjaGlobalsRegistry, + JinjaTemplatesRegistry, +) +from .loaders import GenerativeDataLoader, GenerativeRequestCollator +from .objects import ( + GenerationRequest, + GenerationRequestArguments, + GenerationRequestTimings, + GenerativeDatasetArgs, + GenerativeDatasetColumnType, + GenerativeRequestType, +) +from .preprocessors import ( + DatasetPreprocessor, + GenerativeColumnMapper, +) + +__all__ = [ + "DataNotSupportedError", + "DatasetDeserializer", + "DatasetDeserializerFactory", + "DatasetPreprocessor", + "GenerationRequest", + "GenerationRequestArguments", + "GenerationRequestTimings", + "GenerativeColumnMapper", + "GenerativeDataLoader", + "GenerativeDatasetArgs", + "GenerativeDatasetColumnType", + "GenerativeRequestCollator", + "GenerativeRequestFormatter", + "GenerativeRequestType", + "GenerativeRequestsDataset", + "JinjaEnvironmentMixin", + "JinjaFiltersRegistry", + "JinjaGlobalsRegistry", + "JinjaTemplatesRegistry", +] diff --git a/src/guidellm/data/datasets.py b/src/guidellm/data/datasets.py new file mode 100644 index 00000000..8c24683c --- /dev/null +++ b/src/guidellm/data/datasets.py @@ -0,0 +1,88 @@ +from __future__ import annotations + +from collections.abc import Callable +from typing import Any + +from datasets import Dataset, IterableDataset +from transformers import PreTrainedTokenizerBase + +from guidellm.data.deserializers import DatasetDeserializerFactory +from guidellm.data.formatters import GenerativeRequestFormatter +from guidellm.data.objects import GenerativeDatasetArgs +from guidellm.data.preprocessors import ( + DatasetPreprocessor, + GenerativeColumnMapper, +) +from guidellm.data.utils import datasets_item_iterator, resolve_dataset_split + +__all__ = ["GenerativeRequestsDataset"] + + +class GenerativeRequestsDataset: + @classmethod + def build( + cls, + data: list[Any], + data_args: list[GenerativeDatasetArgs] | None, + data_samples: int, + processor_factory: Callable[[], PreTrainedTokenizerBase], + column_mapper: GenerativeColumnMapper, + preprocessors: list[DatasetPreprocessor], + request_formatter: GenerativeRequestFormatter, + random_seed: int = 42, + ) -> Dataset | IterableDataset: + if not data or not isinstance(data, list): + raise ValueError(f"Data must be a non-empty list, got {data}.") + + if data_args is None: + data_args = [GenerativeDatasetArgs() for _ in data] + + if len(data) != len(data_args): + raise ValueError( + f"Length of data ({len(data)}) must match length of data_args " + f"({len(data_args)})." + ) + + datasets = [] + for datum, args in zip(data, data_args): + datasets.append( + resolve_dataset_split( + dataset=DatasetDeserializerFactory.deserialize( + data=datum, + data_kwargs=args.to_kwargs(), + processor_factory=processor_factory, + random_seed=random_seed, + type_=args.type_, + ), + split=args.split, + ) + ) + + column_mapper.init_data(datasets=datasets, data_args=data_args) + request_formatter.init_data(datasets=datasets, data_args=data_args) + for preprocessor in preprocessors: + preprocessor.init_data(datasets=datasets, data_args=data_args) + + if data_samples > 0: + dataset = Dataset.from_list( + list( + datasets_item_iterator( + datasets=datasets, + data_samples=data_samples, + ) + ) + ) + else: + dataset = IterableDataset.from_generator( + datasets_item_iterator, + gen_kwargs={ + "datasets": datasets, + "data_samples": data_samples, + }, + ) + + dataset = dataset.map(column_mapper) + for preprocessor in preprocessors: + dataset = dataset.map(preprocessor) + + return dataset.map(request_formatter) diff --git a/src/guidellm/data/deserializers/__init__.py b/src/guidellm/data/deserializers/__init__.py new file mode 100644 index 00000000..fdee12ce --- /dev/null +++ b/src/guidellm/data/deserializers/__init__.py @@ -0,0 +1,51 @@ +from .deserializer import ( + DataNotSupportedError, + DatasetDeserializer, + DatasetDeserializerFactory, +) +from .file import ( + ArrowFileDatasetDeserializer, + CSVFileDatasetDeserializer, + DBFileDatasetDeserializer, + HDF5FileDatasetDeserializer, + JSONFileDatasetDeserializer, + ParquetFileDatasetDeserializer, + TarFileDatasetDeserializer, + TextFileDatasetDeserializer, +) +from .huggingface import HuggingFaceDatasetDeserializer +from .memory import ( + InMemoryCsvDatasetDeserializer, + InMemoryDictDatasetDeserializer, + InMemoryDictListDatasetDeserializer, + InMemoryItemListDatasetDeserializer, + InMemoryJsonStrDatasetDeserializer, +) +from .synthetic import ( + SyntheticTextDatasetConfig, + SyntheticTextDatasetDeserializer, + SyntheticTextGenerator, +) + +__all__ = [ + "ArrowFileDatasetDeserializer", + "CSVFileDatasetDeserializer", + "DBFileDatasetDeserializer", + "DataNotSupportedError", + "DatasetDeserializer", + "DatasetDeserializerFactory", + "HDF5FileDatasetDeserializer", + "HuggingFaceDatasetDeserializer", + "InMemoryCsvDatasetDeserializer", + "InMemoryDictDatasetDeserializer", + "InMemoryDictListDatasetDeserializer", + "InMemoryItemListDatasetDeserializer", + "InMemoryJsonStrDatasetDeserializer", + "JSONFileDatasetDeserializer", + "ParquetFileDatasetDeserializer", + "SyntheticTextDatasetConfig", + "SyntheticTextDatasetDeserializer", + "SyntheticTextGenerator", + "TarFileDatasetDeserializer", + "TextFileDatasetDeserializer", +] diff --git a/src/guidellm/data/deserializers/deserializer.py b/src/guidellm/data/deserializers/deserializer.py new file mode 100644 index 00000000..ed9050a1 --- /dev/null +++ b/src/guidellm/data/deserializers/deserializer.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +import contextlib +from collections.abc import Callable +from typing import Any, Protocol, Union, runtime_checkable + +from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict +from transformers import PreTrainedTokenizerBase + +from guidellm.utils import RegistryMixin + +__all__ = [ + "DataNotSupportedError", + "DatasetDeserializer", + "DatasetDeserializerFactory", +] + + +class DataNotSupportedError(Exception): + """Exception raised when data format is not supported by deserializer.""" + + +@runtime_checkable +class DatasetDeserializer(Protocol): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: ... + + +class DatasetDeserializerFactory( + RegistryMixin[Union["type[DatasetDeserializer]", DatasetDeserializer]], +): + @classmethod + def deserialize( + cls, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int = 42, + type_: str | None = None, + ) -> Dataset | IterableDataset | DatasetDict | IterableDatasetDict: + if type_ is not None: + deserializer = cls.get_registered_object(type_) + + if deserializer is None: + raise DataNotSupportedError( + f"Deserializer type '{type_}' is not registered. " + f"Available types: {cls.registry}" + ) + elif isinstance(deserializer, type): + deserializer_fn = deserializer() + else: + deserializer_fn = deserializer + + return deserializer_fn( + data=data, + data_kwargs=data_kwargs, + processor_factory=processor_factory, + random_seed=random_seed, + ) + + for deserializer in cls.registered_objects(): + deserializer_fn: DatasetDeserializer = ( + deserializer() if isinstance(deserializer, type) else deserializer + ) + + with contextlib.suppress(DataNotSupportedError): + return deserializer_fn( + data=data, + data_kwargs=data_kwargs, + processor_factory=processor_factory, + random_seed=random_seed, + ) + + raise DataNotSupportedError( + f"No suitable deserializer found for data {data} with kwargs {data_kwargs}." + ) diff --git a/src/guidellm/data/deserializers/file.py b/src/guidellm/data/deserializers/file.py new file mode 100644 index 00000000..53688cf0 --- /dev/null +++ b/src/guidellm/data/deserializers/file.py @@ -0,0 +1,221 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any, Callable + +import pandas as pd +from datasets import Dataset, load_dataset +from transformers import PreTrainedTokenizerBase + +from guidellm.data.deserializers.deserializer import ( + DataNotSupportedError, + DatasetDeserializer, + DatasetDeserializerFactory, +) + +__all__ = [ + "ArrowFileDatasetDeserializer", + "CSVFileDatasetDeserializer", + "DBFileDatasetDeserializer", + "HDF5FileDatasetDeserializer", + "JSONFileDatasetDeserializer", + "ParquetFileDatasetDeserializer", + "TarFileDatasetDeserializer", + "TextFileDatasetDeserializer", +] + + +@DatasetDeserializerFactory.register("text_file") +class TextFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) # Ignore unused args format errors + + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() not in {".txt", ".text"} + ): + raise DataNotSupportedError( + "Unsupported data for TextFileDatasetDeserializer, " + f"expected str or Path to a local .txt or .text file, got {data}" + ) + + with path.open() as file: + lines = file.readlines() + + return Dataset.from_dict({"text": lines}, **data_kwargs) + + +@DatasetDeserializerFactory.register("csv_file") +class CSVFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() != ".csv" + ): + raise DataNotSupportedError( + "Unsupported data for CSVFileDatasetDeserializer, " + f"expected str or Path to a local .csv file, got {data}" + ) + + return load_dataset("csv", data_files=str(path), **data_kwargs) + + +@DatasetDeserializerFactory.register("json_file") +class JSONFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() not in {".json", ".jsonl"} + ): + raise DataNotSupportedError( + f"Unsupported data for JSONFileDatasetDeserializer, " + f"expected str or Path to a local .json or .jsonl file, got {data}" + ) + + return load_dataset("json", data_files=str(path), **data_kwargs) + + +@DatasetDeserializerFactory.register("parquet_file") +class ParquetFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() != ".parquet" + ): + raise DataNotSupportedError( + f"Unsupported data for ParquetFileDatasetDeserializer, " + f"expected str or Path to a local .parquet file, got {data}" + ) + + return load_dataset("parquet", data_files=str(path), **data_kwargs) + + +@DatasetDeserializerFactory.register("arrow_file") +class ArrowFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() != ".arrow" + ): + raise DataNotSupportedError( + f"Unsupported data for ArrowFileDatasetDeserializer, " + f"expected str or Path to a local .arrow file, got {data}" + ) + + return load_dataset("arrow", data_files=str(path), **data_kwargs) + + +@DatasetDeserializerFactory.register("hdf5_file") +class HDF5FileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() not in {".hdf5", ".h5"} + ): + raise DataNotSupportedError( + f"Unsupported data for HDF5FileDatasetDeserializer, " + f"expected str or Path to a local .hdf5 or .h5 file, got {data}" + ) + + return Dataset.from_pandas(pd.read_hdf(str(path)), **data_kwargs) + + +@DatasetDeserializerFactory.register("db_file") +class DBFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() != ".db" + ): + raise DataNotSupportedError( + f"Unsupported data for DBFileDatasetDeserializer, " + f"expected str or Path to a local .db file, got {data}" + ) + + return Dataset.from_sql(con=str(path), **data_kwargs) + + +@DatasetDeserializerFactory.register("tar_file") +class TarFileDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + if ( + not isinstance(data, (str, Path)) + or not (path := Path(data)).exists() + or not path.is_file() + or path.suffix.lower() != ".tar" + ): + raise DataNotSupportedError( + f"Unsupported data for TarFileDatasetDeserializer, " + f"expected str or Path to a local .tar file, got {data}" + ) + + return load_dataset("webdataset", data_files=str(path), **data_kwargs) diff --git a/src/guidellm/data/deserializers/huggingface.py b/src/guidellm/data/deserializers/huggingface.py new file mode 100644 index 00000000..275f7180 --- /dev/null +++ b/src/guidellm/data/deserializers/huggingface.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any, Callable + +from datasets import ( + Dataset, + DatasetDict, + IterableDataset, + IterableDatasetDict, + load_dataset, + load_from_disk, +) +from transformers import PreTrainedTokenizerBase + +from guidellm.data.deserializers.deserializer import ( + DataNotSupportedError, + DatasetDeserializer, + DatasetDeserializerFactory, +) + +__all__ = ["HuggingFaceDatasetDeserializer"] + + +@DatasetDeserializerFactory.register("huggingface") +class HuggingFaceDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) + + if isinstance( + data, (Dataset, IterableDataset, DatasetDict, IterableDatasetDict) + ): + return data + + load_error = None + + if ( + isinstance(data, (str, Path)) + and (path := Path(data)).exists() + and ((path.is_file() and path.suffix == ".py") or path.is_dir()) + ): + # Handle python script or nested python script in a directory + try: + return load_dataset(str(data), **data_kwargs) + except Exception as err: # noqa: BLE001 + load_error = err + + if ( + isinstance(data, (str, Path)) + and (path := Path(data)).exists() + and path.is_dir() + ): + # Handle local dataset directory + try: + return load_from_disk(str(data), **data_kwargs) + except Exception as err: # noqa: BLE001 + load_error = err + + not_supported = DataNotSupportedError( + "Unsupported data for HuggingFaceDatasetDeserializer, " + "expected Dataset, IterableDataset, DatasetDict, IterableDatasetDict, " + "str or Path to a local dataset directory or a local .py dataset script, " + f"got {data} and HF load error: {load_error}" + ) + + if load_error is not None: + raise not_supported from load_error + else: + raise not_supported diff --git a/src/guidellm/data/deserializers/memory.py b/src/guidellm/data/deserializers/memory.py new file mode 100644 index 00000000..b04ea6bc --- /dev/null +++ b/src/guidellm/data/deserializers/memory.py @@ -0,0 +1,191 @@ +from __future__ import annotations + +import contextlib +import csv +import json +from io import StringIO +from typing import Any, Callable, cast + +from datasets import Dataset +from transformers import PreTrainedTokenizerBase + +from guidellm.data.deserializers.deserializer import ( + DataNotSupportedError, + DatasetDeserializer, + DatasetDeserializerFactory, +) + +__all__ = [ + "InMemoryCsvDatasetDeserializer", + "InMemoryDictDatasetDeserializer", + "InMemoryDictListDatasetDeserializer", + "InMemoryItemListDatasetDeserializer", + "InMemoryJsonStrDatasetDeserializer", +] + + +@DatasetDeserializerFactory.register("in_memory_dict") +class InMemoryDictDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) # Ignore unused args format errors + + if ( + not data + or not isinstance(data, dict) + or not all( + isinstance(key, str) and isinstance(val, list) + for key, val in data.items() + ) + ): + raise DataNotSupportedError( + f"Unsupported data for InMemoryDictDatasetDeserializer, " + f"expected dict[str, list], got {data}" + ) + + rows = len(list(data.values())[0]) + if not all(len(val) == rows for val in data.values()): + raise DataNotSupportedError( + "All lists in the data dictionary must have the same length, " + f"expected {rows} for all keys {list(data.keys())}" + ) + + return Dataset.from_dict(data, **data_kwargs) + + +@DatasetDeserializerFactory.register("in_memory_dict_list") +class InMemoryDictListDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) # Ignore unused args format errors + + if ( + not data + or not isinstance(data, list) + or not all(isinstance(item, dict) for item in data) + or not all(isinstance(key, str) for item in data for key in item) + ): + raise DataNotSupportedError( + f"Unsupported data for InMemoryDictListDatasetDeserializer, " + f"expected list of dicts, got {data}" + ) + + data: list[dict[str, Any]] = cast("list[dict[str, Any]]", data) + first_keys = set(data[0].keys()) + for index, item in enumerate(data): + if set(item.keys()) != first_keys: + raise DataNotSupportedError( + f"All dictionaries must have the same keys. " + f"Expected keys: {first_keys}, " + f"got keys at index {index}: {set(item.keys())}" + ) + + # Convert list of dicts to dict of lists + result_dict = {key: [] for key in first_keys} + for item in data: + for key, value in item.items(): + result_dict[key].append(value) + + return Dataset.from_dict(result_dict, **data_kwargs) + + +@DatasetDeserializerFactory.register("in_memory_item_list") +class InMemoryItemListDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + _ = (processor_factory, random_seed) # Ignore unused args format errors + + primitive_types = (str, int, float, bool, type(None)) + if ( + not data + or not isinstance(data, list) + or not all(isinstance(item, primitive_types) for item in data) + ): + raise DataNotSupportedError( + f"Unsupported data for InMemoryItemListDatasetDeserializer, " + f"expected list of primitive items, got {data}" + ) + + column_name = data_kwargs.pop("column_name", "data") + + return Dataset.from_dict({column_name: data}, **data_kwargs) + + +@DatasetDeserializerFactory.register("in_memory_json_str") +class InMemoryJsonStrDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + if ( + isinstance(data, str) + and (json_str := data.strip()) + and ( + (json_str.startswith("{") and json_str.endswith("}")) + or (json_str.startswith("[") and json_str.endswith("]")) + ) + ): + with contextlib.suppress(Exception): + parsed = json.loads(data) + + for deserializer in [ + InMemoryDictDatasetDeserializer, + InMemoryDictListDatasetDeserializer, + InMemoryItemListDatasetDeserializer, + ]: + with contextlib.suppress(DataNotSupportedError): + return deserializer()( + parsed, data_kwargs, processor_factory, random_seed + ) + + raise DataNotSupportedError( + f"Unsupported data for InMemoryJsonStrDatasetDeserializer, " + f"expected JSON string with a list or dict of items, got {data}" + ) + + +@DatasetDeserializerFactory.register("in_memory_csv_str") +class InMemoryCsvDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> dict[str, list]: + if ( + isinstance(data, str) + and (csv_str := data.strip()) + and len(csv_str.split("\n")) > 0 + ): + with contextlib.suppress(Exception): + csv_buffer = StringIO(data) + reader = csv.DictReader(csv_buffer) + rows = list(reader) + + return InMemoryDictListDatasetDeserializer()( + rows, data_kwargs, processor_factory, random_seed + ) + + raise DataNotSupportedError( + f"Unsupported data for InMemoryCsvDatasetDeserializer, " + f"expected CSV string, got {type(data)}" + ) diff --git a/src/guidellm/data/deserializers/synthetic.py b/src/guidellm/data/deserializers/synthetic.py new file mode 100644 index 00000000..2335596d --- /dev/null +++ b/src/guidellm/data/deserializers/synthetic.py @@ -0,0 +1,255 @@ +from __future__ import annotations + +from collections.abc import Iterator +from pathlib import Path +from typing import Any, Callable + +import yaml +from datasets import Features, IterableDataset, Value +from faker import Faker +from pydantic import Field +from transformers import PreTrainedTokenizerBase + +from guidellm.data.deserializers.deserializer import ( + DataNotSupportedError, + DatasetDeserializer, + DatasetDeserializerFactory, +) +from guidellm.utils import IntegerRangeSampler, StandardBaseModel + +__all__ = [ + "SyntheticTextDatasetConfig", + "SyntheticTextDatasetDeserializer", + "SyntheticTextGenerator", +] + + +class SyntheticTextDatasetConfig(StandardBaseModel): + prompt_tokens: int = Field( + description="The average number of text tokens generated for prompts.", + gt=0, + ) + prompt_tokens_stdev: int | None = Field( + description="The standard deviation of the tokens generated for prompts.", + gt=0, + default=None, + ) + prompt_tokens_min: int | None = Field( + description="The minimum number of text tokens generated for prompts.", + gt=0, + default=None, + ) + prompt_tokens_max: int | None = Field( + description="The maximum number of text tokens generated for prompts.", + gt=0, + default=None, + ) + output_tokens: int = Field( + description="The average number of text tokens generated for outputs.", + gt=0, + ) + output_tokens_stdev: int | None = Field( + description="The standard deviation of the tokens generated for outputs.", + gt=0, + default=None, + ) + output_tokens_min: int | None = Field( + description="The minimum number of text tokens generated for outputs.", + gt=0, + default=None, + ) + output_tokens_max: int | None = Field( + description="The maximum number of text tokens generated for outputs.", + gt=0, + default=None, + ) + source: str = Field( + description="The source of the text data to be used for generation.", + default="data:prideandprejudice.txt.gz", + ) + + +class SyntheticTextGenerator: + def __init__( + self, + config: SyntheticTextDatasetConfig, + processor: PreTrainedTokenizerBase, + random_seed: int = 42, + ): + self.config = config + self.processor = processor + self.random_seed = random_seed + + def __iter__(self) -> Iterator[dict[str, Any]]: + samples_generated = 0 + + faker = Faker() + faker.seed_instance(self.random_seed) + prompt_tokens_sampler = iter( + IntegerRangeSampler( + average=self.config.prompt_tokens, + variance=self.config.prompt_tokens_stdev, + min_value=self.config.prompt_tokens_min, + max_value=self.config.prompt_tokens_max, + random_seed=self.random_seed, + ) + ) + output_tokens_sampler = iter( + IntegerRangeSampler( + average=self.config.output_tokens, + variance=self.config.output_tokens_stdev, + min_value=self.config.output_tokens_min, + max_value=self.config.output_tokens_max, + random_seed=self.random_seed + 1, # ensure diff dist from prompts + ) + ) + + while True: + prompt_tokens_count = next(prompt_tokens_sampler) + output_tokens_count = next(output_tokens_sampler) + + yield { + "prompt": self._create_prompt( + prompt_tokens_count, samples_generated, faker + ), + "prompt_tokens_count": prompt_tokens_count, + "output_tokens_count": output_tokens_count, + } + samples_generated += 1 + + def _create_prompt(self, prompt_tokens_count: int, index: int, faker: Faker) -> str: + prompt_token_ids = [] + avg_chars_per_token = 5 + margin_of_safety = 1.5 + attempts = 0 + + while len(prompt_token_ids) < prompt_tokens_count: + attempts += 1 + num_chars = ( + prompt_tokens_count * avg_chars_per_token * margin_of_safety * attempts + ) + text = f"{index} " + faker.text(max_nb_chars=num_chars) + prompt_token_ids = self.processor.encode(text) + + return self.processor.decode( + prompt_token_ids[:prompt_tokens_count], skip_special_tokens=True + ) + + +@DatasetDeserializerFactory.register("synthetic_text") +class SyntheticTextDatasetDeserializer(DatasetDeserializer): + def __call__( + self, + data: Any, + data_kwargs: dict[str, Any], + processor_factory: Callable[[], PreTrainedTokenizerBase], + random_seed: int, + ) -> IterableDataset: + # Config file pathways, deserialize and call self again + if (config := self._load_config_file(data)) is not None: + return self(config, data_kwargs, processor_factory, random_seed) + + # Config str pathways, deserialize and call self again + if (config := self._load_config_str(data)) is not None: + return self(config, data_kwargs, processor_factory, random_seed) + + if not isinstance(data, SyntheticTextDatasetConfig): + raise DataNotSupportedError( + "Unsupported data for SyntheticTextDatasetDeserializer, " + "expected SyntheticTextDatasetConfig, str or Path to a config file, " + f"got {data}" + ) + + return IterableDataset.from_generator( + lambda: SyntheticTextGenerator( + config=data, processor=processor_factory(), random_seed=random_seed + ), + features=Features( + { + "prompt": Value("string"), + "prompt_tokens_count": Value("int32"), + "output_tokens_count": Value("int32"), + } + ), + ) + + def _load_config_file(self, data: Any) -> SyntheticTextDatasetConfig | None: + if (not isinstance(data, str) and not isinstance(data, Path)) or ( + not Path(data).is_file() + ): + return None + + data_path = Path(data) if isinstance(data, str) else data + error = None + + if Path(data).is_file() and data_path.suffix.lower() == ".json": + try: + return SyntheticTextDatasetConfig.model_validate_json( + data_path.read_text() + ) + except Exception as err: # noqa: BLE001 + error = err + + if Path(data).is_file() and data_path.suffix.lower() in { + ".yaml", + ".yml", + ".config", + }: + try: + return SyntheticTextDatasetConfig.model_validate( + yaml.safe_load(data_path.read_text()) + ) + except Exception as err: # noqa: BLE001 + error = err + + err_message = ( + f"Unsupported file {data_path} for " + f"SyntheticTextDatasetDeserializer, expected .json, " + f".yaml, .yml, or .config" + ) + + if error is not None: + err_message += f" with error: {error}" + raise DataNotSupportedError(err_message) from error + raise DataNotSupportedError(err_message) + + def _load_config_str(self, data: str) -> SyntheticTextDatasetConfig | None: + if not isinstance(data, str): + return None + + data_str = data.strip() + error = None + + if (data_str.startswith("{") and data_str.endswith("}")) or ( + data_str.startswith("[") and data_str.endswith("]") + ): + try: + return SyntheticTextDatasetConfig.model_validate_json(data_str) + except Exception as err: # noqa: BLE001 + error = err + + if data_str.count("=") > 1: + # key=value pairs separated by commas + try: + config_dict = {} + items = data_str.split(",") + for item in items: + key, value = item.split("=") + config_dict[key.strip()] = ( + int(value.strip()) + if value.strip().isnumeric() + else value.strip() + ) + + return SyntheticTextDatasetConfig.model_validate(config_dict) + except Exception as err: # noqa: BLE001 + error = err + + err_message = ( + "Unsupported string data for SyntheticTextDatasetDeserializer, " + f"expected JSON or key-value pairs, got {data}" + ) + if error is not None: + err_message += f" with error: {error}" + raise DataNotSupportedError(err_message) from error + raise DataNotSupportedError(err_message) diff --git a/src/guidellm/data/formatters/__init__.py b/src/guidellm/data/formatters/__init__.py new file mode 100644 index 00000000..0a5ccbc9 --- /dev/null +++ b/src/guidellm/data/formatters/__init__.py @@ -0,0 +1,47 @@ +from .environment import JinjaEnvironmentMixin +from .filters import ( + JinjaFiltersRegistry, + download_audio, + download_image, + download_video, + encode_audio, + encode_image, + encode_image_base64, + encode_video, + encode_video_base64, + get_file_format, + is_url, + resize_image, +) +from .globals import JinjaGlobalsRegistry +from .objects import GenerativeRequestFormatter +from .templates import ( + DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE, + DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE, + DEFAULT_CHAT_COMPLETIONS_TEMPLATE, + DEFAULT_TEXT_COMPLETIONS_TEMPLATE, + JinjaTemplatesRegistry, +) + +__all__ = [ + "DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE", + "DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE", + "DEFAULT_CHAT_COMPLETIONS_TEMPLATE", + "DEFAULT_TEXT_COMPLETIONS_TEMPLATE", + "GenerativeRequestFormatter", + "JinjaEnvironmentMixin", + "JinjaFiltersRegistry", + "JinjaGlobalsRegistry", + "JinjaTemplatesRegistry", + "download_audio", + "download_image", + "download_video", + "encode_audio", + "encode_image", + "encode_image_base64", + "encode_video", + "encode_video_base64", + "get_file_format", + "is_url", + "resize_image", +] diff --git a/src/guidellm/data/formatters/environment.py b/src/guidellm/data/formatters/environment.py new file mode 100644 index 00000000..bd37e26b --- /dev/null +++ b/src/guidellm/data/formatters/environment.py @@ -0,0 +1,63 @@ +from __future__ import annotations + +from typing import Any, ClassVar + +from jinja2 import Template +from jinja2.nativetypes import NativeEnvironment, NativeTemplate + +from guidellm.data.formatters.filters import JinjaFiltersRegistry +from guidellm.data.formatters.globals import JinjaGlobalsRegistry +from guidellm.data.formatters.templates import JinjaTemplatesRegistry + +__all__ = ["JinjaEnvironmentMixin"] + + +class JinjaEnvironmentMixin: + jinja_environment: ClassVar[NativeEnvironment | None] = None + + @classmethod + def create_environment(cls, **env_kwargs: Any) -> NativeEnvironment: + if "autoescape" not in env_kwargs: + env_kwargs["autoescape"] = False + + extensions = env_kwargs.pop("extensions", []) + extensions = set(extensions) | {"jinja2.ext.do"} + + env = NativeEnvironment(extensions=list(extensions), **env_kwargs) # noqa: S701 + + # Attach registered filters + filters_registry = JinjaFiltersRegistry.registry # type: ignore[misc] + if filters_registry: + for name, func in filters_registry.items(): + env.filters[name] = func + + # Attach registered globals + globals_registry = JinjaGlobalsRegistry.registry # type: ignore[misc] + if globals_registry: + for name, value in globals_registry.items(): + env.globals[name] = value + + cls.jinja_environment = env + return env + + @classmethod + def get_environment(cls) -> NativeEnvironment: + if cls.jinja_environment is None: + raise ValueError( + "Jinja environment is not initialized. Call create_environment first." + ) + return cls.jinja_environment + + @classmethod + def template_from_source(cls, source: str | Template) -> NativeTemplate: + if isinstance(source, Template): + return source + env = cls.get_environment() + return env.from_string(source) + + @classmethod + def template_from_registry(cls, name: str) -> NativeTemplate: + template = JinjaTemplatesRegistry.get_registered_object(name) + if template is None: + raise ValueError(f"Template '{name}' not found in registry.") + return cls.template_from_source(template) diff --git a/src/guidellm/data/formatters/filters.py b/src/guidellm/data/formatters/filters.py new file mode 100644 index 00000000..8dd4e445 --- /dev/null +++ b/src/guidellm/data/formatters/filters.py @@ -0,0 +1,324 @@ +from __future__ import annotations + +import base64 +import io +from pathlib import Path +from typing import Any, Callable, Literal + +import datasets +import httpx +import librosa +import numpy as np +import soundfile +from PIL import Image as PILImage + +from guidellm.utils import RegistryMixin + +__all__ = [ + "JinjaFiltersRegistry", + "download_audio", + "download_image", + "download_video", + "encode_audio", + "encode_image", + "encode_image_base64", + "encode_video", + "encode_video_base64", + "get_file_format", + "is_url", + "resize_image", +] + + +class JinjaFiltersRegistry(RegistryMixin[Callable[..., Any]]): + pass + + +@JinjaFiltersRegistry.register("is_url") +def is_url(text: Any) -> bool: + return isinstance(text, str) and text.startswith(("http://", "https://")) + + +@JinjaFiltersRegistry.register("encode_image") +def encode_image( + image: bytes | str | Path | np.ndarray | PILImage.Image | datasets.Image, + max_size: int | None = None, + max_width: int | None = None, + max_height: int | None = None, + encode_type: Literal["base64", "url"] | None = None, +) -> str: + """ + Input image types: + - bytes: raw image bytes, decoded with Pillow + - str: file path on disk, url, or already base64 encoded image string + - pathlib.Path: file path on disk + - np.ndarray: image array, decoded with Pillow + - PIL.Image.Image: Pillow image + - datasets.Image: HuggingFace datasets Image object + + max_size: maximum size of the longest edge of the image + max_width: maximum width of the image + max_height: maximum height of the image + + encode_type: None to return the supported format + (url for url, base64 string for others) + "base64" to return base64 encoded string (or download URL and encode) + "url" to return url (only if input is url, otherwise fails) + + Returns a str of either: + - image url + - "data:image/{type};base64, {data}" string + """ + url = is_url(image) + + if ( + url + and (encode_type is None or encode_type == "url") + and (max_size is not None or max_width is not None or max_height is not None) + ): + raise ValueError("Cannot resize image when encode_type is 'url'") + elif url and (encode_type is None or encode_type == "url"): + return image + elif url and encode_type == "base64": + raise ValueError(f"Cannot convert non-url image to URL {image}") + + return encode_image_base64( + image=image, + max_size=max_size, + max_width=max_width, + max_height=max_height, + ) + + +@JinjaFiltersRegistry.register("encode_image_base64") +def encode_image_base64( + image: bytes | str | Path | np.ndarray | PILImage.Image, + width: int | None = None, + height: int | None = None, + max_width: int | None = None, + max_height: int | None = None, + max_size: int | None = None, +) -> str: + if ( + isinstance(image, str) + and image.startswith("data:image/") + and ";base64," in image + ): + return image + + if is_url(image): + image = download_image(image) + + if isinstance(image, bytes): + image = PILImage.open(io.BytesIO(image)) + elif isinstance(image, (str, Path)): + image = PILImage.open(image) + elif isinstance(image, np.ndarray): + image = PILImage.fromarray(image) + elif not isinstance(image, PILImage.Image): + raise ValueError(f"Unsupported image type: {type(image)}") + + image = resize_image( + image, + width=width, + height=height, + max_width=max_width, + max_height=max_height, + max_size=max_size, + ) + if image.mode != "RGB": + image = image.convert("RGB") + + buffer = io.BytesIO() + image.save(buffer, format="JPEG") + image_bytes = buffer.getvalue() + image_base64 = base64.b64encode(image_bytes).decode("utf-8") + + return f"data:image/jpeg;base64,{image_base64}" + + +@JinjaFiltersRegistry.register("resize_image") +def resize_image( + image: PILImage.Image, + width: int | None = None, + height: int | None = None, + max_width: int | None = None, + max_height: int | None = None, + max_size: int | None = None, +) -> PILImage.Image: + if not isinstance(image, PILImage.Image): + raise ValueError(f"Unsupported image type: {type(image)}") + + if width is not None and height is not None: + return image.resize((width, height), PILImage.Resampling.BILINEAR) + + orig_w, orig_h = image.size + aspect = orig_w / orig_h + + if width is not None: + target_w = width + target_h = round(width / aspect) + elif height is not None: + target_h = height + target_w = round(height * aspect) + else: + target_w, target_h = orig_w, orig_h + + # Normalize max_size → max_width/max_height + if max_size is not None: + max_width = max_width or max_size + max_height = max_height or max_size + + # Apply max constraints (preserve aspect ratio) + if max_width or max_height: + scale_w = max_width / target_w if max_width else 1.0 + scale_h = max_height / target_h if max_height else 1.0 + scale = min(scale_w, scale_h, 1.0) # never upscale + target_w = round(target_w * scale) + target_h = round(target_h * scale) + + if (target_w, target_h) != (orig_w, orig_h): + image = image.resize((target_w, target_h), PILImage.Resampling.BILINEAR) + + return image + + +@JinjaFiltersRegistry.register("download_image") +def download_image(url: str) -> bytes: + response = httpx.get(url) + response.raise_for_status() + return response.content + + +@JinjaFiltersRegistry.register("encode_video") +def encode_video( + video: bytes | str | Path | datasets.Video, + encode_type: Literal["base64", "url"] | None = None, +) -> str: + """ + Input video types: + - bytes: raw video bytes + - str: file path on disk, url, or already base64 encoded video string + - pathlib.Path: file path on disk + - datasets.Video: HuggingFace datasets Video object + + encode_type: None to return the supported format + (url for url, base64 string for others) + "base64" to return base64 encoded string (or download URL and encode) + "url" to return url (only if input is url, otherwise fails) + + Returns a str of either: + - video url + - "data:video/{type};base64, {data}" string + """ + url = is_url(video) + + if url and (encode_type is None or encode_type == "url"): + return video + elif url and encode_type == "base64": + raise ValueError(f"Cannot encode URL video {video}") + + return encode_video_base64(video=video) + + +@JinjaFiltersRegistry.register("encode_video_base64") +def encode_video_base64(video: bytes | str | Path) -> str: + if ( + isinstance(video, str) + and video.startswith("data:video/") + and ";base64," in video + ): + return video + + video_format = "unknown" + + if is_url(video): + video, video_format = download_video(video) + + if isinstance(video, (str, Path)): + path = Path(video) + video = path.read_bytes() + video_format = get_file_format(path) + elif not isinstance(video, bytes): + raise ValueError(f"Unsupported video type: {type(video)}") + + video_base64 = base64.b64encode(video).decode("utf-8") + return f"data:video/{video_format};base64,{video_base64}" + + +@JinjaFiltersRegistry.register("download_video") +def download_video(url: str) -> tuple[bytes, str]: + response = httpx.get(url) + response.raise_for_status() + return response.content, get_file_format(url) + + +@JinjaFiltersRegistry.register("encode_audio") +def encode_audio( + audio: bytes | str | Path | dict | np.ndarray, + sample_rate: int | None = None, + max_duration: float | None = None, +) -> dict[str, str]: + """ + Input audio types: + - bytes: raw audio bytes + - str: file path on disk or URL + - pathlib.Path: file path on disk + - dict: {"data": base64_string, "format": "wav"} format + - numpy.ndarray: audio array, assumed to be at sample_rate if provided + + sample_rate: sample rate of the input audio if input is np.ndarray + target_sample_rate: resample to this rate if provided + duration: limit audio to this duration in seconds if provided + + Returns dict with format: + { + "data": base64_encoded_audio_bytes, + "format": "wav" + } + """ + if is_url(audio): + audio, _ = download_audio(audio) + + if isinstance(audio, dict): + if "data" not in audio: + raise ValueError("Audio dict must contain 'data' key") + audio = base64.b64decode(audio["data"]) + + if isinstance(audio, bytes): + audio_data, sample_rate = librosa.load(io.BytesIO(audio), sr=sample_rate) + elif isinstance(audio, (str, Path)): + audio_data, sample_rate = librosa.load(str(audio), sr=sample_rate) + elif isinstance(audio, np.ndarray): + if sample_rate is None: + raise ValueError("sample_rate must be provided for numpy arrays") + audio_data = audio + else: + raise ValueError(f"Unsupported audio type: {type(audio)}") + + if max_duration is not None: + max_samples = int(max_duration * sample_rate) + if len(audio_data) > max_samples: + audio_data = audio_data[:max_samples] + + buffer = io.BytesIO() + soundfile.write(buffer, audio_data, sample_rate, format="WAV", subtype="PCM_16") + + return {"data": buffer.getvalue(), "format": "wav"} + + +@JinjaFiltersRegistry.register("download_audio") +def download_audio(url: str) -> tuple[bytes, str]: + """Download audio from URL and return bytes with format.""" + response = httpx.get(url) + response.raise_for_status() + content = response.content + audio_format = get_file_format(url) + return content, audio_format + + +@JinjaFiltersRegistry.register("get_file_format") +def get_file_format(path: Path | str) -> str: + """Get file format from path extension.""" + suffix = Path(path).suffix.lower() + return suffix[1:] if suffix.startswith(".") else "unknown" diff --git a/src/guidellm/data/formatters/globals.py b/src/guidellm/data/formatters/globals.py new file mode 100644 index 00000000..6c066191 --- /dev/null +++ b/src/guidellm/data/formatters/globals.py @@ -0,0 +1,9 @@ +from typing import Any + +from guidellm.utils import RegistryMixin + +__all__ = ["JinjaGlobalsRegistry"] + + +class JinjaGlobalsRegistry(RegistryMixin[Any]): + pass diff --git a/src/guidellm/data/formatters/objects.py b/src/guidellm/data/formatters/objects.py new file mode 100644 index 00000000..3e032089 --- /dev/null +++ b/src/guidellm/data/formatters/objects.py @@ -0,0 +1,92 @@ +from __future__ import annotations + +from typing import Any, Literal + +from datasets import Dataset, IterableDataset +from jinja2 import Template + +from guidellm.data.formatters import JinjaEnvironmentMixin +from guidellm.data.objects import ( + GenerationRequest, + GenerationRequestArguments, + GenerativeDatasetArgs, + GenerativeRequestType, +) +from guidellm.data.preprocessors.objects import DatasetPreprocessor + +__all__ = ["GenerativeRequestFormatter"] + + +class GenerativeRequestFormatter(DatasetPreprocessor, JinjaEnvironmentMixin): + def __init__( + self, + request_type: GenerativeRequestType | str = "text_completions", + request_template: str | Template | None = None, + request_extras: dict[str, Any] | GenerationRequestArguments | None = None, + request_defaults: dict[str, Any] | GenerationRequestArguments | None = None, + environment_extras: dict[str, Any] | None = None, + ): + self.datasets: list[Dataset | IterableDataset] | None = None + self.data_args: list[GenerativeDatasetArgs] | None = None + + self.request_type = request_type + self.request_template = request_template + self.request_extras = request_extras or {} + self.request_defaults = request_defaults or { + "stream": True, + "json_body": { + "stream": True, + "stream_options": { + "include_usage": True, + }, + }, + } + self.environment_extras = environment_extras or {} + self.jinja_template: Template | None = None + + def init_data( + self, + datasets: list[Dataset | IterableDataset], + data_args: list[GenerativeDatasetArgs], + ): + self.datasets = datasets + self.data_args = data_args + + self.create_environment(**self.environment_extras) + self.jinja_template = ( + self.template_from_source(self.request_template) + if self.request_template + else self.template_from_registry(self.request_type) + ) + + def __call__( + self, item: dict[str, Any] + ) -> dict[Literal["request"], GenerationRequest]: + if self.jinja_template is None: + raise ValueError("GenerativeRequestCreator not initialized with data.") + + stats = {} + if "prompt_tokens_count" in item: + count = item["prompt_tokens_count"][0] + stats["prompt_tokens"] = count + item["prompt_tokens_count"] = count + if "output_tokens_count" in item: + count = item["output_tokens_count"][0] + stats["output_tokens"] = count + item["output_tokens_count"] = count + + return { + "request": { + "request_type": self.request_type, + "arguments": GenerationRequestArguments.model_combine_dict( + self.request_defaults, + self.request_extras, + self.jinja_template.render( + **item, + request_defaults=self.request_defaults, + request_extras=self.request_extras, + ), + ), + "stats": stats, + } + } diff --git a/src/guidellm/data/formatters/templates.py b/src/guidellm/data/formatters/templates.py new file mode 100644 index 00000000..2cf6e2f3 --- /dev/null +++ b/src/guidellm/data/formatters/templates.py @@ -0,0 +1,182 @@ +import textwrap +from typing import Union + +from jinja2 import Template + +from guidellm.utils import RegistryMixin + +__all__ = [ + "DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE", + "DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE", + "DEFAULT_CHAT_COMPLETIONS_TEMPLATE", + "DEFAULT_TEXT_COMPLETIONS_TEMPLATE", + "JinjaTemplatesRegistry", +] + + +class JinjaTemplatesRegistry(RegistryMixin[Union[Template, str]]): + pass + + +DEFAULT_TEXT_COMPLETIONS_TEMPLATE = JinjaTemplatesRegistry.register("text_completions")( + textwrap.dedent(""" + {% set obj = { + "json_body": { + "prompt": ( + text_column[0] + if text_column and text_column|length == 1 + else text_column + ) + } + } %} + + {% if output_tokens_count is defined and output_tokens_count is not none %} + {% do obj["json_body"].update({ + "max_tokens": output_tokens_count, + "max_completion_tokens": output_tokens_count, + "stop": None, + "ignore_eos": True + }) %} + {% elif max_tokens is defined and max_tokens is not none %} + {% do obj["json_body"].update({"max_tokens": max_tokens}) %} + {% elif max_completion_tokens is defined and max_completion_tokens is not none %} + {% do obj["json_body"].update({"max_completion_tokens": max_completion_tokens}) %} + {% endif %} + + {{ obj }} + """).strip() # noqa: E501 +) + +DEFAULT_CHAT_COMPLETIONS_TEMPLATE = JinjaTemplatesRegistry.register("chat_completions")( + textwrap.dedent(""" + {% set obj = { + "json_body": { + "messages": [ + { + "role": "user", + "content": [] + } + ] + } + } %} + + {%- for item in text_column or [] %} + {% do obj["json_body"].messages[0].content.append({"type": "text", "text": item}) %} + {%- endfor %} + + {%- for item in image_column or [] %} + {% do obj["json_body"].messages[0].content.append({ + "type": "image_url", + "image_url": encode_image( + item, + max_size=max_size|default(None), + max_width=max_width|default(None), + max_height=max_height|default(None), + encode_type=image_encode_type|default(encode_type|default(None)) + ) + }) %} + {%- endfor %} + + {%- for item in video_column or [] %} + {% do obj["json_body"].messages[0].content.append({ + "type": "video_url", + "video_url": encode_video( + item, + encode_type=video_encode_type|default(encode_type|default(None)) + ) + }) %} + {%- endfor %} + + {%- for item in audio_column or [] %} + {%- set audio_type, audio_val = encode_audio( + item, + sample_rate=sample_rate|default(None), + max_duration=max_duration|default(None), + encode_type=audio_encode_type|default(encode_type|default(None)) + ) -%} + {% do content_list.append({"type": audio_type, audio_type: audio_val}) %} + {%- endfor %} + + {% if output_tokens_count is defined and output_tokens_count is not none %} + {% do obj["json_body"].update({ + "max_completion_tokens": output_tokens_count, + "stop": None, + "ignore_eos": True + }) %} + {% elif max_tokens is defined and max_tokens is not none %} + {% do obj["json_body"].update({"max_completion_tokens": max_tokens}) %} + {% elif max_completion_tokens is defined and max_completion_tokens is not none %} + {% do obj["json_body"].update({"max_completion_tokens": max_completion_tokens}) %} + {% endif %} + + {{ obj }} + """).strip() # noqa: E501 +) + +DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE = JinjaTemplatesRegistry.register( + "audio_transcriptions" +)( + textwrap.dedent(""" + { + {%- if output_tokens_count_column is defined and output_tokens_count_column is not none -%} + "max_tokens": {{ output_tokens_count_column }}, + "max_completion_tokens": {{ output_tokens_count_column }}, + "stop": None, + "ignore_eos": True, + {%- else -%} + {%- if max_tokens is defined and max_tokens is not none -%} + "max_tokens": {{ max_tokens }}, + {%- endif -%} + {%- if max_completion_tokens is defined and max_completion_tokens is not none -%} + "max_completion_tokens": {{ max_completion_tokens }}, + {%- endif -%} + {%- endif -%} + "files": { + "file": {{ encode_audio_file( + audio_column[0], + encode_type=audio_encode_type|default(encode_type|default(None)) + ) }} + } + {%- if text_column and text_column|length > 0 -%} + , + "json": { + "prompt": {{ text_column[0] }} + } + {%- endif -%} + } + """).strip() # noqa: E501 +) + +DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE = JinjaTemplatesRegistry.register( + "audio_translations" +)( + textwrap.dedent(""" + { + {%- if output_tokens_count_column is defined and output_tokens_count_column is not none -%} + "max_tokens": {{ output_tokens_count_column }}, + "max_completion_tokens": {{ output_tokens_count_column }}, + "stop": None, + "ignore_eos": True, + {%- else -%} + {%- if max_tokens is defined and max_tokens is not none -%} + "max_tokens": {{ max_tokens }}, + {%- endif -%} + {%- if max_completion_tokens is defined and max_completion_tokens is not none -%} + "max_completion_tokens": {{ max_completion_tokens }}, + {%- endif -%} + {%- endif -%} + "files": { + "file": {{ encode_audio_file( + audio_column[0], + encode_type=audio_encode_type|default(encode_type|default(None)) + ) }} + } + {%- if text_column and text_column|length > 0 -%} + , + "json": { + "prompt": {{ text_column[0] }} + } + {%- endif -%} + } + """).strip() # noqa: E501 +) diff --git a/src/guidellm/data/loaders.py b/src/guidellm/data/loaders.py new file mode 100644 index 00000000..ebecdb6f --- /dev/null +++ b/src/guidellm/data/loaders.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +from collections.abc import Callable +from typing import Any, Literal + +from datasets import Dataset, IterableDataset +from torch.utils.data import DataLoader, Sampler +from transformers import PreTrainedTokenizerBase + +from guidellm.data.datasets import GenerativeRequestsDataset +from guidellm.data.formatters import GenerativeRequestFormatter +from guidellm.data.objects import GenerationRequest, GenerativeDatasetArgs +from guidellm.data.preprocessors import ( + DatasetPreprocessor, + GenerativeColumnMapper, +) + +__all__ = ["GenerativeDataLoader", "GenerativeRequestCollator"] + + +class GenerativeRequestCollator: + def __call__( + self, batch: list[dict[Literal["request"], dict[str, Any]]] + ) -> GenerationRequest: + if len(batch) != 1: + raise NotImplementedError( + f"Batch size greater than 1 is not currently supported. " + f"Got batch size: {len(batch)}" + ) + + return GenerationRequest.model_validate(batch[0]["request"]) + + +class GenerativeDataLoader(DataLoader[GenerationRequest]): + def __init__( + self, + data: list[Any], + data_args: list[GenerativeDatasetArgs] | None, + data_samples: int, + processor_factory: Callable[[], PreTrainedTokenizerBase], + column_mapper: GenerativeColumnMapper, + preprocessors: list[DatasetPreprocessor], + request_formatter: GenerativeRequestFormatter, + sampler: Sampler[int] | Literal["shuffle"] | None = None, + collate_fn: GenerativeRequestCollator | None = None, + num_workers: int | None = None, + random_seed: int = 42, + **kwargs: Any, + ): + dataset = GenerativeRequestsDataset.build( + data=data, + data_args=data_args, + data_samples=data_samples, + processor_factory=processor_factory, + column_mapper=column_mapper, + request_formatter=request_formatter, + preprocessors=preprocessors, + random_seed=random_seed, + ) + + if collate_fn is None: + collate_fn = GenerativeRequestCollator() + + # Handle sampler/shuffle logic based on dataset type + if sampler == "shuffle": + shuffle = True + sampler = None + elif isinstance(sampler, str) and sampler != "shuffle": + raise ValueError( + f"Invalid string sampler: {sampler}. " + f"Only 'shuffle' is supported as a string value." + ) + else: + shuffle = False + + if isinstance(dataset, IterableDataset) and sampler is not None: + raise ValueError( + "Samplers are not supported with IterableDataset. " + "Use shuffle=True or apply shuffling to the dataset directly." + ) + elif isinstance(dataset, Dataset) and shuffle: + dataset = dataset.shuffle(seed=random_seed) + shuffle = False + + super().__init__( + dataset=dataset, + batch_size=1, + shuffle=shuffle, + sampler=sampler, + collate_fn=collate_fn, + num_workers=num_workers or 0, + **kwargs, + ) diff --git a/src/guidellm/data/objects.py b/src/guidellm/data/objects.py new file mode 100644 index 00000000..04c5407d --- /dev/null +++ b/src/guidellm/data/objects.py @@ -0,0 +1,230 @@ +from __future__ import annotations + +import uuid +from typing import Any, Literal, get_args + +from pydantic import Field + +from guidellm.scheduler import ( + MeasuredRequestTimings, + SchedulerMessagingPydanticRegistry, +) +from guidellm.utils import StandardBaseDict, StandardBaseModel + +__all__ = [ + "GenerationRequest", + "GenerationRequestArguments", + "GenerationRequestTimings", + "GenerativeDatasetArgs", + "GenerativeDatasetColumnType", + "GenerativeRequestType", +] + + +GenerativeRequestType = Literal[ + "text_completions", + "chat_completions", + "audio_transcriptions", + "audio_translations", +] + +GenerativeDatasetColumnType = Literal[ + "prompt_tokens_count_column", + "output_tokens_count_column", + "text_column", + "image_column", + "video_column", + "audio_column", +] + + +class GenerationRequestArguments(StandardBaseDict): + @classmethod + def model_combine_dict( # noqa: C901, PLR0912 + cls, *arguments: GenerationRequestArguments | dict[str, Any] + ) -> dict[str, Any]: + combined = {} + + for args in arguments: + if ( + url := args.get("url") if isinstance(args, dict) else args.url + ) is not None: + combined["url"] = url + + if ( + path := args.get("path") if isinstance(args, dict) else args.path + ) is not None: + combined["path"] = path + + if ( + method := args.get("method") if isinstance(args, dict) else args.method + ) is not None: + combined["method"] = method + + if ( + stream := args.get("stream") if isinstance(args, dict) else args.stream + ) is not None: + combined["stream"] = stream + + if ( + content_body := ( + args.get("content_body") + if isinstance(args, dict) + else args.content_body + ) + ) is not None: + combined["content_body"] = content_body + + if ( + json_body := ( + args.get("json_body") if isinstance(args, dict) else args.json_body + ) + ) is not None: + if "json_body" not in combined: + combined["json_body"] = {} + combined["json_body"].update(json_body) + + if ( + files := args.get("files") if isinstance(args, dict) else args.files + ) is not None: + if "files" not in combined: + combined["files"] = {} + combined["files"].update(files) + + if ( + params := args.get("params") if isinstance(args, dict) else args.params + ) is not None: + if "params" not in combined: + combined["params"] = {} + combined["params"].update(params) + + if ( + headers := ( + args.get("headers") if isinstance(args, dict) else args.headers + ) + ) is not None: + if "headers" not in combined: + combined["headers"] = {} + combined["headers"].update(headers) + + return combined + + url: str | None = Field( + default=None, + description="The URL endpoint to which the request will be sent.", + ) + path: str | None = Field( + default=None, + description="The path to append to the base URL for the request.", + ) + method: str | None = Field( + default=None, + description="The HTTP method to use for the request (e.g., 'POST', 'GET').", + ) + stream: bool | None = Field( + default=None, + description="Whether to stream the response, if applicable.", + ) + content_body: Any | None = Field( + default=None, + description="Raw content to send in the request body, if applicable.", + ) + json_body: dict[str, Any] | None = Field( + default=None, + description="JSON content to include in the request body, if applicable.", + ) + files: dict[str, Any] | None = Field( + default=None, + description="Files to include in the request, if applicable.", + ) + params: dict[str, Any] | None = Field( + default=None, + description="Query parameters to include in the request URL, if applicable.", + ) + headers: dict[str, str] | None = Field( + default=None, + description="HTTP headers to include in the request, if applicable.", + ) + + +@SchedulerMessagingPydanticRegistry.register() +class GenerationRequest(StandardBaseModel): + """Request model for backend generation operations.""" + + request_id: str = Field( + default_factory=lambda: str(uuid.uuid4()), + description="Unique identifier for the request.", + ) + request_type: GenerativeRequestType | str = Field( + description=( + "Type of request. If url is not provided in arguments, " + "this will be used to determine the request url." + ), + ) + arguments: GenerationRequestArguments = Field( + description=( + "Payload for the request, structured as a dictionary of arguments to pass " + "to the respective backend method. For example, can contain " + "'json', 'headers', 'files', etc." + ) + ) + stats: dict[Literal["prompt_tokens", "output_tokens"], int] = Field( + default_factory=dict, + description="Request statistics including prompt and output token counts.", + ) + + +@SchedulerMessagingPydanticRegistry.register() +@MeasuredRequestTimings.register("generation_request_timings") +class GenerationRequestTimings(MeasuredRequestTimings): + """Timing model for tracking generation request lifecycle events.""" + + timings_type: Literal["generation_request_timings"] = "generation_request_timings" + first_iteration: float | None = Field( + default=None, + description="Unix timestamp when the first generation iteration began.", + ) + last_iteration: float | None = Field( + default=None, + description="Unix timestamp when the last generation iteration completed.", + ) + + +class GenerativeDatasetArgs(StandardBaseDict): + type_: str | None = None + split: str | None = None + prompt_tokens_count_column: str | None = None + output_tokens_count_column: str | None = None + text_column: str | list[str] | None = None + image_column: str | list[str] | None = None + video_column: str | list[str] | None = None + audio_column: str | list[str] | None = None + + def to_kwargs(self) -> dict[str, Any]: + return { + key: value + for key, value in self.model_extra.items() + if not key.endswith("_column") + } + + def get_mapped_columns( + self, + ) -> dict[GenerativeDatasetColumnType | str, str | list[str]]: + column_mapping: dict[GenerativeDatasetColumnType | str, list[str] | None] = {} + + # Add in any non None columns from the fields + for column in get_args(GenerativeDatasetColumnType): + value = getattr(self, column) + if value is not None: + column_mapping[column] = value + + # Enable flexibility for extra columns to be passed through and referenced later + for extra in self.model_extra: + if ( + extra.endswith("_column") + and extra not in column_mapping + and self.model_extra[extra] is not None + ): + column_mapping[extra] = self.model_extra[extra] + + return column_mapping diff --git a/src/guidellm/data/preprocessors/__init__.py b/src/guidellm/data/preprocessors/__init__.py new file mode 100644 index 00000000..039f74a5 --- /dev/null +++ b/src/guidellm/data/preprocessors/__init__.py @@ -0,0 +1,7 @@ +from .mappers import GenerativeColumnMapper +from .objects import DatasetPreprocessor + +__all__ = [ + "DatasetPreprocessor", + "GenerativeColumnMapper", +] diff --git a/src/guidellm/data/preprocessors/mappers.py b/src/guidellm/data/preprocessors/mappers.py new file mode 100644 index 00000000..1792cb7e --- /dev/null +++ b/src/guidellm/data/preprocessors/mappers.py @@ -0,0 +1,115 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any, Literal + +from datasets import Dataset, IterableDataset + +from guidellm.data.objects import ( + GenerativeDatasetArgs, + GenerativeDatasetColumnType, +) +from guidellm.data.preprocessors.objects import DatasetPreprocessor +from guidellm.data.utils import DEFAULT_COLUMN_NAMES + +__all__ = ["ColumnMapping", "GenerativeColumnMapper"] + + +@dataclass +class ColumnMapping: + indices: list[int] + names: list[str] + + +class GenerativeColumnMapper(DatasetPreprocessor): + def __init__(self): + self.datasets: list[Dataset | IterableDataset] | None = None + self.data_args: list[GenerativeDatasetArgs] | None = None + self.column_mappings: ( + dict[GenerativeDatasetColumnType, ColumnMapping | None] | None + ) = None + + def __call__( + self, row: dict[Literal["items"], tuple[dict[str, Any]]] + ) -> dict[str, Any]: + if ( + self.datasets is None + or self.data_args is None + or self.column_mapping is None + ): + raise ValueError("GenerativeColumnMapper not initialized with data.") + + mapped: dict[GenerativeDatasetColumnType, list[Any]] = {} + items = row.pop("items") + + for column_type, column_mapping in self.column_mapping.items(): + mapped[column_type] = [ + items[index].get(name) + for index, name in zip(column_mapping.indices, column_mapping.names) + ] + + return mapped + + def init_data( + self, + datasets: list[Dataset | IterableDataset], + data_args: list[GenerativeDatasetArgs], + ): + self.datasets = datasets + self.data_args = data_args + self.column_mapping = self.generate_column_mapping() + + def generate_column_mapping( + self, + ) -> dict[GenerativeDatasetColumnType, ColumnMapping]: + mappings: dict[GenerativeDatasetColumnType, ColumnMapping] = {} + # Map any columns specified in the GenerativeDatasetArgs first + self._fill_mappings_from_data_args(mappings) + # For standard column types not mapped, fill in first one found from defaults + self._fill_mappings_from_defaults(mappings) + + return mappings + + def _fill_mappings_from_data_args( + self, mappings: dict[GenerativeDatasetColumnType, ColumnMapping] + ): + for index, args in enumerate(self.data_args): + args_column_mappings = args.get_mapped_columns() + for column_type, column_name in args_column_mappings.items(): + if column_type not in mappings: + mappings[column_type] = ColumnMapping(indices=[], names=[]) + column_mapping = mappings[column_type] + + for name in ( + column_name if isinstance(column_name, list) else [column_name] + ): + if name not in self.datasets[index].column_names: + raise ValueError( + f"Column '{name}' not found in dataset columns: " + f"{self.datasets[index].column_names}" + ) + column_mapping.indices.append(index) + column_mapping.names.append(name) + + def _fill_mappings_from_defaults( + self, mappings: dict[GenerativeDatasetColumnType, ColumnMapping] + ): + for column_type, default_names in DEFAULT_COLUMN_NAMES.items(): + if column_type in mappings: + continue + + for index, dataset in enumerate(self.datasets): + for name in default_names: + if name in dataset.column_names: + mappings[column_type] = ColumnMapping( + indices=[index], names=[name] + ) + break + # Check for plural form of the name + if f"{name}s" in dataset.column_names: + mappings[column_type] = ColumnMapping( + indices=[index], names=[f"{name}s"] + ) + break + if column_type in mappings: + break diff --git a/src/guidellm/data/preprocessors/objects.py b/src/guidellm/data/preprocessors/objects.py new file mode 100644 index 00000000..831f944d --- /dev/null +++ b/src/guidellm/data/preprocessors/objects.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +from typing import Any, Protocol, runtime_checkable + +from datasets import Dataset, IterableDataset + +from guidellm.data.objects import GenerativeDatasetArgs + +__all__ = ["DatasetPreprocessor"] + + +@runtime_checkable +class DatasetPreprocessor(Protocol): + def init_data( + self, + datasets: list[Dataset | IterableDataset], + data_args: list[GenerativeDatasetArgs], + ): ... + + def __call__(self, item: dict[str, Any]) -> dict[str, Any]: ... diff --git a/src/guidellm/data/prideandprejudice.txt.gz b/src/guidellm/data/prideandprejudice.txt.gz deleted file mode 100644 index 8c7a10727c239964fff2e203f07318b29108eb2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241795 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

D_NS;t$alj-?%gi;nlcCiQ~!8PmuFG*9~vcZ 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

>}&UF~c4dDD<+)u}95AF?2P4v6^HyDT6fJXk{# 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 X_J@c2{~rJV|NjF3P@u7{S3n8?q;DzF diff --git a/src/guidellm/data/utils.py b/src/guidellm/data/utils.py new file mode 100644 index 00000000..7d53a054 --- /dev/null +++ b/src/guidellm/data/utils.py @@ -0,0 +1,161 @@ +from __future__ import annotations + +import contextlib +import math +from collections.abc import Iterator +from typing import Any, Literal + +from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict + +__all__ = [ + "DEFAULT_COLUMN_NAMES", + "DEFAULT_SPLITS", + "datasets_item_iterator", + "resolve_dataset_split", +] + + +DEFAULT_SPLITS: dict[Literal["train", "calib", "val", "test"], list[str]] = { + "train": [ + "train", + "training", + "train_set", + "training_set", + "train_dataset", + "training_dataset", + "train_data", + "training_data", + "pretrain", + "pretrain_set", + "pretrain_dataset", + "pretrain_data", + "pretraining", + ], + "calib": [ + "calibration", + "calib", + "cal", + "calibration_set", + "calib_set", + "cal_set", + "calibration_dataset", + "calib_dataset", + "cal_set", + "calibration_data", + "calib_data", + "cal_data", + ], + "val": [ + "validation", + "val", + "valid", + "validation_set", + "val_set", + "validation_dataset", + "val_dataset", + "validation_data", + "val_data", + "dev", + "dev_set", + "dev_dataset", + "dev_data", + ], + "test": [ + "test", + "testing", + "test_set", + "testing_set", + "test_dataset", + "testing_dataset", + "test_data", + "testing_data", + "eval", + "eval_set", + "eval_dataset", + "eval_data", + ], +} + + +DEFAULT_COLUMN_NAMES: dict[str, list[str]] = { + "prompt_tokens_count": ["prompt_tokens_count", "input_tokens_count"], + "output_tokens_count": ["output_tokens_count", "completion_tokens_count"], + "text_column": [ + "prompt", + "instruction", + "question", + "input", + "context", + "content", + "conversation", + "turn", + "text", + ], + "image_column": [ + "image", + "picture", + "photo", + "img", + ], + "video_column": [ + "video", + "clip", + "movie", + "footage", + "mp4", + "mov", + "avi", + ], + "audio_column": [ + "audio", + "sound", + "voice", + "speech", + "wav", + "mp3", + ], +} + + +def resolve_dataset_split( + dataset: Dataset | IterableDataset | DatasetDict | IterableDatasetDict, + split: str | None, +) -> Dataset | IterableDataset: + if split is not None and isinstance(dataset, (DatasetDict, IterableDatasetDict)): + if split in dataset: + return dataset[split] + + raise ValueError(f"Requested split '{split}' not found in dataset: {dataset}.") + elif split is not None: + raise ValueError( + f"Requested split '{split}' but dataset has no splits: {dataset}." + ) + + if isinstance(dataset, (Dataset, IterableDataset)): + return dataset + + for _, default_splits in DEFAULT_SPLITS.items(): + for default_split in default_splits: + if default_split in dataset: + return dataset[default_split] + + return dataset[list(dataset.keys())[0]] + + +def datasets_item_iterator( + datasets: list[Dataset | IterableDataset], + data_samples: int, +) -> Iterator[dict[Literal["items"], tuple[dict[str, Any]]]]: + dataset_iters = [iter(dataset) for dataset in datasets] + gen_count = 0 + + with contextlib.suppress(StopIteration): + while gen_count < data_samples or data_samples <= 0 or data_samples == math.inf: + yield {"items": tuple(next(dataset_iter) for dataset_iter in dataset_iters)} + gen_count += 1 + + if gen_count < data_samples and data_samples > 0 and data_samples != math.inf: + raise ValueError( + f"Requested {data_samples} samples, but only {gen_count} available " + "from the provided datasets." + ) diff --git a/src/guidellm/dataset/__init__.py b/src/guidellm/dataset/__init__.py deleted file mode 100644 index b90b72ff..00000000 --- a/src/guidellm/dataset/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -from .creator import ColumnInputTypes, DatasetCreator -from .entrypoints import load_dataset -from .file import FileDatasetCreator -from .hf_datasets import HFDatasetsCreator -from .in_memory import InMemoryDatasetCreator -from .synthetic import ( - SyntheticDatasetConfig, - SyntheticDatasetCreator, - SyntheticTextItemsGenerator, -) - -__all__ = [ - "ColumnInputTypes", - "DatasetCreator", - "FileDatasetCreator", - "HFDatasetsCreator", - "InMemoryDatasetCreator", - "SyntheticDatasetConfig", - "SyntheticDatasetCreator", - "SyntheticTextItemsGenerator", - "load_dataset", -] diff --git a/src/guidellm/dataset/creator.py b/src/guidellm/dataset/creator.py deleted file mode 100644 index a74ec8c0..00000000 --- a/src/guidellm/dataset/creator.py +++ /dev/null @@ -1,213 +0,0 @@ -from abc import ABC, abstractmethod -from pathlib import Path -from typing import Any, Literal, Optional, Union - -from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -__all__ = ["ColumnInputTypes", "DatasetCreator"] - -ColumnInputTypes = Literal[ - "prompt_column", - "text_column", - "prompt_tokens_count_column", - "output_tokens_count_column", -] - - -class DatasetCreator(ABC): - DEFAULT_SPLITS_TRAIN = [ - "train", - "training", - "train_set", - "training_set", - "train_dataset", - "training_dataset", - "train_data", - "training_data", - "pretrain", - "pretrain_set", - "pretrain_dataset", - "pretrain_data", - "pretraining", - ] - DEFAULT_SPLITS_CALIB = [ - "calibration", - "calib", - "cal", - "calibration_set", - "calib_set", - "cal_set", - "calibration_dataset", - "calib_dataset", - "cal_set", - "calibration_data", - "calib_data", - "cal_data", - ] - DEFAULT_SPLITS_VAL = [ - "validation", - "val", - "valid", - "validation_set", - "val_set", - "validation_dataset", - "val_dataset", - "validation_data", - "val_data", - "dev", - "dev_set", - "dev_dataset", - "dev_data", - ] - DEFAULT_SPLITS_TEST = [ - "test", - "testing", - "test_set", - "testing_set", - "test_dataset", - "testing_dataset", - "test_data", - "testing_data", - "eval", - "eval_set", - "eval_dataset", - "eval_data", - ] - DEFAULT_SPLITS_DATASET: dict[str, str] = {} - - @classmethod - def create( - cls, - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], - processor_args: Optional[dict[str, Any]], - random_seed: int = 42, - split_pref_order: Optional[list[str]] = None, - ) -> tuple[Union[Dataset, IterableDataset], dict[ColumnInputTypes, str]]: - if not cls.is_supported(data, data_args): - raise ValueError(f"Unsupported data type: {type(data)} given for {data}. ") - - split = cls.extract_args_split(data_args) - column_mappings = cls.extract_args_column_mappings(data_args) - dataset = cls.handle_create( - data, data_args, processor, processor_args, random_seed - ) - - if isinstance(dataset, (DatasetDict, IterableDatasetDict)): - dataset = cls.extract_dataset_split(dataset, split, split_pref_order) - - if not isinstance(dataset, (Dataset, IterableDataset)): - raise ValueError( - f"Unsupported data type: {type(dataset)} given for {dataset}." - ) - - return dataset, column_mappings - - @classmethod - def extract_args_split(cls, data_args: Optional[dict[str, Any]]) -> str: - split = "auto" - - if data_args and "split" in data_args: - split = data_args["split"] - del data_args["split"] - - return split - - @classmethod - def extract_args_column_mappings( - cls, - data_args: Optional[dict[str, Any]], - ) -> dict[ColumnInputTypes, str]: - columns: dict[ColumnInputTypes, str] = {} - - if data_args: - if "prompt_column" in data_args: - columns["prompt_column"] = data_args["prompt_column"] - del data_args["prompt_column"] - - if "prompt_tokens_count_column" in data_args: - columns["prompt_tokens_count_column"] = data_args[ - "prompt_tokens_count_column" - ] - del data_args["prompt_tokens_count_column"] - - if "output_tokens_count_column" in data_args: - columns["output_tokens_count_column"] = data_args[ - "output_tokens_count_column" - ] - del data_args["output_tokens_count_column"] - - return columns - - @classmethod - def extract_dataset_name( - cls, dataset: Union[Dataset, IterableDataset, DatasetDict, IterableDatasetDict] - ) -> Optional[str]: - if isinstance(dataset, (DatasetDict, IterableDatasetDict)): - dataset = dataset[list(dataset.keys())[0]] - - if isinstance(dataset, (Dataset, IterableDataset)): - if not hasattr(dataset, "info") or not hasattr( - dataset.info, "dataset_name" - ): - return None - - return dataset.info.dataset_name - - raise ValueError(f"Unsupported data type: {type(dataset)} given for {dataset}.") - - @classmethod - def extract_dataset_split( - cls, - dataset: Union[DatasetDict, IterableDatasetDict], - specified_split: Union[Literal["auto"], str] = "auto", - split_pref_order: Optional[Union[Literal["auto"], list[str]]] = "auto", - ) -> Union[Dataset, IterableDataset]: - if not isinstance(dataset, (DatasetDict, IterableDatasetDict)): - raise ValueError( - f"Unsupported data type: {type(dataset)} given for {dataset}." - ) - - if specified_split != "auto": - if specified_split not in dataset: - raise ValueError( - f"Split {specified_split} not found in dataset {dataset}." - ) - - return dataset[specified_split] - - dataset_name = cls.extract_dataset_name(dataset) - - if dataset_name and dataset_name in cls.DEFAULT_SPLITS_DATASET: - return dataset[cls.DEFAULT_SPLITS_DATASET[dataset_name]] - - if split_pref_order == "auto": - split_pref_order = [ - *cls.DEFAULT_SPLITS_TEST, - *cls.DEFAULT_SPLITS_VAL, - *cls.DEFAULT_SPLITS_CALIB, - *cls.DEFAULT_SPLITS_TRAIN, - ] - - for test_split in split_pref_order or []: - if test_split in dataset: - return dataset[test_split] - - return dataset[list(dataset.keys())[0]] - - @classmethod - @abstractmethod - def is_supported(cls, data: Any, data_args: Optional[dict[str, Any]]) -> bool: ... - - @classmethod - @abstractmethod - def handle_create( - cls, - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], - processor_args: Optional[dict[str, Any]], - random_seed: int, - ) -> Union[Dataset, DatasetDict, IterableDataset, IterableDatasetDict]: ... diff --git a/src/guidellm/dataset/entrypoints.py b/src/guidellm/dataset/entrypoints.py deleted file mode 100644 index cf689956..00000000 --- a/src/guidellm/dataset/entrypoints.py +++ /dev/null @@ -1,42 +0,0 @@ -from pathlib import Path -from typing import Any, Optional, Union - -from datasets import Dataset, IterableDataset -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -from guidellm.dataset.creator import ColumnInputTypes -from guidellm.dataset.file import FileDatasetCreator -from guidellm.dataset.hf_datasets import HFDatasetsCreator -from guidellm.dataset.in_memory import InMemoryDatasetCreator -from guidellm.dataset.synthetic import SyntheticDatasetCreator - -__all__ = ["load_dataset"] - - -def load_dataset( - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], - processor_args: Optional[dict[str, Any]], - random_seed: int = 42, - split_pref_order: Optional[list[str]] = None, -) -> tuple[Union[Dataset, IterableDataset], dict[ColumnInputTypes, str]]: - creators = [ - InMemoryDatasetCreator, - SyntheticDatasetCreator, - FileDatasetCreator, - HFDatasetsCreator, - ] - - for creator in creators: - if creator.is_supported(data, data_args): - return creator.create( - data, - data_args, - processor, - processor_args, - random_seed, - split_pref_order, - ) - - raise ValueError(f"Unsupported data type: {type(data)} given for {data}. ") diff --git a/src/guidellm/dataset/file.py b/src/guidellm/dataset/file.py deleted file mode 100644 index 5d6df1d9..00000000 --- a/src/guidellm/dataset/file.py +++ /dev/null @@ -1,92 +0,0 @@ -from pathlib import Path -from typing import Any, Optional, Union - -import pandas as pd # type: ignore[import] -from datasets import ( - Dataset, - DatasetDict, - IterableDataset, - IterableDatasetDict, - load_dataset, -) -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -from guidellm.dataset.creator import DatasetCreator - -__all__ = ["FileDatasetCreator"] - - -class FileDatasetCreator(DatasetCreator): - SUPPORTED_TYPES = { - ".txt", - ".text", - ".csv", - ".json", - ".jsonl", - ".parquet", - ".arrow", - ".hdf5", - ".tar", - } - - @classmethod - def is_supported(cls, data: Any, data_args: Optional[dict[str, Any]]) -> bool: # noqa: ARG003 - if isinstance(data, (str, Path)) and (path := Path(data)).exists(): - # local folder or py file, assume supported - return path.suffix.lower() in cls.SUPPORTED_TYPES - - return False - - @classmethod - def handle_create( - cls, - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], # noqa: ARG003 - processor_args: Optional[dict[str, Any]], # noqa: ARG003 - random_seed: int, # noqa: ARG003 - ) -> Union[Dataset, DatasetDict, IterableDataset, IterableDatasetDict]: - if not isinstance(data, (str, Path)): - raise ValueError(f"Unsupported data type: {type(data)} given for {data}. ") - - path = Path(data) - if not path.exists(): - raise FileNotFoundError(f"File not found: {path}") - - if not path.is_file(): - raise ValueError(f"Unsupported data type: {path} given for {path}. ") - - if path.suffix.lower() not in cls.SUPPORTED_TYPES: - raise ValueError(f"Unsupported file type: {path.suffix} given for {path}. ") - - return cls.load_dataset(path, data_args) - - @classmethod - def load_dataset( - cls, path: Path, data_args: Optional[dict[str, Any]] - ) -> Union[Dataset, IterableDataset]: - if path.suffix.lower() in {".txt", ".text"}: - with path.open("r") as file: - items = file.readlines() - - dataset = Dataset.from_dict({"text": items}, **(data_args or {})) - elif path.suffix.lower() == ".csv": - dataset = load_dataset("csv", data_files=str(path), **(data_args or {})) - elif path.suffix.lower() in {".json", ".jsonl"}: - dataset = load_dataset("json", data_files=str(path), **(data_args or {})) - elif path.suffix.lower() == ".parquet": - dataset = load_dataset("parquet", data_files=str(path), **(data_args or {})) - elif path.suffix.lower() == ".arrow": - dataset = load_dataset("arrow", data_files=str(path), **(data_args or {})) - elif path.suffix.lower() == ".hdf5": - dataset = Dataset.from_pandas(pd.read_hdf(str(path)), **(data_args or {})) - elif path.suffix.lower() == ".db": - dataset = Dataset.from_sql(con=str(path), **(data_args or {})) - elif path.suffix.lower() == ".tar": - dataset = load_dataset( - "webdataset", data_files=str(path), **(data_args or {}) - ) - else: - raise ValueError(f"Unsupported file type: {path.suffix} given for {path}. ") - - return dataset diff --git a/src/guidellm/dataset/hf_datasets.py b/src/guidellm/dataset/hf_datasets.py deleted file mode 100644 index 7f91facd..00000000 --- a/src/guidellm/dataset/hf_datasets.py +++ /dev/null @@ -1,62 +0,0 @@ -from pathlib import Path -from typing import Any, Optional, Union - -from datasets import ( - Dataset, - DatasetDict, - IterableDataset, - IterableDatasetDict, - get_dataset_config_info, - load_dataset, -) -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -from guidellm.dataset.creator import DatasetCreator - -__all__ = ["HFDatasetsCreator"] - - -class HFDatasetsCreator(DatasetCreator): - @classmethod - def is_supported(cls, data: Any, data_args: Optional[dict[str, Any]]) -> bool: # noqa: ARG003 - if isinstance( - data, (Dataset, DatasetDict, IterableDataset, IterableDatasetDict) - ): - # base type is supported - return True - - if isinstance(data, (str, Path)) and (path := Path(data)).exists(): - # local folder or py file, assume supported - return path.is_dir() or path.suffix == ".py" - - if isinstance(data, (str, Path)): - try: - # try to load dataset - return get_dataset_config_info(data) is not None - except Exception: # noqa: BLE001, S110 - pass - - return False - - @classmethod - def handle_create( - cls, - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], # noqa: ARG003 - processor_args: Optional[dict[str, Any]], # noqa: ARG003 - random_seed: int, # noqa: ARG003 - ) -> Union[Dataset, DatasetDict, IterableDataset, IterableDatasetDict]: - if isinstance(data, (str, Path)): - data = load_dataset(data, **(data_args or {})) - elif data_args: - raise ValueError( - f"data_args should not be provided when data is a {type(data)}" - ) - - if isinstance( - data, (Dataset, DatasetDict, IterableDataset, IterableDatasetDict) - ): - return data - - raise ValueError(f"Unsupported data type: {type(data)} given for {data}. ") diff --git a/src/guidellm/dataset/in_memory.py b/src/guidellm/dataset/in_memory.py deleted file mode 100644 index af84f658..00000000 --- a/src/guidellm/dataset/in_memory.py +++ /dev/null @@ -1,132 +0,0 @@ -from collections.abc import Iterable -from pathlib import Path -from typing import Any, Optional, Union - -from datasets import ( - Dataset, - DatasetDict, - IterableDataset, - IterableDatasetDict, -) -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -from guidellm.dataset.creator import DatasetCreator - -__all__ = ["InMemoryDatasetCreator"] - - -class InMemoryDatasetCreator(DatasetCreator): - @classmethod - def is_supported(cls, data: Any, data_args: Optional[dict[str, Any]]) -> bool: # noqa: ARG003 - return isinstance(data, Iterable) and not isinstance(data, str) - - @classmethod - def handle_create( - cls, - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], # noqa: ARG003 - processor_args: Optional[dict[str, Any]], # noqa: ARG003 - random_seed: int, # noqa: ARG003 - ) -> Union[Dataset, DatasetDict, IterableDataset, IterableDatasetDict]: - if not isinstance(data, Iterable): - raise TypeError( - f"Unsupported data format. Expected Iterable[Any], got {type(data)}" - ) - - if not data: - raise ValueError("Data is empty") - - if isinstance(data, dict): - # assume data is a dictionary of columns and values: {"c1": ["i1", "i2"]} - data_dict = cls.format_data_dict(data) - elif isinstance(data[0], dict): # type: ignore[index] - # assume data is a list of dictionaries: [{"c1": "i1"}, {"c1": "i2"}] - data_dict = cls.format_data_iterable_dicts(data) - else: - # assume data is a list of items with no columns: ["i1", "i2"] - data_dict = cls.format_data_iterable_values(data) - - return Dataset.from_dict(data_dict, **(data_args or {})) - - @classmethod - def format_data_dict(cls, data: dict[Any, Any]) -> dict[str, Any]: - if not isinstance(data, dict): - raise TypeError( - f"Unsupported data format. Expected Dict[str, Iterable[Any]], " - f"got {type(data)}" - ) - - if not all( - isinstance(key, str) and isinstance(val, Iterable) - for key, val in data.items() - ): - raise TypeError( - "Unsupported data format. Expected Dict[str, Iterable[Any]], " - f"got {type(data)}" - ) - - samples = len(list(data.values())[0]) - if not all(len(val) == samples for val in data.values()): - raise ValueError( - "Unsupported data format. Not all columns have the same number samples " - f"for {data}" - ) - - return data - - @classmethod - def format_data_iterable_dicts( - cls, data: Iterable[dict[Any, Any]] - ) -> dict[str, Any]: - if not isinstance(data, Iterable): - raise TypeError( - f"Unsupported data format. Expected Iterable[Dict[str, Any]], " - f"got {type(data)}" - ) - - if not all(isinstance(item, dict) for item in data): - raise TypeError( - f"Unsupported data format. Expected Iterable[Dict[str, Any]], " - f"got {type(data)}" - ) - - if not all(isinstance(key, str) for key in data[0]): # type: ignore[index] - raise TypeError( - "Unsupported data format. Expected Dict[str, Any], " - f"but one of the items had a non string column for {data}" - ) - - columns = list(data[0].keys()) # type: ignore[index] - if not all( - len(item) == len(columns) and all(key in item for key in columns) - for item in data - ): - raise ValueError( - "Unsupported data format. Not all items have the same columns " - f"for {data}" - ) - - data_dict: dict[str, Any] = {key: [] for key in columns} - for item in data: - for key, value in item.items(): - data_dict[key].append(value) - - return data_dict - - @classmethod - def format_data_iterable_values(cls, data: Iterable[Any]) -> dict[str, Any]: - if not isinstance(data, Iterable): - raise TypeError( - f"Unsupported data format. Expected Iterable[Iterable[Any]], " - f"got {type(data)}" - ) - - first_item = next(iter(data), None) - first_type = type(first_item) - if not all(isinstance(item, first_type) for item in data): - raise TypeError( - f"Unsupported data format. Not all types are the same for {data}" - ) - - return {"data": list(data)} diff --git a/src/guidellm/dataset/synthetic.py b/src/guidellm/dataset/synthetic.py deleted file mode 100644 index 8c30f0f7..00000000 --- a/src/guidellm/dataset/synthetic.py +++ /dev/null @@ -1,287 +0,0 @@ -import json -import random -from collections.abc import Iterable, Iterator -from itertools import cycle -from pathlib import Path -from typing import Any, Literal, Optional, Union - -import yaml -from datasets import ( - Dataset, - DatasetDict, - IterableDataset, - IterableDatasetDict, -) -from pydantic import BaseModel, Field -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -from guidellm.dataset.creator import ColumnInputTypes, DatasetCreator -from guidellm.utils import EndlessTextCreator, IntegerRangeSampler, check_load_processor - -__all__ = [ - "SyntheticDatasetConfig", - "SyntheticDatasetCreator", - "SyntheticTextItemsGenerator", -] - - -class SyntheticDatasetConfig(BaseModel): - prefix_tokens: int = Field( - description="The number of shared prefix tokens to prepend to each prompt.", - ge=0, - default=0, - ) - prompt_tokens: int = Field( - description="The average number of text tokens generated for prompts.", - gt=0, - ) - prompt_tokens_stdev: Optional[int] = Field( - description="The standard deviation of the tokens generated for prompts.", - gt=0, - default=None, - ) - prompt_tokens_min: Optional[int] = Field( - description="The minimum number of text tokens generated for prompts.", - gt=0, - default=None, - ) - prompt_tokens_max: Optional[int] = Field( - description="The maximum number of text tokens generated for prompts.", - gt=0, - default=None, - ) - output_tokens: int = Field( - description="The average number of text tokens generated for outputs.", - gt=0, - ) - output_tokens_stdev: Optional[int] = Field( - description="The standard deviation of the tokens generated for outputs.", - gt=0, - default=None, - ) - output_tokens_min: Optional[int] = Field( - description="The minimum number of text tokens generated for outputs.", - gt=0, - default=None, - ) - output_tokens_max: Optional[int] = Field( - description="The maximum number of text tokens generated for outputs.", - gt=0, - default=None, - ) - samples: int = Field( - description="The number of samples to generate for the dataset.", - gt=0, - default=1000, - ) - source: str = Field( - description="The source of the text data to be used for generation.", - default="data:prideandprejudice.txt.gz", - ) - - @staticmethod - def parse_str(data: Union[str, Path]) -> "SyntheticDatasetConfig": - if ( - isinstance(data, Path) - or data.strip().endswith(".config") - or data.strip().endswith(".yaml") - ): - return SyntheticDatasetConfig.parse_config_file(data) - - if data.strip().startswith("{"): - return SyntheticDatasetConfig.parse_json(data) - - if data.count("=") > 1: - return SyntheticDatasetConfig.parse_key_value_pairs(data) - - raise ValueError( - f"Unsupported data format. Expected JSON or key-value pairs, got {data}" - ) - - @staticmethod - def parse_json(data: str) -> "SyntheticDatasetConfig": - config_dict = json.loads(data.strip()) - - return SyntheticDatasetConfig(**config_dict) - - @staticmethod - def parse_key_value_pairs(data: str) -> "SyntheticDatasetConfig": - config_dict = {} - items = data.strip().split(",") - for item in items: - key, value = item.split("=") - config_dict[key.strip()] = ( - int(value.strip()) if value.strip().isnumeric() else value.strip() - ) - - return SyntheticDatasetConfig(**config_dict) # type: ignore[arg-type] - - @staticmethod - def parse_config_file(data: Union[str, Path]) -> "SyntheticDatasetConfig": - with Path(data).open("r") as file: - config_dict = yaml.safe_load(file) - - return SyntheticDatasetConfig(**config_dict) - - -class SyntheticTextItemsGenerator( - Iterable[ - dict[ - Literal["prompt", "prompt_tokens_count", "output_tokens_count"], - Union[str, int], - ] - ] -): - def __init__( - self, - config: SyntheticDatasetConfig, - processor: PreTrainedTokenizerBase, - random_seed: int, - ): - self.config = config - self.processor = processor - self.random_seed = random_seed - self.text_creator = EndlessTextCreator( - data=config.source, - ) - - def __iter__( - self, - ) -> Iterator[ - dict[ - Literal["prompt", "prompt_tokens_count", "output_tokens_count"], - Union[str, int], - ] - ]: - prompt_tokens_sampler = IntegerRangeSampler( - average=self.config.prompt_tokens, - variance=self.config.prompt_tokens_stdev, - min_value=self.config.prompt_tokens_min, - max_value=self.config.prompt_tokens_max, - random_seed=self.random_seed, - ) - output_tokens_sampler = IntegerRangeSampler( - average=self.config.output_tokens, - variance=self.config.output_tokens_stdev, - min_value=self.config.output_tokens_min, - max_value=self.config.output_tokens_max, - random_seed=self.random_seed + 1, # ensure diff dist from prompts - ) - # ensure diff distribution from output tokens - rand = random.Random(self.random_seed + 2) # noqa: S311 - unique_prefix_iter = cycle(self.processor.get_vocab().values()) - - prefix_index = rand.randint(0, len(self.text_creator.words)) - prefix_tokens = self._create_prompt(self.config.prefix_tokens, prefix_index) - - for _, prompt_tokens, output_tokens in zip( - range(self.config.samples), - prompt_tokens_sampler, - output_tokens_sampler, - ): - start_index = rand.randint(0, len(self.text_creator.words)) - prompt_text = self.processor.decode( - prefix_tokens - + self._create_prompt( - prompt_tokens, start_index, next(unique_prefix_iter) - ), - skip_special_tokens=True, - ) - yield { - "prompt": prompt_text, - "prompt_tokens_count": self.config.prefix_tokens + prompt_tokens, - "output_tokens_count": output_tokens, - } - - def _create_prompt( - self, prompt_tokens: int, start_index: int, unique_prefix: Optional[int] = None - ) -> list[int]: - if prompt_tokens <= 0: - return [] - - left = start_index - right = start_index + 4 * prompt_tokens - start_tokens = [unique_prefix] if unique_prefix else [] - - while left < right: - mid = (left + right) // 2 - test_prompt = self.text_creator.create_text(start_index, mid - start_index) - test_tokens = start_tokens + self.processor.encode(test_prompt) - - if len(test_tokens) == prompt_tokens: - return test_tokens - elif len(test_tokens) < prompt_tokens: - left = mid + 1 - else: - right = mid - - final_text = self.text_creator.create_text(start_index, left - start_index) - return start_tokens + self.processor.encode(final_text) - - -class SyntheticDatasetCreator(DatasetCreator): - @classmethod - def is_supported( - cls, - data: Any, - data_args: Optional[dict[str, Any]], # noqa: ARG003 - ) -> bool: - if ( - isinstance(data, Path) - and data.exists() - and data.suffix in {".config", ".yaml"} - ): - return True - - if isinstance(data, str): - data_str: str = data.strip() - if ( - data_str.startswith("{") - or data_str.count("=") > 1 - or data_str.endswith((".config", ".yaml")) - ): - return True - - return False - - @classmethod - def handle_create( - cls, - data: Any, - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], - processor_args: Optional[dict[str, Any]], - random_seed: int, - ) -> Union[Dataset, DatasetDict, IterableDataset, IterableDatasetDict]: - processor = check_load_processor( - processor, - processor_args, - error_msg=( - "Processor/tokenizer required for synthetic dataset generation." - ), - ) - - config = SyntheticDatasetConfig.parse_str(data) - generator = SyntheticTextItemsGenerator(config, processor, random_seed) - items = list(generator) - - return Dataset.from_list(items, **(data_args or {})) - - @classmethod - def extract_args_column_mappings( - cls, - data_args: Optional[dict[str, Any]], - ) -> dict[ColumnInputTypes, str]: - data_args_columns = super().extract_args_column_mappings(data_args) - - if data_args_columns: - raise ValueError( - f"Column mappings are not supported for synthetic datasets. " - f"Got {data_args_columns}" - ) - - return { - "prompt_column": "prompt", - "prompt_tokens_count_column": "prompt_tokens_count", - "output_tokens_count_column": "output_tokens_count", - } diff --git a/src/guidellm/logger.py b/src/guidellm/logger.py index 70259bad..da3464f9 100644 --- a/src/guidellm/logger.py +++ b/src/guidellm/logger.py @@ -72,7 +72,7 @@ def configure_logger(config: LoggingSettings = settings.logging): sys.stdout, level=config.console_log_level.upper(), format="{time:YY-MM-DD HH:mm:ss}|{level: <8} \ - |{name}:{function}:{line} - {message}" + |{name}:{function}:{line} - {message}", ) if config.log_file or config.log_file_level: diff --git a/src/guidellm/preprocess/dataset.py b/src/guidellm/preprocess/dataset.py index a94b8a14..9d65dcd6 100644 --- a/src/guidellm/preprocess/dataset.py +++ b/src/guidellm/preprocess/dataset.py @@ -11,7 +11,6 @@ from pydantic import BaseModel, Field from transformers import PreTrainedTokenizerBase -from guidellm.dataset import load_dataset as guidellm_load_dataset from guidellm.utils import IntegerRangeSampler, check_load_processor from guidellm.utils.hf_datasets import SUPPORTED_TYPES, save_dataset_to_file @@ -239,7 +238,7 @@ def process_dataset( prompt_tokens: Union[str, Path], output_tokens: Union[str, Path], processor_args: Optional[dict[str, Any]] = None, - data_args: Optional[dict[str, Any]] = None, + data_args: Optional[dict[str, Any]] = None, # noqa: ARG001 short_prompt_strategy: ShortPromptStrategy = ShortPromptStrategy.IGNORE, pad_char: Optional[str] = None, concat_delimiter: Optional[str] = None, @@ -271,9 +270,7 @@ def process_dataset( f"Starting dataset conversion | Input: {data} | Output directory: {output_path}" ) - dataset, column_mappings = guidellm_load_dataset( - data, data_args, processor, processor_args - ) + dataset, column_mappings = None, None tokenizer = check_load_processor( processor, processor_args, diff --git a/src/guidellm/request/__init__.py b/src/guidellm/request/__init__.py deleted file mode 100644 index 85b447d6..00000000 --- a/src/guidellm/request/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -from .loader import ( - GenerativeRequestLoader, - GenerativeRequestLoaderDescription, - RequestLoader, - RequestLoaderDescription, -) -from .request import GenerationRequest -from .types import RequestT, ResponseT - -__all__ = [ - "GenerationRequest", - "GenerativeRequestLoader", - "GenerativeRequestLoaderDescription", - "RequestLoader", - "RequestLoaderDescription", - "RequestT", - "ResponseT", -] diff --git a/src/guidellm/request/loader.py b/src/guidellm/request/loader.py deleted file mode 100644 index 607a7455..00000000 --- a/src/guidellm/request/loader.py +++ /dev/null @@ -1,284 +0,0 @@ -from abc import abstractmethod -from collections.abc import Iterable, Iterator -from pathlib import Path -from typing import ( - Any, - Literal, - Optional, - Union, -) - -from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict -from transformers import PreTrainedTokenizerBase # type: ignore[import] - -from guidellm.dataset import ColumnInputTypes, load_dataset -from guidellm.request.request import GenerationRequest -from guidellm.settings import settings -from guidellm.utils import StandardBaseModel - -__all__ = [ - "GenerativeRequestLoader", - "GenerativeRequestLoaderDescription", - "RequestLoader", - "RequestLoaderDescription", -] - - -class RequestLoaderDescription(StandardBaseModel): - type_: Literal["request_loader"] = "request_loader" - - -class RequestLoader(Iterable): - @abstractmethod - def __iter__(self) -> Iterator: ... - - @abstractmethod - def __len__(self) -> int: ... - - @property - @abstractmethod - def description(self) -> RequestLoaderDescription: ... - - -class GenerativeRequestLoaderDescription(RequestLoaderDescription): - type_: Literal["generative_request_loader"] = "generative_request_loader" # type: ignore[assignment] - data: str - data_args: Optional[dict[str, Any]] - processor: str - processor_args: Optional[dict[str, Any]] - - -class GenerativeRequestLoader(RequestLoader): - DEFAULT_PROMPT_COLUMNS = [ - "prompt", - "prompts", - "instruction", - "instructions", - "question", - "questions", - "input", - "inputs", - "context", - "content", - "conversation", - "conversations", - "turn", - "turns", - "text", - ] - - def __init__( - self, - data: Union[ - str, - Path, - Iterable[Union[str, dict[str, Any]]], - Dataset, - DatasetDict, - IterableDataset, - IterableDatasetDict, - ], - data_args: Optional[dict[str, Any]], - processor: Optional[Union[str, Path, PreTrainedTokenizerBase]], - processor_args: Optional[dict[str, Any]], - shuffle: bool = True, - iter_type: Literal["finite", "infinite"] = "finite", - random_seed: int = 42, - ): - self.data = data - self.data_args = data_args - dataset, args_column_mappings = load_dataset( - data, - data_args, - processor, - processor_args, - random_seed, - ) - self.dataset = dataset - self.processor = processor - self.processor_args = processor_args - self.shuffle = shuffle - self.iter_type = iter_type - self.random_seed = random_seed - - self.column_mappings = self._create_column_mappings(args_column_mappings) - self.preserve_iter_state = iter_type == "infinite" # ensure no caching requests - self._preserved_iter = None - - def __iter__(self) -> Iterator[GenerationRequest]: - scope_create_count = 0 - - while (dataset_iter := self._get_dataset_iter(scope_create_count)) is not None: - scope_create_count += 1 - - for item in dataset_iter: - yield self._create_request(item) - - self._preserved_iter = None - - def __len__(self) -> int: - if self.iter_type == "finite": - return self.num_unique_items() - - raise ValueError(f"Unable to determine length of dataset: {self.data}") - - @property - def description(self) -> GenerativeRequestLoaderDescription: - return GenerativeRequestLoaderDescription( - data=str(self.data), - data_args=self.data_args, - processor=str(self.processor), - processor_args=self.processor_args, - ) - - def num_unique_items(self, raise_err: bool = True) -> int: - try: - return len(self.dataset) - except Exception: # noqa: BLE001, S110 - pass - - dataset_size = self.dataset.info.dataset_size - if dataset_size is not None: - return dataset_size - - if raise_err: - raise ValueError("Unable to determine number of items in the dataset") - - return -1 - - def _create_column_mappings( - self, - args_column_mappings: dict[ColumnInputTypes, str], - ) -> dict[ColumnInputTypes, str]: - column_mappings: dict[ColumnInputTypes, str] = {} - - if "text_column" in args_column_mappings: - column_mappings["prompt_column"] = args_column_mappings["text_column"] - else: - column_mappings["prompt_column"] = self._extract_text_column() - - if "prompt_tokens_count_column" in args_column_mappings: - column_mappings["prompt_tokens_count_column"] = args_column_mappings[ - "prompt_tokens_count_column" - ] - elif prompt_tokens_count_column := self._extract_prompt_tokens_count_column(): - column_mappings["prompt_tokens_count_column"] = prompt_tokens_count_column - - if "output_tokens_count_column" in args_column_mappings: - column_mappings["output_tokens_count_column"] = args_column_mappings[ - "output_tokens_count_column" - ] - elif output_tokens_count_column := self._extract_output_tokens_count_column(): - column_mappings["output_tokens_count_column"] = output_tokens_count_column - - return column_mappings - - def _extract_text_column(self) -> str: - column_names = self._dataset_columns( - err_msg=( - "Unable to determine text column from dataset and it is required. " - "To specify the text column, set the 'text_column' key in the " - "'data_args' dictionary." - ) - ) - - if not column_names: - raise ValueError( - "Unable to determine text column from dataset and it is required. " - "To specify the text column, set the 'text_column' key in the " - "'data_args' dictionary." - ) - - if len(column_names) == 1: - return column_names[0] - - for def_column in self.DEFAULT_PROMPT_COLUMNS: - if def_column in column_names: - return def_column - - raise ValueError( - f"Unable to determine text column from dataset columns: {column_names}. " - "To specify the text column, set the 'text_column' key in the " - "'data_args' dictionary." - ) - - def _extract_prompt_tokens_count_column(self) -> Optional[str]: - column_names = self._dataset_columns() - - if column_names and "prompt_tokens_count" in column_names: - return "prompt_tokens_count" - - if column_names and "prompt_tokens" in column_names: - return "prompt_tokens" - - return None - - def _extract_output_tokens_count_column(self) -> Optional[str]: - column_names = self._dataset_columns() - - if column_names and "output_tokens_count" in column_names: - return "output_tokens_count" - - if column_names and "output_tokens" in column_names: - return "output_tokens" - - return None - - def _dataset_columns(self, err_msg: Optional[str] = None) -> Optional[list[str]]: - try: - column_names = self.dataset.column_names - - if not column_names and err_msg: - raise ValueError(f"No column names found in dataset: {self.data}") - except Exception as err: - if err_msg: - raise ValueError(err_msg) from err - - column_names = None - - return column_names - - def _get_dataset_iter( - self, scope_create_count: int - ) -> Optional[Iterator[dict[str, Any]]]: - if scope_create_count > 0 and self.iter_type != "infinite": - return None - - if self.preserve_iter_state and self._preserved_iter is not None: - return self._preserved_iter - - dataset = ( - self.dataset - if not self.shuffle - else self.dataset.shuffle(seed=self.random_seed) - ) - - dataset_iter = iter(dataset) - - if self.preserve_iter_state: - self._preserved_iter = dataset_iter - - return dataset_iter - - def _create_request(self, item: dict[str, Any]) -> GenerationRequest: - prompt_tokens = ( - item[self.column_mappings["prompt_tokens_count_column"]] - if "prompt_tokens_count_column" in self.column_mappings - else None - ) - output_tokens = ( - item[self.column_mappings["output_tokens_count_column"]] - if "output_tokens_count_column" in self.column_mappings - else None - ) - - return GenerationRequest( - request_type=settings.preferred_route, - content=item[self.column_mappings["prompt_column"]], - stats=( - {"prompt_tokens": prompt_tokens} if prompt_tokens is not None else {} - ), - constraints=( - {"output_tokens": output_tokens} if output_tokens is not None else {} - ), - ) diff --git a/src/guidellm/request/request.py b/src/guidellm/request/request.py deleted file mode 100644 index bf4e59fb..00000000 --- a/src/guidellm/request/request.py +++ /dev/null @@ -1,79 +0,0 @@ -import uuid -from typing import Any, Literal, Optional - -from pydantic import Field - -from guidellm.utils import StandardBaseModel - -__all__ = ["GenerationRequest"] - - -class GenerationRequest(StandardBaseModel): - """ - A class representing a request for generation. - This class is used to encapsulate the details of a generation request, - including the request ID, type, content, parameters, statistics, and constraints. - It is designed to be used with the BackendRequestsWorker class to handle - the generation process. - - :param request_id: The unique identifier for the request. - :param request_type: The type of request (e.g., text, chat). - :param content: The content for the request to send to the backend. - If request_type is 'text', this should be a string or list of strings - which will be resolved by backend.text_completions. - If request_type is 'chat', this should be a string, - a list of (str, Dict[str, Union[str, Dict[str, str]], Path, Image]), - or Any raw content which will be resolved by backend.chat_completions. - If raw content, raw_content=True must be passed in the params. - :param params: Additional parameters for the request passed in as kwargs. - For an http backend, these are passed into the body of the request. - :param stats: Statistics for the request, such as the number of prompt tokens. - Used for tracking and reporting purposes. - :param constraints: Constraints for the request, such as the maximum number - of output tokens. Used for controlling the behavior of the backend. - """ - - request_id: Optional[str] = Field( - default_factory=lambda: str(uuid.uuid4()), - description="The unique identifier for the request.", - ) - request_type: Literal["text_completions", "chat_completions"] = Field( - default="text_completions", - description=( - "The type of request (e.g., text, chat). " - "If request_type='text_completions', resolved by backend.text_completions. " - "If request_typ='chat_completions', resolved by backend.chat_completions." - ), - ) - content: Any = Field( - description=( - "The content for the request to send to the backend. " - "If request_type is 'text', this should be a string or list of strings " - "which will be resolved by backend.text_completions. " - "If request_type is 'chat', this should be a string, " - "a list of (str, Dict[str, Union[str, Dict[str, str]], Path, Image]), " - "or Any raw content which will be resolved by backend.chat_completions. " - "If raw content, raw_content=True must be passed in the params." - ) - ) - params: dict[str, Any] = Field( - default_factory=dict, - description=( - "Additional parameters for the request that will be passed in as kwargs. " - "For an http backend, these are passed into the body of the request. " - ), - ) - stats: dict[Literal["prompt_tokens"], int] = Field( - default_factory=dict, - description=( - "Statistics for the request, such as the number of prompt tokens. " - "Used for tracking and reporting purposes." - ), - ) - constraints: dict[Literal["output_tokens"], int] = Field( - default_factory=dict, - description=( - "Constraints for the request, such as the maximum number of output tokens. " - "Used for controlling the behavior of the backend." - ), - ) diff --git a/src/guidellm/request/types.py b/src/guidellm/request/types.py deleted file mode 100644 index f82493be..00000000 --- a/src/guidellm/request/types.py +++ /dev/null @@ -1,10 +0,0 @@ -from typing import TypeVar - -__all__ = [ - "RequestT", - "ResponseT", -] - - -RequestT = TypeVar("RequestT") -ResponseT = TypeVar("ResponseT") diff --git a/src/guidellm/scheduler/scheduler.py b/src/guidellm/scheduler/scheduler.py index e7d8b2c6..d9bb7c23 100644 --- a/src/guidellm/scheduler/scheduler.py +++ b/src/guidellm/scheduler/scheduler.py @@ -124,7 +124,7 @@ async def run( # Setup the worker group, sync start with the environment worker_group = WorkerProcessGroup[RequestT, ResponseT]( - requests=None, + requests=local_requests, cycle_requests=local_requests, backend=backend, strategy=local_strategy, diff --git a/src/guidellm/scheduler/worker_group.py b/src/guidellm/scheduler/worker_group.py index c1d516f1..e64d64fc 100644 --- a/src/guidellm/scheduler/worker_group.py +++ b/src/guidellm/scheduler/worker_group.py @@ -98,10 +98,9 @@ def __init__( :raises ValueError: If neither requests nor cycle_requests are provided, or if cycle_requests is an Iterator rather than Iterable """ - if not requests and not cycle_requests: + if requests is None and cycle_requests is None: raise ValueError( "At least one of 'requests' or 'cycle_requests' must be provided. " - f"Got requests: {requests}, cycle_requests: {cycle_requests}" ) if isinstance(cycle_requests, Iterator): @@ -487,10 +486,10 @@ def requests_generator( """ def _iter(): - if requests: + if requests is not None: yield from requests - if cycle_requests: + if cycle_requests is not None: while True: yield from cycle_requests @@ -512,6 +511,8 @@ def _iter(): scheduler_start_time=self.start_time, ) state_update = self._locked_update(request_info) + request_info.scheduler_timings.queued = time.time() + yield (request, request_info) if state_update.stop_queueing: From dd7a4b884f821da37e7a1c36cd9d9accf61d961a Mon Sep 17 00:00:00 2001 From: Samuel Monson Date: Fri, 3 Oct 2025 17:00:00 -0400 Subject: [PATCH 2/3] [GuideLLM Refactor] Advanced Prefix Cache Controls (#382) ## TODO - Docs - ~CSV arg string support~ CSV arg string now supports single bucket (see last example). Might leave it at that for now. - More validation ## Summary This PR is a port of #287 to the v0.4.0 refactor branch. Adds controls for sharing one or more fixed prefixes between samples. See examples bellow. ## Details Adds a `prefix_buckets` argument to the `SyntheticTextDatasetConfig`, each bucket consists of a prefix count, token count, and bucket weight. Prefix count sets the number of unique prefixes to generate for a given bucket, token count is the length of each prompt in the bucket, and bucket weight is used to calculate the proportion of requests the bucket applies to relative to the sum of all bucket weights. Here are a few examples: Here we have one bucket of 32 prefixes of length 2048. Since there are 1024 total samples each prefix will apply to 32 samples. If there is only one bucket than weight can be omitted as the bucket applies to 100% of samples. ```yaml data: prefix_buckets: - prefix_tokens: 2048 prefix_count: 32 prompt_tokens: 256 output_tokens: 256 samples: 1024 ``` In this modified version of the first example 16 of the prompts have 2048 tokens while the other 16 have 1024 tokens. ```yaml data: prefix_buckets: - prefix_tokens: 2048 prefix_count: 16 bucket_weight: 50 - prefix_tokens: 1024 prefix_count: 16 bucket_weight: 50 prompt_tokens: 256 output_tokens: 256 samples: 1024 ``` The prefix tokens of a bucket can also be 0 to disable prefixes for those samples. Here is an example where 40% of the samples have a prefix of 2048 tokens while the other 60% have no prefix. ```yaml data: prefix_buckets: - prefix_tokens: 2048 bucket_weight: 40 - prefix_tokens: 0 bucket_weight: 60 prompt_tokens: 256 output_tokens: 256 samples: 1000 ``` If only a single bucket is needed, it can be set at the top level. This make the changes backwards compatible with the previous interface and allows the CSV string format to work without parsing nested structures (at least for this use-case). ```yaml data: prefix_tokens: 128 prefix_count: 10 prompt_tokens: 256 output_tokens: 256 samples: 1000 ``` ## Test Plan - PR includes unit tests for all synthetic dataset changes (`pytest tests/unit/dataset`) - Scenearios in the Details section can be used against a model server with prefix caching and the cache rate can be confirmed by inspecting console output. ## Related Issues - Resolves #232 - Closes #287 --- - [x] "I certify that all code in this PR is my own, except as noted below." ## Use of AI - [x] Includes AI-assisted code completion - [ ] Includes code generated by an AI application - [x] Includes AI-generated tests (NOTE: AI written tests should have a docstring that includes `## WRITTEN BY AI ##`) --------- Signed-off-by: Samuel Monson --- pylock.toml | 2465 +++++++++-------- pyproject.toml | 9 + src/guidellm/data/deserializers/__init__.py | 2 + src/guidellm/data/deserializers/synthetic.py | 96 +- src/guidellm/data/formatters/templates.py | 16 +- src/guidellm/data/objects.py | 2 + src/guidellm/data/utils.py | 5 + tests/unit/{dataset => data}/__init__.py | 0 tests/unit/data/deserializers/__init__.py | 0 .../unit/data/deserializers/test_synthetic.py | 587 ++++ tests/unit/dataset/test_synthetic.py | 873 ------ 11 files changed, 2035 insertions(+), 2020 deletions(-) rename tests/unit/{dataset => data}/__init__.py (100%) create mode 100644 tests/unit/data/deserializers/__init__.py create mode 100644 tests/unit/data/deserializers/test_synthetic.py delete mode 100644 tests/unit/dataset/test_synthetic.py diff --git a/pylock.toml b/pylock.toml index 2fa1b28e..4c6468c2 100644 --- a/pylock.toml +++ b/pylock.toml @@ -3,8 +3,8 @@ lock-version = "1.0" requires-python = "<4.0,>=3.9.0" environments = [ - "python_version ~= \"3.10\"", - "python_version < \"3.10\" and python_version >= \"3.9\"", + "python_version ~= \"3.12\"", + "python_version < \"3.12\" and python_version >= \"3.9\"", ] extras = ["dev", "recommended"] dependency-groups = ["default"] @@ -44,6 +44,24 @@ dependencies = [ "tomli>=2.0.1; python_version < \"3.11\"", ] +[[packages]] +name = "blobfile" +version = "3.1.0" +requires-python = ">=3.8.0" +sdist = {name = "blobfile-3.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/f0/6d/2e7567da75ddbb24fe979f52284b708da349d67a41042635af36071a5a6b/blobfile-3.1.0.tar.gz", hashes = {sha256 = "d45b6b1fa3b0920732314c23ddbdb4f494ca12f787c2b6eb6bba6faa51382671"}} +wheels = [ + {name = "blobfile-3.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/77/a7/51af11120d75af2828f8eede0b13a4caff650d708ac50e62d000aefe1ffb/blobfile-3.1.0-py3-none-any.whl",hashes = {sha256 = "2b4c5e766ebb7dfa20e4990cf6ec3d2106bdc91d632fb9377f170a234c5a5c6a"}}, +] +marker = "\"recommended\" in extras" + +[packages.tool.pdm] +dependencies = [ + "pycryptodomex>=3.8", + "urllib3<3,>=1.25.3", + "lxml>=4.9", + "filelock>=3.0", +] + [[packages]] name = "build" version = "1.2.2.post1" @@ -63,6 +81,21 @@ dependencies = [ "tomli>=1.1.0; python_version < \"3.11\"", ] +[[packages]] +name = "culsans" +version = "0.9.0" +requires-python = ">=3.8" +sdist = {name = "culsans-0.9.0.tar.gz", url = "https://files.pythonhosted.org/packages/90/5d/12e7e16b0caafaa8cca0728dd817204afd1274ddb35531b029b1c5cf7b2a/culsans-0.9.0.tar.gz", hashes = {sha256 = "942dd3c3c77f20e9ac3383d9a5ef8b7b24c0dac1a593bdb20d46c8a38720a5f3"}} +wheels = [ + {name = "culsans-0.9.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/6f/b4/1e3cccb48f09e89e0cfc06925182cbcd36abf80b8eda2489430b41c7eaff/culsans-0.9.0-py3-none-any.whl",hashes = {sha256 = "d3537b65bbb341c2ac72e7d152deb8ab893b2a00452d2a68702a1a1a41619d6f"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "aiologic>=0.13.0", +] + [[packages]] name = "ftfy" version = "6.3.1" @@ -78,6 +111,118 @@ dependencies = [ "wcwidth", ] +[[packages]] +name = "librosa" +version = "0.11.0" +requires-python = ">=3.8" +sdist = {name = "librosa-0.11.0.tar.gz", url = "https://files.pythonhosted.org/packages/64/36/360b5aafa0238e29758729e9486c6ed92a6f37fa403b7875e06c115cdf4a/librosa-0.11.0.tar.gz", hashes = {sha256 = "f5ed951ca189b375bbe2e33b2abd7e040ceeee302b9bbaeeffdfddb8d0ace908"}} +wheels = [ + {name = "librosa-0.11.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b5/ba/c63c5786dfee4c3417094c4b00966e61e4a63efecee22cb7b4c0387dda83/librosa-0.11.0-py3-none-any.whl",hashes = {sha256 = "0b6415c4fd68bff4c29288abe67c6d80b587e0e1e2cfb0aad23e4559504a7fa1"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "audioread>=2.1.9", + "numba>=0.51.0", + "numpy>=1.22.3", + "scipy>=1.6.0", + "scikit-learn>=1.1.0", + "joblib>=1.0", + "decorator>=4.3.0", + "soundfile>=0.12.1", + "pooch>=1.1", + "soxr>=0.3.2", + "typing-extensions>=4.1.1", + "lazy-loader>=0.1", + "msgpack>=1.0", + "standard-aifc; python_version >= \"3.13\"", + "standard-sunau; python_version >= \"3.13\"", +] + +[[packages]] +name = "scipy" +version = "1.15.3" +requires-python = ">=3.10" +sdist = {name = "scipy-1.15.3.tar.gz", url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hashes = {sha256 = "eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"}} +wheels = [ + {name = "scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759"}}, + {name = "scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl",hashes = {sha256 = "7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62"}}, + {name = "scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl",hashes = {sha256 = "8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb"}}, + {name = "scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl",hashes = {sha256 = "0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730"}}, + {name = "scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825"}}, + {name = "scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7"}}, + {name = "scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11"}}, + {name = "scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126"}}, + {name = "scipy-1.15.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163"}}, + {name = "scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8"}}, + {name = "scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl",hashes = {sha256 = "6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5"}}, + {name = "scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl",hashes = {sha256 = "50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e"}}, + {name = "scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl",hashes = {sha256 = "14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb"}}, + {name = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723"}}, + {name = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb"}}, + {name = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4"}}, + {name = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5"}}, + {name = "scipy-1.15.3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca"}}, + {name = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/37/4b/683aa044c4162e10ed7a7ea30527f2cbd92e6999c10a8ed8edb253836e9c/scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"}}, + {name = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7b/7e/f30be3d03de07f25dc0ec926d1681fed5c732d759ac8f51079708c79e680/scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl",hashes = {sha256 = "185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"}}, + {name = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/07/9c/0ddb0d0abdabe0d181c1793db51f02cd59e4901da6f9f7848e1f96759f0d/scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl",hashes = {sha256 = "05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"}}, + {name = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/af/43/0bce905a965f36c58ff80d8bea33f1f9351b05fad4beaad4eae34699b7a1/scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl",hashes = {sha256 = "06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"}}, + {name = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/56/30/a6f08f84ee5b7b28b4c597aca4cbe545535c39fe911845a96414700b64ba/scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"}}, + {name = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/0b/1f/03f52c282437a168ee2c7c14a1a0d0781a9a4a8962d84ac05c06b4c5b555/scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"}}, + {name = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"}}, + {name = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"}}, + {name = "scipy-1.15.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"}}, +] +marker = "python_version ~= \"3.12\"" + +[packages.tool.pdm] +dependencies = [ + "numpy<2.5,>=1.23.5", +] + +[[packages]] +name = "numpy" +version = "2.2.6" +requires-python = ">=3.10" +sdist = {name = "numpy-2.2.6.tar.gz", url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hashes = {sha256 = "e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd"}} +wheels = [ + {name = "numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84"}}, + {name = "numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b"}}, + {name = "numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl",hashes = {sha256 = "f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d"}}, + {name = "numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl",hashes = {sha256 = "55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566"}}, + {name = "numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f"}}, + {name = "numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f"}}, + {name = "numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868"}}, + {name = "numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d"}}, + {name = "numpy-2.2.6-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl",hashes = {sha256 = "5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd"}}, + {name = "numpy-2.2.6-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl",hashes = {sha256 = "b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c"}}, + {name = "numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6"}}, + {name = "numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda"}}, + {name = "numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl",hashes = {sha256 = "5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40"}}, + {name = "numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl",hashes = {sha256 = "fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8"}}, + {name = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f"}}, + {name = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa"}}, + {name = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571"}}, + {name = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1"}}, + {name = "numpy-2.2.6-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl",hashes = {sha256 = "038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff"}}, + {name = "numpy-2.2.6-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06"}}, + {name = "numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff"}}, + {name = "numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c"}}, + {name = "numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl",hashes = {sha256 = "894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3"}}, + {name = "numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl",hashes = {sha256 = "71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282"}}, + {name = "numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87"}}, + {name = "numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249"}}, + {name = "numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49"}}, + {name = "numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de"}}, + {name = "numpy-2.2.6-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl",hashes = {sha256 = "4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4"}}, + {name = "numpy-2.2.6-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl",hashes = {sha256 = "c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2"}}, +] +marker = "python_version ~= \"3.12\"" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "lorem" version = "0.1.1" @@ -173,6 +318,38 @@ dependencies = [ "aiohttp>=3.3", ] +[[packages]] +name = "msgpack" +version = "1.1.1" +requires-python = ">=3.8" +sdist = {name = "msgpack-1.1.1.tar.gz", url = "https://files.pythonhosted.org/packages/45/b1/ea4f68038a18c77c9467400d166d74c4ffa536f34761f7983a104357e614/msgpack-1.1.1.tar.gz", hashes = {sha256 = "77b79ce34a2bdab2594f490c8e80dd62a02d650b91a75159a63ec413b8d104cd"}} +wheels = [ + {name = "msgpack-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/a1/38/561f01cf3577430b59b340b51329803d3a5bf6a45864a55f4ef308ac11e3/msgpack-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "3765afa6bd4832fc11c3749be4ba4b69a0e8d7b728f78e68120a157a4c5d41f0"}}, + {name = "msgpack-1.1.1-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/09/48/54a89579ea36b6ae0ee001cba8c61f776451fad3c9306cd80f5b5c55be87/msgpack-1.1.1-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "8ddb2bcfd1a8b9e431c8d6f4f7db0773084e107730ecf3472f1dfe9ad583f3d9"}}, + {name = "msgpack-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a0/60/daba2699b308e95ae792cdc2ef092a38eb5ee422f9d2fbd4101526d8a210/msgpack-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "196a736f0526a03653d829d7d4c5500a97eea3648aebfd4b6743875f28aa2af8"}}, + {name = "msgpack-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/20/22/2ebae7ae43cd8f2debc35c631172ddf14e2a87ffcc04cf43ff9df9fff0d3/msgpack-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9d592d06e3cc2f537ceeeb23d38799c6ad83255289bb84c2e5792e5a8dea268a"}}, + {name = "msgpack-1.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/40/1b/54c08dd5452427e1179a40b4b607e37e2664bca1c790c60c442c8e972e47/msgpack-1.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "4df2311b0ce24f06ba253fda361f938dfecd7b961576f9be3f3fbd60e87130ac"}}, + {name = "msgpack-1.1.1-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/2e/60/6bb17e9ffb080616a51f09928fdd5cac1353c9becc6c4a8abd4e57269a16/msgpack-1.1.1-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e4141c5a32b5e37905b5940aacbc59739f036930367d7acce7a64e4dec1f5e0b"}}, + {name = "msgpack-1.1.1-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ee/97/88983e266572e8707c1f4b99c8fd04f9eb97b43f2db40e3172d87d8642db/msgpack-1.1.1-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "b1ce7f41670c5a69e1389420436f41385b1aa2504c3b0c30620764b15dded2e7"}}, + {name = "msgpack-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/bc/66/36c78af2efaffcc15a5a61ae0df53a1d025f2680122e2a9eb8442fed3ae4/msgpack-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4147151acabb9caed4e474c3344181e91ff7a388b888f1e19ea04f7e73dc7ad5"}}, + {name = "msgpack-1.1.1-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/8c/87/a75eb622b555708fe0427fab96056d39d4c9892b0c784b3a721088c7ee37/msgpack-1.1.1-cp313-cp313-win32.whl",hashes = {sha256 = "500e85823a27d6d9bba1d057c871b4210c1dd6fb01fbb764e37e4e8847376323"}}, + {name = "msgpack-1.1.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ca/91/7dc28d5e2a11a5ad804cf2b7f7a5fcb1eb5a4966d66a5d2b41aee6376543/msgpack-1.1.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "6d489fba546295983abd142812bda76b57e33d0b9f5d5b71c09a583285506f69"}}, + {name = "msgpack-1.1.1-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/e3/26/389b9c593eda2b8551b2e7126ad3a06af6f9b44274eb3a4f054d48ff7e47/msgpack-1.1.1-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "ae497b11f4c21558d95de9f64fff7053544f4d1a17731c866143ed6bb4591238"}}, + {name = "msgpack-1.1.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ab/65/7d1de38c8a22cf8b1551469159d4b6cf49be2126adc2482de50976084d78/msgpack-1.1.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "33be9ab121df9b6b461ff91baac6f2731f83d9b27ed948c5b9d1978ae28bf157"}}, + {name = "msgpack-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/0f/bd/cacf208b64d9577a62c74b677e1ada005caa9b69a05a599889d6fc2ab20a/msgpack-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "6f64ae8fe7ffba251fecb8408540c34ee9df1c26674c50c4544d72dbf792e5ce"}}, + {name = "msgpack-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/4d/ec/fd869e2567cc9c01278a736cfd1697941ba0d4b81a43e0aa2e8d71dab208/msgpack-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "a494554874691720ba5891c9b0b39474ba43ffb1aaf32a5dac874effb1619e1a"}}, + {name = "msgpack-1.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/55/2a/35860f33229075bce803a5593d046d8b489d7ba2fc85701e714fc1aaf898/msgpack-1.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "cb643284ab0ed26f6957d969fe0dd8bb17beb567beb8998140b5e38a90974f6c"}}, + {name = "msgpack-1.1.1-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/8c/16/69ed8f3ada150bf92745fb4921bd621fd2cdf5a42e25eb50bcc57a5328f0/msgpack-1.1.1-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d275a9e3c81b1093c060c3837e580c37f47c51eca031f7b5fb76f7b8470f5f9b"}}, + {name = "msgpack-1.1.1-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/c6/b6/0c398039e4c6d0b2e37c61d7e0e9d13439f91f780686deb8ee64ecf1ae71/msgpack-1.1.1-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "4fd6b577e4541676e0cc9ddc1709d25014d3ad9a66caa19962c4f5de30fc09ef"}}, + {name = "msgpack-1.1.1-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b8/d0/0cf4a6ecb9bc960d624c93effaeaae75cbf00b3bc4a54f35c8507273cda1/msgpack-1.1.1-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "bb29aaa613c0a1c40d1af111abf025f1732cab333f96f285d6a93b934738a68a"}}, + {name = "msgpack-1.1.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/62/83/9697c211720fa71a2dfb632cad6196a8af3abea56eece220fde4674dc44b/msgpack-1.1.1-cp312-cp312-win32.whl",hashes = {sha256 = "870b9a626280c86cff9c576ec0d9cbcc54a1e5ebda9cd26dab12baf41fee218c"}}, + {name = "msgpack-1.1.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c0/23/0abb886e80eab08f5e8c485d6f13924028602829f63b8f5fa25a06636628/msgpack-1.1.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "5692095123007180dca3e788bb4c399cc26626da51629a31d40207cb262e67f4"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "mypy" version = "1.15.0" @@ -191,25 +368,7 @@ wheels = [ {name = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}}, {name = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}}, {name = "mypy-1.15.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}}, - {name = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}}, - {name = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}}, - {name = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}}, - {name = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}}, - {name = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}}, - {name = "mypy-1.15.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}}, - {name = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}}, - {name = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}}, - {name = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}}, - {name = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}}, - {name = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}}, - {name = "mypy-1.15.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}}, {name = "mypy-1.15.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl",hashes = {sha256 = "5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}}, - {name = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}}, - {name = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}}, - {name = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}}, - {name = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}}, - {name = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}}, - {name = "mypy-1.15.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}}, ] marker = "\"dev\" in extras" @@ -263,33 +422,6 @@ wheels = [ {name = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl",hashes = {sha256 = "8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}}, {name = "PyYAML-6.0.2-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl",hashes = {sha256 = "ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}}, {name = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}}, - {name = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}}, - {name = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}}, - {name = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}}, - {name = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}}, - {name = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}}, - {name = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl",hashes = {sha256 = "ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}}, - {name = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}}, - {name = "PyYAML-6.0.2-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl",hashes = {sha256 = "11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}}, - {name = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}}, - {name = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}}, - {name = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}}, - {name = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}}, - {name = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}}, - {name = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}}, - {name = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl",hashes = {sha256 = "936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}}, - {name = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl",hashes = {sha256 = "23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}}, - {name = "PyYAML-6.0.2-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl",hashes = {sha256 = "2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}}, - {name = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl",hashes = {sha256 = "a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}}, - {name = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}}, - {name = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}}, - {name = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}}, - {name = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}}, - {name = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}}, - {name = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl",hashes = {sha256 = "0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}}, - {name = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl",hashes = {sha256 = "a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}}, - {name = "PyYAML-6.0.2-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl",hashes = {sha256 = "6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}}, - {name = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl",hashes = {sha256 = "39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}}, ] marker = "\"default\" in dependency_groups or \"dev\" in extras" @@ -353,17 +485,19 @@ dependencies = [ [[packages]] name = "pytest-asyncio" -version = "0.23.8" -requires-python = ">=3.8" -sdist = {name = "pytest_asyncio-0.23.8.tar.gz", url = "https://files.pythonhosted.org/packages/de/b4/0b378b7bf26a8ae161c3890c0b48a91a04106c5713ce81b4b080ea2f4f18/pytest_asyncio-0.23.8.tar.gz", hashes = {sha256 = "759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}} +version = "1.1.1" +requires-python = ">=3.9" +sdist = {name = "pytest_asyncio-1.1.1.tar.gz", url = "https://files.pythonhosted.org/packages/8d/1e/2aa43805d4a320a9489d2b99f7877b69f9094c79aa0732159a1415dd6cd4/pytest_asyncio-1.1.1.tar.gz", hashes = {sha256 = "b72d215c38e2c91dbb32f275e0b5be69602d7869910e109360e375129960a649"}} wheels = [ - {name = "pytest_asyncio-0.23.8-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl",hashes = {sha256 = "50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}}, + {name = "pytest_asyncio-1.1.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/28/de/aba79e9ccdb51b5d0d65c67dd857bd78b00c64723df16b9fc800d8b94ce6/pytest_asyncio-1.1.1-py3-none-any.whl",hashes = {sha256 = "726339d30fcfde24691f589445b9b67d058b311ac632b1d704e97f20f1d878da"}}, ] marker = "\"dev\" in extras" [packages.tool.pdm] dependencies = [ - "pytest<9,>=7.0.0", + "backports-asyncio-runner<2,>=1.1; python_version < \"3.11\"", + "pytest<9,>=8.2", + "typing-extensions>=4.12; python_version < \"3.10\"", ] [[packages]] @@ -457,131 +591,6 @@ marker = "\"dev\" in extras" [packages.tool.pdm] dependencies = [] -[[packages]] -name = "scipy" -version = "1.15.3" -requires-python = ">=3.10" -sdist = {name = "scipy-1.15.3.tar.gz", url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hashes = {sha256 = "eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"}} -wheels = [ - {name = "scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759"}}, - {name = "scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl",hashes = {sha256 = "7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62"}}, - {name = "scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl",hashes = {sha256 = "8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb"}}, - {name = "scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl",hashes = {sha256 = "0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730"}}, - {name = "scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825"}}, - {name = "scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7"}}, - {name = "scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11"}}, - {name = "scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126"}}, - {name = "scipy-1.15.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163"}}, - {name = "scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8"}}, - {name = "scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl",hashes = {sha256 = "6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5"}}, - {name = "scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl",hashes = {sha256 = "50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e"}}, - {name = "scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl",hashes = {sha256 = "14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb"}}, - {name = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723"}}, - {name = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb"}}, - {name = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4"}}, - {name = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5"}}, - {name = "scipy-1.15.3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca"}}, - {name = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/37/4b/683aa044c4162e10ed7a7ea30527f2cbd92e6999c10a8ed8edb253836e9c/scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"}}, - {name = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7b/7e/f30be3d03de07f25dc0ec926d1681fed5c732d759ac8f51079708c79e680/scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl",hashes = {sha256 = "185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"}}, - {name = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/07/9c/0ddb0d0abdabe0d181c1793db51f02cd59e4901da6f9f7848e1f96759f0d/scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl",hashes = {sha256 = "05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"}}, - {name = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/af/43/0bce905a965f36c58ff80d8bea33f1f9351b05fad4beaad4eae34699b7a1/scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl",hashes = {sha256 = "06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"}}, - {name = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/56/30/a6f08f84ee5b7b28b4c597aca4cbe545535c39fe911845a96414700b64ba/scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"}}, - {name = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/0b/1f/03f52c282437a168ee2c7c14a1a0d0781a9a4a8962d84ac05c06b4c5b555/scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"}}, - {name = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"}}, - {name = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"}}, - {name = "scipy-1.15.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"}}, - {name = "scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/96/ab/5cc9f80f28f6a7dff646c5756e559823614a42b1939d86dd0ed550470210/scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl",hashes = {sha256 = "993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b"}}, - {name = "scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4a/4a/66ba30abe5ad1a3ad15bfb0b59d22174012e8056ff448cb1644deccbfed2/scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl",hashes = {sha256 = "34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba"}}, - {name = "scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4b/fa/a7e5b95afd80d24313307f03624acc65801846fa75599034f8ceb9e2cbf6/scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl",hashes = {sha256 = "3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65"}}, - {name = "scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/99/f3aaddccf3588bb4aea70ba35328c204cadd89517a1612ecfda5b2dd9d7a/scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl",hashes = {sha256 = "6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1"}}, - {name = "scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/56/c5/1032cdb565f146109212153339f9cb8b993701e9fe56b1c97699eee12586/scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889"}}, - {name = "scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/bd/37/89f19c8c05505d0601ed5650156e50eb881ae3918786c8fd7262b4ee66d3/scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982"}}, - {name = "scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7e/31/be59513aa9695519b18e1851bb9e487de66f2d31f835201f1b42f5d4d475/scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9"}}, - {name = "scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/10/c0/4f5f3eeccc235632aab79b27a74a9130c6c35df358129f7ac8b29f562ac7/scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594"}}, - {name = "scipy-1.15.3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ab/a7/0ddaf514ce8a8714f6ed243a2b391b41dbb65251affe21ee3077ec45ea9a/scipy-1.15.3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb"}}, - {name = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/2f/4966032c5f8cc7e6a60f1b2e0ad686293b9474b65246b0c642e3ef3badd0/scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl",hashes = {sha256 = "a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}}, - {name = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a0/6e/0c3bf90fae0e910c274db43304ebe25a6b391327f3f10b5dcc638c090795/scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl",hashes = {sha256 = "ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"}}, - {name = "scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ea/b1/4deb37252311c1acff7f101f6453f0440794f51b6eacb1aad4459a134081/scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl",hashes = {sha256 = "aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f"}}, - {name = "scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/38/7d/f457626e3cd3c29b3a49ca115a304cebb8cc6f31b04678f03b216899d3c6/scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl",hashes = {sha256 = "1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92"}}, - {name = "scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/db/0a/92b1de4a7adc7a15dcf5bddc6e191f6f29ee663b30511ce20467ef9b82e4/scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82"}}, - {name = "scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/8e/6d/41991e503e51fc1134502694c5fa7a1671501a17ffa12716a4a9151af3df/scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40"}}, - {name = "scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/25/e1/3df8f83cb15f3500478c889be8fb18700813b95e9e087328230b98d547ff/scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e"}}, - {name = "scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/93/3e/b3257cf446f2a3533ed7809757039016b74cd6f38271de91682aa844cfc5/scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c"}}, - {name = "scipy-1.15.3-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d1/84/55bc4881973d3f79b479a5a2e2df61c8c9a04fcb986a213ac9c02cfb659b/scipy-1.15.3-cp310-cp310-win_amd64.whl",hashes = {sha256 = "9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13"}}, -] -marker = "python_version ~= \"3.10\" and \"dev\" in extras" - -[packages.tool.pdm] -dependencies = [ - "numpy<2.5,>=1.23.5", -] - -[[packages]] -name = "numpy" -version = "2.2.6" -requires-python = ">=3.10" -sdist = {name = "numpy-2.2.6.tar.gz", url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hashes = {sha256 = "e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd"}} -wheels = [ - {name = "numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84"}}, - {name = "numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b"}}, - {name = "numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl",hashes = {sha256 = "f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d"}}, - {name = "numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl",hashes = {sha256 = "55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566"}}, - {name = "numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f"}}, - {name = "numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f"}}, - {name = "numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868"}}, - {name = "numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d"}}, - {name = "numpy-2.2.6-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl",hashes = {sha256 = "5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd"}}, - {name = "numpy-2.2.6-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl",hashes = {sha256 = "b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c"}}, - {name = "numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6"}}, - {name = "numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda"}}, - {name = "numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl",hashes = {sha256 = "5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40"}}, - {name = "numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl",hashes = {sha256 = "fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8"}}, - {name = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f"}}, - {name = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa"}}, - {name = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571"}}, - {name = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1"}}, - {name = "numpy-2.2.6-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl",hashes = {sha256 = "038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff"}}, - {name = "numpy-2.2.6-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06"}}, - {name = "numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff"}}, - {name = "numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c"}}, - {name = "numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl",hashes = {sha256 = "894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3"}}, - {name = "numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl",hashes = {sha256 = "71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282"}}, - {name = "numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87"}}, - {name = "numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249"}}, - {name = "numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49"}}, - {name = "numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de"}}, - {name = "numpy-2.2.6-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl",hashes = {sha256 = "4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4"}}, - {name = "numpy-2.2.6-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl",hashes = {sha256 = "c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2"}}, - {name = "numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae"}}, - {name = "numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a"}}, - {name = "numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl",hashes = {sha256 = "3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42"}}, - {name = "numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl",hashes = {sha256 = "481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491"}}, - {name = "numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a"}}, - {name = "numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf"}}, - {name = "numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1"}}, - {name = "numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab"}}, - {name = "numpy-2.2.6-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl",hashes = {sha256 = "0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47"}}, - {name = "numpy-2.2.6-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl",hashes = {sha256 = "e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303"}}, - {name = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}}, - {name = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}}, - {name = "numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl",hashes = {sha256 = "37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163"}}, - {name = "numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl",hashes = {sha256 = "5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf"}}, - {name = "numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83"}}, - {name = "numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915"}}, - {name = "numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680"}}, - {name = "numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289"}}, - {name = "numpy-2.2.6-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl",hashes = {sha256 = "b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d"}}, - {name = "numpy-2.2.6-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl",hashes = {sha256 = "f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3"}}, - {name = "numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d"}}, - {name = "numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl",hashes = {sha256 = "7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db"}}, - {name = "numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543"}}, - {name = "numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl",hashes = {sha256 = "d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00"}}, -] -marker = "\"default\" in dependency_groups and python_version ~= \"3.10\" or \"dev\" in extras and python_version ~= \"3.10\"" - -[packages.tool.pdm] -dependencies = [] - [[packages]] name = "setuptools" version = "80.9.0" @@ -590,7 +599,7 @@ sdist = {name = "setuptools-80.9.0.tar.gz", url = "https://files.pythonhosted.or wheels = [ {name = "setuptools-80.9.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl",hashes = {sha256 = "062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}}, ] -marker = "\"dev\" in extras" +marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [] @@ -644,24 +653,6 @@ wheels = [ {name = "tiktoken-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d5/2d/4d77f6feb9292bfdd23d5813e442b3bba883f42d0ac78ef5fdc56873f756/tiktoken-0.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "7f929255c705efec7a28bf515e29dc74220b2f07544a8c81b8d69e8efc4578bd"}}, {name = "tiktoken-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/7a/65/7ff0a65d3bb0fc5a1fb6cc71b03e0f6e71a68c5eea230d1ff1ba3fd6df49/tiktoken-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "61f1d15822e4404953d499fd1dcc62817a12ae9fb1e4898033ec8fe3915fdf8e"}}, {name = "tiktoken-0.11.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f5/6e/5b71578799b72e5bdcef206a214c3ce860d999d579a3b56e74a6c8989ee2/tiktoken-0.11.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "45927a71ab6643dfd3ef57d515a5db3d199137adf551f66453be098502838b0f"}}, - {name = "tiktoken-0.11.0-cp311-cp311-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/91/912b459799a025d2842566fe1e902f7f50d54a1ce8a0f236ab36b5bd5846/tiktoken-0.11.0-cp311-cp311-macosx_10_12_x86_64.whl",hashes = {sha256 = "4ae374c46afadad0f501046db3da1b36cd4dfbfa52af23c998773682446097cf"}}, - {name = "tiktoken-0.11.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/8c/e9/6faa6870489ce64f5f75dcf91512bf35af5864583aee8fcb0dcb593121f5/tiktoken-0.11.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "25a512ff25dc6c85b58f5dd4f3d8c674dc05f96b02d66cdacf628d26a4e4866b"}}, - {name = "tiktoken-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a1/3e/a05d1547cf7db9dc75d1461cfa7b556a3b48e0516ec29dfc81d984a145f6/tiktoken-0.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2130127471e293d385179c1f3f9cd445070c0772be73cdafb7cec9a3684c0458"}}, - {name = "tiktoken-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/34/9a/db7a86b829e05a01fd4daa492086f708e0a8b53952e1dbc9d380d2b03677/tiktoken-0.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "21e43022bf2c33f733ea9b54f6a3f6b4354b909f5a73388fb1b9347ca54a069c"}}, - {name = "tiktoken-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/9d/bb/52edc8e078cf062ed749248f1454e9e5cfd09979baadb830b3940e522015/tiktoken-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "adb4e308eb64380dc70fa30493e21c93475eaa11669dea313b6bbf8210bfd013"}}, - {name = "tiktoken-0.11.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/60/d9/884b6cd7ae2570ecdcaffa02b528522b18fef1cbbfdbcaa73799807d0d3b/tiktoken-0.11.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "ece6b76bfeeb61a125c44bbefdfccc279b5288e6007fbedc0d32bfec602df2f2"}}, - {name = "tiktoken-0.11.0-cp310-cp310-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/8b/4d/c6a2e7dca2b4f2e9e0bfd62b3fe4f114322e2c028cfba905a72bc76ce479/tiktoken-0.11.0-cp310-cp310-macosx_10_12_x86_64.whl",hashes = {sha256 = "8a9b517d6331d7103f8bef29ef93b3cca95fa766e293147fe7bacddf310d5917"}}, - {name = "tiktoken-0.11.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/41/54/3739d35b9f94cb8dc7b0db2edca7192d5571606aa2369a664fa27e811804/tiktoken-0.11.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "b4ddb1849e6bf0afa6cc1c5d809fb980ca240a5fffe585a04e119519758788c0"}}, - {name = "tiktoken-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/dd/f4/ec8d43338d28d53513004ebf4cd83732a135d11011433c58bf045890cc10/tiktoken-0.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "10331d08b5ecf7a780b4fe4d0281328b23ab22cdb4ff65e68d56caeda9940ecc"}}, - {name = "tiktoken-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/94/80/fb0ada0a882cb453caf519a4bf0d117c2a3ee2e852c88775abff5413c176/tiktoken-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "b062c82300341dc87e0258c69f79bed725f87e753c21887aea90d272816be882"}}, - {name = "tiktoken-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/2f/e9/6c104355b463601719582823f3ea658bc3aa7c73d1b3b7553ebdc48468ce/tiktoken-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "195d84bec46169af3b1349a1495c151d37a0ff4cba73fd08282736be7f92cc6c"}}, - {name = "tiktoken-0.11.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/94/75/eaa6068f47e8b3f0aab9e05177cce2cf5aa2cc0ca93981792e620d4d4117/tiktoken-0.11.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "fe91581b0ecdd8783ce8cb6e3178f2260a3912e8724d2f2d49552b98714641a1"}}, - {name = "tiktoken-0.11.0-cp39-cp39-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/aa/b6/81c5799ab77a9580c6d840cf77d4717e929193a42190fd623a080c647aa6/tiktoken-0.11.0-cp39-cp39-macosx_10_12_x86_64.whl",hashes = {sha256 = "13220f12c9e82e399377e768640ddfe28bea962739cc3a869cad98f42c419a89"}}, - {name = "tiktoken-0.11.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/50/89/faa668066b2a4640534ef5797c09ecd0a48b43367502129b217339dfaa97/tiktoken-0.11.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "7f2db627f5c74477c0404b4089fd8a28ae22fa982a6f7d9c7d4c305c375218f3"}}, - {name = "tiktoken-0.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/aa/7f/5f950528b54cb3025af4bc3522c23dbfb691afe8ffb292aa1e8dc2e6bddf/tiktoken-0.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2302772f035dceb2bcf8e55a735e4604a0b51a6dd50f38218ff664d46ec43807"}}, - {name = "tiktoken-0.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/27/a4/e82ddf0773835ba24536ac8c0dce561e697698ec020a93212a1e041d39b4/tiktoken-0.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "20b977989afe44c94bcc50db1f76971bb26dca44218bd203ba95925ef56f8e7a"}}, - {name = "tiktoken-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1b/c2/06361e41d176e62797ae65fa678111cdd30553321cf4d83e7b84107ea95f/tiktoken-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "669a1aa1ad6ebf1b3c26b45deb346f345da7680f845b5ea700bba45c20dea24c"}}, - {name = "tiktoken-0.11.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bb/ad/ca37e15c46741ebb3904d562d03194e845539a08f7751a6df0f391757312/tiktoken-0.11.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "e363f33c720a055586f730c00e330df4c7ea0024bf1c83a8a9a9dbc054c4f304"}}, ] marker = "\"recommended\" in extras" @@ -671,6 +662,41 @@ dependencies = [ "requests>=2.26.0", ] +[[packages]] +name = "torch" +version = "2.8.0+cpu" +requires-python = ">=3.9.0" +wheels = [ + {name = "torch-2.8.0+cpu-cp313-cp313-linux_s390x.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313-linux_s390x.whl",hashes = {sha256 = "8b5882276633cf91fe3d2d7246c743b94d44a7e660b27f1308007fdb1bb89f7d"}}, + {name = "torch-2.8.0+cpu-cp313-cp313-manylinux_2_28_aarch64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313-manylinux_2_28_aarch64.whl",hashes = {sha256 = "a5064b5e23772c8d164068cc7c12e01a75faf7b948ecd95a0d4007d7487e5f25"}}, + {name = "torch-2.8.0+cpu-cp313-cp313-manylinux_2_28_x86_64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313-manylinux_2_28_x86_64.whl",hashes = {sha256 = "8f81dedb4c6076ec325acc3b47525f9c550e5284a18eae1d9061c543f7b6e7de"}}, + {name = "torch-2.8.0+cpu-cp313-cp313-win_amd64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313-win_amd64.whl",hashes = {sha256 = "e1ee1b2346ade3ea90306dfbec7e8ff17bc220d344109d189ae09078333b0856"}}, + {name = "torch-2.8.0+cpu-cp313-cp313-win_arm64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313-win_arm64.whl",hashes = {sha256 = "64c187345509f2b1bb334feed4666e2c781ca381874bde589182f81247e61f88"}}, + {name = "torch-2.8.0+cpu-cp313-cp313t-manylinux_2_28_aarch64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313t-manylinux_2_28_aarch64.whl",hashes = {sha256 = "af81283ac671f434b1b25c95ba295f270e72db1fad48831eb5e4748ff9840041"}}, + {name = "torch-2.8.0+cpu-cp313-cp313t-manylinux_2_28_x86_64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313t-manylinux_2_28_x86_64.whl",hashes = {sha256 = "a9dbb6f64f63258bc811e2c0c99640a81e5af93c531ad96e95c5ec777ea46dab"}}, + {name = "torch-2.8.0+cpu-cp313-cp313t-win_amd64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "6d93a7165419bc4b2b907e859ccab0dea5deeab261448ae9a5ec5431f14c0e64"}}, + {name = "torch-2.8.0-cp313-cp313t-macosx_14_0_arm64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0-cp313-cp313t-macosx_14_0_arm64.whl",hashes = {sha256 = "fbe2e149c5174ef90d29a5f84a554dfaf28e003cb4f61fa2c8c024c17ec7ca58"}}, + {name = "torch-2.8.0-cp313-none-macosx_11_0_arm64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0-cp313-none-macosx_11_0_arm64.whl",hashes = {sha256 = "057efd30a6778d2ee5e2374cd63a63f63311aa6f33321e627c655df60abdd390"}}, + {name = "torch-2.8.0+cpu-cp312-cp312-linux_s390x.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp312-cp312-linux_s390x.whl",hashes = {sha256 = "0e34e276722ab7dd0dffa9e12fe2135a9b34a0e300c456ed7ad6430229404eb5"}}, + {name = "torch-2.8.0+cpu-cp312-cp312-manylinux_2_28_aarch64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp312-cp312-manylinux_2_28_aarch64.whl",hashes = {sha256 = "610f600c102386e581327d5efc18c0d6edecb9820b4140d26163354a99cd800d"}}, + {name = "torch-2.8.0+cpu-cp312-cp312-manylinux_2_28_x86_64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp312-cp312-manylinux_2_28_x86_64.whl",hashes = {sha256 = "cb9a8ba8137ab24e36bf1742cb79a1294bd374db570f09fc15a5e1318160db4e"}}, + {name = "torch-2.8.0+cpu-cp312-cp312-win_amd64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp312-cp312-win_amd64.whl",hashes = {sha256 = "2be20b2c05a0cce10430cc25f32b689259640d273232b2de357c35729132256d"}}, + {name = "torch-2.8.0+cpu-cp312-cp312-win_arm64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0%2Bcpu-cp312-cp312-win_arm64.whl",hashes = {sha256 = "99fc421a5d234580e45957a7b02effbf3e1c884a5dd077afc85352c77bf41434"}}, + {name = "torch-2.8.0-cp312-none-macosx_11_0_arm64.whl",url = "https://download.pytorch.org/whl/cpu/torch-2.8.0-cp312-none-macosx_11_0_arm64.whl",hashes = {sha256 = "a47b7986bee3f61ad217d8a8ce24605809ab425baf349f97de758815edd2ef54"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "filelock", + "typing-extensions>=4.10.0", + "sympy>=1.13.3", + "networkx", + "jinja2", + "fsspec", + "setuptools; python_version >= \"3.12\"", +] + [[packages]] name = "tox" version = "4.16.0" @@ -724,22 +750,28 @@ dependencies = [ ] [[packages]] -name = "blobfile" -version = "3.1.0" +name = "uvloop" +version = "0.21.0" requires-python = ">=3.8.0" -sdist = {name = "blobfile-3.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/f0/6d/2e7567da75ddbb24fe979f52284b708da349d67a41042635af36071a5a6b/blobfile-3.1.0.tar.gz", hashes = {sha256 = "d45b6b1fa3b0920732314c23ddbdb4f494ca12f787c2b6eb6bba6faa51382671"}} -wheels = [ - {name = "blobfile-3.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/77/a7/51af11120d75af2828f8eede0b13a4caff650d708ac50e62d000aefe1ffb/blobfile-3.1.0-py3-none-any.whl",hashes = {sha256 = "2b4c5e766ebb7dfa20e4990cf6ec3d2106bdc91d632fb9377f170a234c5a5c6a"}}, +sdist = {name = "uvloop-0.21.0.tar.gz", url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hashes = {sha256 = "3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3"}} +wheels = [ + {name = "uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281"}}, + {name = "uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af"}}, + {name = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6"}}, + {name = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816"}}, + {name = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc"}}, + {name = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553"}}, + {name = "uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c"}}, + {name = "uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2"}}, + {name = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d"}}, + {name = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc"}}, + {name = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb"}}, + {name = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f"}}, ] -marker = "\"recommended\" in extras" +marker = "\"default\" in dependency_groups" [packages.tool.pdm] -dependencies = [ - "pycryptodomex>=3.8", - "urllib3<3,>=1.25.3", - "lxml>=4.9", - "filelock>=3.0", -] +dependencies = [] [[packages]] name = "datasets" @@ -769,31 +801,59 @@ dependencies = [ ] [[packages]] -name = "loguru" -version = "0.7.3" -requires-python = "<4.0,>=3.5" -sdist = {name = "loguru-0.7.3.tar.gz", url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hashes = {sha256 = "19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}} +name = "eval-type-backport" +version = "0.2.2" +requires-python = ">=3.8" +sdist = {name = "eval_type_backport-0.2.2.tar.gz", url = "https://files.pythonhosted.org/packages/30/ea/8b0ac4469d4c347c6a385ff09dc3c048c2d021696664e26c7ee6791631b5/eval_type_backport-0.2.2.tar.gz", hashes = {sha256 = "f0576b4cf01ebb5bd358d02314d31846af5e07678387486e2c798af0e7d849c1"}} wheels = [ - {name = "loguru-0.7.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl",hashes = {sha256 = "31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}}, + {name = "eval_type_backport-0.2.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ce/31/55cd413eaccd39125368be33c46de24a1f639f2e12349b0361b4678f3915/eval_type_backport-0.2.2-py3-none-any.whl",hashes = {sha256 = "cb6ad7c393517f476f96d456d0412ea80f0a8cf96f6892834cd9340149111b0a"}}, ] marker = "\"default\" in dependency_groups" [packages.tool.pdm] -dependencies = [ - "colorama>=0.3.4; sys_platform == \"win32\"", - "aiocontextvars>=0.2.0; python_version < \"3.7\"", - "win32-setctime>=1.0.0; sys_platform == \"win32\"", -] +dependencies = [] [[packages]] -name = "pillow" -version = "11.3.0" +name = "faker" +version = "37.8.0" requires-python = ">=3.9" -sdist = {name = "pillow-11.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hashes = {sha256 = "3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"}} +sdist = {name = "faker-37.8.0.tar.gz", url = "https://files.pythonhosted.org/packages/3a/da/1336008d39e5d4076dddb4e0f3a52ada41429274bf558a3cc28030d324a3/faker-37.8.0.tar.gz", hashes = {sha256 = "090bb5abbec2b30949a95ce1ba6b20d1d0ed222883d63483a0d4be4a970d6fb8"}} wheels = [ - {name = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"}}, - {name = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"}}, - {name = "pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632"}}, + {name = "faker-37.8.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f5/11/02ebebb09ff2104b690457cb7bc6ed700c9e0ce88cf581486bb0a5d3c88b/faker-37.8.0-py3-none-any.whl",hashes = {sha256 = "b08233118824423b5fc239f7dd51f145e7018082b4164f8da6a9994e1f1ae793"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "tzdata", +] + +[[packages]] +name = "loguru" +version = "0.7.3" +requires-python = "<4.0,>=3.5" +sdist = {name = "loguru-0.7.3.tar.gz", url = "https://files.pythonhosted.org/packages/3a/05/a1dae3dffd1116099471c643b8924f5aa6524411dc6c63fdae648c4f1aca/loguru-0.7.3.tar.gz", hashes = {sha256 = "19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}} +wheels = [ + {name = "loguru-0.7.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/0c/29/0348de65b8cc732daa3e33e67806420b2ae89bdce2b04af740289c5c6c8c/loguru-0.7.3-py3-none-any.whl",hashes = {sha256 = "31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "colorama>=0.3.4; sys_platform == \"win32\"", + "aiocontextvars>=0.2.0; python_version < \"3.7\"", + "win32-setctime>=1.0.0; sys_platform == \"win32\"", +] + +[[packages]] +name = "pillow" +version = "11.3.0" +requires-python = ">=3.9" +sdist = {name = "pillow-11.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hashes = {sha256 = "3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"}} +wheels = [ + {name = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"}}, + {name = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"}}, + {name = "pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632"}}, {name = "pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/b5/3d/b932bb4225c80b58dfadaca9d42d08d0b7064d2d1791b6a237f87f661834/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673"}}, {name = "pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/09/b5/0487044b7c096f1b48f0d7ad416472c02e0e4bf6919541b111efd3cae690/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027"}}, {name = "pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/a8/2d/524f9318f6cbfcc79fbc004801ea6b607ec3f843977652fdee4857a7568b/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77"}}, @@ -849,53 +909,6 @@ wheels = [ {name = "pillow-11.3.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/26/7d/73699ad77895f69edff76b0f332acc3d497f22f5d75e5360f78cbcaff248/pillow-11.3.0-cp312-cp312-win32.whl",hashes = {sha256 = "7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149"}}, {name = "pillow-11.3.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8c/ce/e7dfc873bdd9828f3b6e5c2bbb74e47a98ec23cc5c74fc4e54462f0d9204/pillow-11.3.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d"}}, {name = "pillow-11.3.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/16/8f/b13447d1bf0b1f7467ce7d86f6e6edf66c0ad7cf44cf5c87a37f9bed9936/pillow-11.3.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542"}}, - {name = "pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl",url = "https://files.pythonhosted.org/packages/db/26/77f8ed17ca4ffd60e1dcd220a6ec6d71210ba398cfa33a13a1cd614c5613/pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl",hashes = {sha256 = "1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722"}}, - {name = "pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/cb/39/ee475903197ce709322a17a866892efb560f57900d9af2e55f86db51b0a5/pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288"}}, - {name = "pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/d5/90/442068a160fd179938ba55ec8c97050a612426fae5ec0a764e345839f76d/pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d"}}, - {name = "pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/13/92/dcdd147ab02daf405387f0218dcf792dc6dd5b14d2573d40b4caeef01059/pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494"}}, - {name = "pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/6e/db/839d6ba7fd38b51af641aa904e2960e7a5644d60ec754c046b7d2aee00e5/pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58"}}, - {name = "pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/f2/2f/d7675ecae6c43e9f12aa8d58b6012683b20b6edfbdac7abcb4e6af7a3784/pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f"}}, - {name = "pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/45/ad/931694675ede172e15b2ff03c8144a0ddaea1d87adb72bb07655eaffb654/pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e"}}, - {name = "pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3a/04/ba8f2b11fc80d2dd462d7abec16351b45ec99cbbaea4387648a44190351a/pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94"}}, - {name = "pillow-11.3.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/48/59/8cd06d7f3944cc7d892e8533c56b0acb68399f640786313275faec1e3b6f/pillow-11.3.0-cp311-cp311-win32.whl",hashes = {sha256 = "b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0"}}, - {name = "pillow-11.3.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f1/cc/29c0f5d64ab8eae20f3232da8f8571660aa0ab4b8f1331da5c2f5f9a938e/pillow-11.3.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac"}}, - {name = "pillow-11.3.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/c6/df/90bd886fabd544c25addd63e5ca6932c86f2b701d5da6c7839387a076b4a/pillow-11.3.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/de/5f/c22340acd61cef960130585bbe2120e2fd8434c214802f07e8c03596b17e/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/31/5e/03966aedfbfcbb4d5f8aa042452d3361f325b963ebbadddac05b122e47dd/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/cc/2d/e082982aacc927fc2cab48e1e731bdb1643a1406acace8bed0900a61464e/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7"}}, - {name = "pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8"}}, - {name = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl",url = "https://files.pythonhosted.org/packages/4c/5d/45a3553a253ac8763f3561371432a90bdbe6000fbdcf1397ffe502aa206c/pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl",hashes = {sha256 = "1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"}}, - {name = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7c/c8/67c12ab069ef586a25a4a79ced553586748fad100c77c0ce59bb4983ac98/pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"}}, - {name = "pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/2f/bd/6741ebd56263390b382ae4c5de02979af7f8bd9807346d068700dd6d5cf9/pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0"}}, - {name = "pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/ca/0b/c412a9e27e1e6a829e6ab6c2dca52dd563efbedf4c9c6aa453d9a9b77359/pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b"}}, - {name = "pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/59/9d/9b7076aaf30f5dd17e5e5589b2d2f5a5d7e30ff67a171eb686e4eecc2adf/pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50"}}, - {name = "pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/f0/16/1a6bf01fb622fb9cf5c91683823f073f053005c849b1f52ed613afcf8dae/pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae"}}, - {name = "pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7b/e6/6ff7077077eb47fde78739e7d570bdcd7c10495666b6afcd23ab56b19a43/pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9"}}, - {name = "pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c3/3a/b13f36832ea6d279a697231658199e0a03cd87ef12048016bdcc84131601/pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e"}}, - {name = "pillow-11.3.0-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/6c/e4/61b2e1a7528740efbc70b3d581f33937e38e98ef3d50b05007267a55bcb2/pillow-11.3.0-cp310-cp310-win32.whl",hashes = {sha256 = "89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6"}}, - {name = "pillow-11.3.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a9/d3/60c781c83a785d6afbd6a326ed4d759d141de43aa7365725cbcd65ce5e54/pillow-11.3.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f"}}, - {name = "pillow-11.3.0-cp310-cp310-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9f/28/4f4a0203165eefb3763939c6789ba31013a2e90adffb456610f30f613850/pillow-11.3.0-cp310-cp310-win_arm64.whl",hashes = {sha256 = "819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/6f/8b/209bd6b62ce8367f47e68a218bffac88888fdf2c9fcf1ecadc6c3ec1ebc7/pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2e/e6/231a0b76070c2cfd9e260a7a5b504fb72da0a95279410fa7afd99d9751d6/pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/13/f4/10cf94fda33cb12765f2397fc285fa6d8eb9c29de7f3185165b702fc7386/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/72/c9/583821097dc691880c92892e8e2d41fe0a5a3d6021f4963371d2f6d57250/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/3b/8e/5c9d410f9217b12320efc7c413e72693f48468979a013ad17fd690397b9a/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/62/bb/78347dbe13219991877ffb3a91bf09da8317fbfcd4b5f9140aeae020ad71/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a"}}, - {name = "pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d9/28/1000353d5e61498aaeaaf7f1e4b49ddb05f2c6575f9d4f9f914a3538b6e1/pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl",hashes = {sha256 = "8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f"}}, - {name = "pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl",url = "https://files.pythonhosted.org/packages/9e/8e/9c089f01677d1264ab8648352dcb7773f37da6ad002542760c80107da816/pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl",hashes = {sha256 = "48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f"}}, - {name = "pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b5/a9/5749930caf674695867eb56a581e78eb5f524b7583ff10b01b6e5048acb3/pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081"}}, - {name = "pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/43/46/0b85b763eb292b691030795f9f6bb6fcaf8948c39413c81696a01c3577f7/pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4"}}, - {name = "pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/5e/c6/1a230ec0067243cbd60bc2dad5dc3ab46a8a41e21c15f5c9b52b26873069/pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc"}}, - {name = "pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/63/dd/f296c27ffba447bfad76c6a0c44c1ea97a90cb9472b9304c94a732e8dbfb/pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06"}}, - {name = "pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/a5/a0/98a3630f0b57f77bae67716562513d3032ae70414fcaf02750279c389a9e/pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a"}}, - {name = "pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/de/e6/83dfba5646a290edd9a21964da07674409e410579c341fc5b8f7abd81620/pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978"}}, - {name = "pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/bc/41/15ab268fe6ee9a2bc7391e2bbb20a98d3974304ab1a406a992dcb297a370/pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d"}}, - {name = "pillow-11.3.0-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/64/79/6d4f638b288300bed727ff29f2a3cb63db054b33518a95f27724915e3fbc/pillow-11.3.0-cp39-cp39-win32.whl",hashes = {sha256 = "ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71"}}, - {name = "pillow-11.3.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/46/05/4106422f45a05716fd34ed21763f8ec182e8ea00af6e9cb05b93a247361a/pillow-11.3.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada"}}, - {name = "pillow-11.3.0-cp39-cp39-win_arm64.whl",url = "https://files.pythonhosted.org/packages/63/c6/287fd55c2c12761d0591549d48885187579b7c257bef0c6660755b0b59ae/pillow-11.3.0-cp39-cp39-win_arm64.whl",hashes = {sha256 = "6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb"}}, ] marker = "\"default\" in dependency_groups" @@ -914,8 +927,6 @@ wheels = [ {name = "protobuf-6.31.1-cp39-abi3-manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/76/a1/7a5a94032c83375e4fe7e7f56e3976ea6ac90c5e85fac8576409e25c39c3/protobuf-6.31.1-cp39-abi3-manylinux2014_aarch64.whl",hashes = {sha256 = "a40fc12b84c154884d7d4c4ebd675d5b3b5283e155f324049ae396b95ddebc39"}}, {name = "protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/fa/b1/b59d405d64d31999244643d88c45c8241c58f17cc887e73bcb90602327f8/protobuf-6.31.1-cp39-abi3-manylinux2014_x86_64.whl",hashes = {sha256 = "4ee898bf66f7a8b0bd21bce523814e6fbd8c6add948045ce958b73af7e8878c6"}}, {name = "protobuf-6.31.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/f7/af/ab3c51ab7507a7325e98ffe691d9495ee3d3aa5f589afad65ec920d39821/protobuf-6.31.1-py3-none-any.whl",hashes = {sha256 = "720a6c7e6b77288b85063569baae8536671b39f15cc22037ec7045658d80489e"}}, - {name = "protobuf-6.31.1-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/b1/f0/4160dbd205eee8fdf8647d154e7ceaa9d25b3a877b6311274eb6dc896b75/protobuf-6.31.1-cp39-cp39-win32.whl",hashes = {sha256 = "0414e3aa5a5f3ff423828e1e6a6e907d6c65c1d5b7e6e975793d5590bdeecc16"}}, - {name = "protobuf-6.31.1-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/09/34/13989eb9f482409ed821bfa3e34e6a3878b42607c38e7f7572b4cc825091/protobuf-6.31.1-cp39-cp39-win_amd64.whl",hashes = {sha256 = "8764cf4587791e7564051b35524b72844f845ad0bb011704c3736cce762d8fe9"}}, ] marker = "\"default\" in dependency_groups" @@ -939,6 +950,31 @@ dependencies = [ "typing-extensions<5.0,>=4.0.0; python_version < \"3.11\"", ] +[[packages]] +name = "sanic" +version = "25.3.0" +requires-python = ">=3.8" +sdist = {name = "sanic-25.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/df/8b/08dc376390fe854ef32984973883b646ee68c6727da72ffcc65340d8f192/sanic-25.3.0.tar.gz", hashes = {sha256 = "775d522001ec81f034ec8e4d7599e2175bfc097b8d57884f5e4c9322f5e369bb"}} +wheels = [ + {name = "sanic-25.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a6/e1/b36ddc16862d63d22986ae21b04a79c8fb7ec48d5d664acdfd1c2acf78ac/sanic-25.3.0-py3-none-any.whl",hashes = {sha256 = "fb519b38b4c220569b0e2e868583ffeaffaab96a78b2e42ae78bc56a644a4cd7"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "sanic-routing>=23.12.0", + "httptools>=0.0.10", + "uvloop>=0.15.0; sys_platform != \"win32\" and implementation_name == \"cpython\"", + "ujson>=1.35; sys_platform != \"win32\" and implementation_name == \"cpython\"", + "aiofiles>=0.6.0", + "websockets>=10.0", + "multidict<7.0,>=5.0", + "html5tagger>=1.2.1", + "tracerite>=1.0.0", + "typing-extensions>=4.4.0", + "setuptools>=70.1.0", +] + [[packages]] name = "transformers" version = "4.53.1" @@ -1047,73 +1083,6 @@ wheels = [ {name = "pydantic_core-2.33.2-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl",hashes = {sha256 = "9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}}, {name = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}}, {name = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl",hashes = {sha256 = "cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl",hashes = {sha256 = "4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl",hashes = {sha256 = "fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl",url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl",hashes = {sha256 = "bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl",hashes = {sha256 = "6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}}, - {name = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl",hashes = {sha256 = "6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl",hashes = {sha256 = "dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl",hashes = {sha256 = "f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl",url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl",hashes = {sha256 = "de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl",hashes = {sha256 = "82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}}, - {name = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl",hashes = {sha256 = "2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl",hashes = {sha256 = "031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl",url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl",hashes = {sha256 = "f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl",hashes = {sha256 = "73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl",hashes = {sha256 = "0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}}, - {name = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl",hashes = {sha256 = "b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl",hashes = {sha256 = "5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl",hashes = {sha256 = "0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl",url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl",hashes = {sha256 = "1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl",hashes = {sha256 = "fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}}, - {name = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl",hashes = {sha256 = "a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/53/ea/bbe9095cdd771987d13c82d104a9c8559ae9aec1e29f139e286fd2e9256e/pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl",hashes = {sha256 = "a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/49/1d/4ac5ed228078737d457a609013e8f7edc64adc37b91d619ea965758369e5/pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/23/9a/2e70d6388d7cda488ae38f57bc2f7b03ee442fbcf0d75d848304ac7e405b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",url = "https://files.pythonhosted.org/packages/ff/2e/1568934feb43370c1ffb78a77f0baaa5a8b6897513e7a91051af707ffdc4/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",hashes = {sha256 = "53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/01/1a/1a1118f38ab64eac2f6269eb8c120ab915be30e387bb561e3af904b12499/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/5c/da/44754d1d7ae0f22d6d3ce6c6b1486fc07ac2c524ed8f6eca636e2e1ee49b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/4d/98/f43cd89172220ec5aa86654967b22d862146bc4d736b1350b4c41e7c9c03/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/2b/cc/f77e8e242171d2158309f830f7d5d07e0531b756106f36bc18712dc439df/pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/54/7a/7be6a7bd43e0a47c147ba7fbf124fe8aaf1200bc587da925509641113b2d/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl",hashes = {sha256 = "44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl",url = "https://files.pythonhosted.org/packages/2a/07/31cf8fadffbb03be1cb520850e00a8490c0927ec456e8293cafda0726184/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl",hashes = {sha256 = "eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/b6/8d/bbaf4c6721b668d44f01861f297eb01c9b35f612f6b8e14173cb204e6240/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl",hashes = {sha256 = "9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/bb/93/3cc157026bca8f5006250e74515119fcaa6d6858aceee8f67ab6dc548c16/pydantic_core-2.33.2-cp39-cp39-win32.whl",hashes = {sha256 = "83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}}, - {name = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/5b/90/7edc3b2a0d9f0dda8806c04e511a67b0b7a41d2187e2003673a996fb4310/pydantic_core-2.33.2-cp39-cp39-win_amd64.whl",hashes = {sha256 = "f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl",url = "https://files.pythonhosted.org/packages/08/98/dbf3fdfabaf81cda5622154fda78ea9965ac467e3239078e0dcd6df159e7/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl",hashes = {sha256 = "87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/8d/99/7810aa9256e7f2ccd492590f86b79d370df1e9292f1f80b000b6a75bd2fb/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl",hashes = {sha256 = "7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/d8/60/bc06fa9027c7006cc6dd21e48dbf39076dc39d9abbaf718a1604973a9670/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/f2/40/9d03997d9518816c68b4dfccb88969756b9146031b61cd37f781c74c9b6a/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl",url = "https://files.pythonhosted.org/packages/d8/62/d490198d05d2d86672dc269f52579cad7261ced64c2df213d5c16e0aecb1/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl",hashes = {sha256 = "970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl",url = "https://files.pythonhosted.org/packages/9a/ec/4cd215534fd10b8549015f12ea650a1a973da20ce46430b68fc3185573e8/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl",hashes = {sha256 = "3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl",url = "https://files.pythonhosted.org/packages/1a/1a/abbd63d47e1d9b0d632fee6bb15785d0889c8a6e0a6c3b5a8e28ac1ec5d2/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl",hashes = {sha256 = "3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/80/1c/fa883643429908b1c90598fd2642af8839efd1d835b65af1f75fba4d94fe/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl",hashes = {sha256 = "3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}}, - {name = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl",hashes = {sha256 = "2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}}, ] marker = "\"default\" in dependency_groups" @@ -1122,49 +1091,6 @@ dependencies = [ "typing-extensions!=4.7.0,>=4.6.0", ] -[[packages]] -name = "tomli" -version = "2.2.1" -requires-python = ">=3.8" -sdist = {name = "tomli-2.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hashes = {sha256 = "cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}} -wheels = [ - {name = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}}, - {name = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}}, - {name = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}}, - {name = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}}, - {name = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}}, - {name = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}}, - {name = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}}, - {name = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}}, - {name = "tomli-2.2.1-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl",hashes = {sha256 = "d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}}, - {name = "tomli-2.2.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}}, - {name = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}}, - {name = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}}, - {name = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}}, - {name = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}}, - {name = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}}, - {name = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}}, - {name = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}}, - {name = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}}, - {name = "tomli-2.2.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl",hashes = {sha256 = "889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}}, - {name = "tomli-2.2.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}}, - {name = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}}, - {name = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}}, - {name = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}}, - {name = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}}, - {name = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}}, - {name = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}}, - {name = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}}, - {name = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}}, - {name = "tomli-2.2.1-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl",hashes = {sha256 = "465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}}, - {name = "tomli-2.2.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}}, - {name = "tomli-2.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl",hashes = {sha256 = "cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}}, -] -marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" - -[packages.tool.pdm] -dependencies = [] - [[packages]] name = "typing-extensions" version = "4.14.1" @@ -1358,46 +1284,7 @@ wheels = [ {name = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}}, {name = "charset_normalizer-3.4.2-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl",hashes = {sha256 = "db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}}, {name = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl",hashes = {sha256 = "daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}}, - {name = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl",hashes = {sha256 = "e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}}, - {name = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl",hashes = {sha256 = "f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}}, {name = "charset_normalizer-3.4.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl",hashes = {sha256 = "7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/28/f8/dfb01ff6cc9af38552c69c9027501ff5a5117c4cc18dcd27cb5259fa1888/charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/32/fb/74e26ee556a9dbfe3bd264289b67be1e6d616329403036f6507bb9f3f29c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/ad/06/8499ee5aa7addc6f6d72e068691826ff093329fe59891e83b092ae4c851c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/f1/a2/5e4c187680728219254ef107a6949c60ee0e9a916a5dadb148c7ae82459c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/4c/fe/56aca740dda674f0cc1ba1418c4d84534be51f639b5f98f538b332dc9a95/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/53/13/db2e7779f892386b589173dd689c1b1e304621c5792046edd8a978cbf9e0/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/69/35/e52ab9a276186f729bce7a0638585d2982f50402046e4b0faa5d2c3ef2da/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/a6/d8/af7333f732fc2e7635867d56cb7c349c28c7094910c72267586947561b4b/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/7a/3d/a5b2e48acef264d71e036ff30bcc49e51bde80219bb628ba3e00cf59baac/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/85/d8/23e2c112532a29f3eef374375a8684a4f3b8e784f62b01da931186f43494/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c7/57/93e0169f08ecc20fe82d12254a200dfaceddc1c12a4077bf454ecc597e33/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/2c/9d/9bf2b005138e7e060d7ebdec7503d0ef3240141587651f4b445bdf7286c2/charset_normalizer-3.4.2-cp39-cp39-win32.whl",hashes = {sha256 = "43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}}, - {name = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6d/24/5849d46cf4311bbf21b424c443b09b459f5b436b1558c04e45dbb7cc478b/charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl",hashes = {sha256 = "d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}}, ] marker = "\"default\" in dependency_groups or \"dev\" in extras or \"recommended\" in extras" @@ -1496,57 +1383,6 @@ wheels = [ {name = "aiohttp-3.12.14-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/22/32/5501ab525a47ba23c20613e568174d6c63aa09e2caa22cded5c6ea8e3ada/aiohttp-3.12.14-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2785b112346e435dd3a1a67f67713a3fe692d288542f1347ad255683f066d8e0"}}, {name = "aiohttp-3.12.14-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/06/af/28e24574801fcf1657945347ee10df3892311c2829b41232be6089e461e7/aiohttp-3.12.14-cp312-cp312-win32.whl",hashes = {sha256 = "15f5f4792c9c999a31d8decf444e79fcfd98497bf98e94284bf390a7bb8c1729"}}, {name = "aiohttp-3.12.14-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/98/d5/7ac2464aebd2eecac38dbe96148c9eb487679c512449ba5215d233755582/aiohttp-3.12.14-cp312-cp312-win_amd64.whl",hashes = {sha256 = "3b66e1a182879f579b105a80d5c4bd448b91a57e8933564bf41665064796a338"}}, - {name = "aiohttp-3.12.14-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/53/e1/8029b29316971c5fa89cec170274582619a01b3d82dd1036872acc9bc7e8/aiohttp-3.12.14-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "f4552ff7b18bcec18b60a90c6982049cdb9dac1dba48cf00b97934a06ce2e597"}}, - {name = "aiohttp-3.12.14-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/96/bd/4f204cf1e282041f7b7e8155f846583b19149e0872752711d0da5e9cc023/aiohttp-3.12.14-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "8283f42181ff6ccbcf25acaae4e8ab2ff7e92b3ca4a4ced73b2c12d8cd971393"}}, - {name = "aiohttp-3.12.14-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d6/0f/2a580fcdd113fe2197a3b9df30230c7e85bb10bf56f7915457c60e9addd9/aiohttp-3.12.14-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "040afa180ea514495aaff7ad34ec3d27826eaa5d19812730fe9e529b04bb2179"}}, - {name = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/38/78/2c1089f6adca90c3dd74915bafed6d6d8a87df5e3da74200f6b3a8b8906f/aiohttp-3.12.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "b413c12f14c1149f0ffd890f4141a7471ba4b41234fe4fd4a0ff82b1dc299dbb"}}, - {name = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/4a/c8/ce6c7a34d9c589f007cfe064da2d943b3dee5aabc64eaecd21faf927ab11/aiohttp-3.12.14-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "1d6f607ce2e1a93315414e3d448b831238f1874b9968e1195b06efaa5c87e245"}}, - {name = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/18/10/431cd3d089de700756a56aa896faf3ea82bee39d22f89db7ddc957580308/aiohttp-3.12.14-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "565e70d03e924333004ed101599902bba09ebb14843c8ea39d657f037115201b"}}, - {name = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/fa/b2/26f4524184e0f7ba46671c512d4b03022633bcf7d32fa0c6f1ef49d55800/aiohttp-3.12.14-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "4699979560728b168d5ab63c668a093c9570af2c7a78ea24ca5212c6cdc2b641"}}, - {name = "aiohttp-3.12.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/e0/30/aadcdf71b510a718e3d98a7bfeaea2396ac847f218b7e8edb241b09bd99a/aiohttp-3.12.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "ad5fdf6af93ec6c99bf800eba3af9a43d8bfd66dce920ac905c817ef4a712afe"}}, - {name = "aiohttp-3.12.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/67/7f/7ccf11756ae498fdedc3d689a0c36ace8fc82f9d52d3517da24adf6e9a74/aiohttp-3.12.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "4ac76627c0b7ee0e80e871bde0d376a057916cb008a8f3ffc889570a838f5cc7"}}, - {name = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/6b/4d/35ebc170b1856dd020c92376dbfe4297217625ef4004d56587024dc2289c/aiohttp-3.12.14-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "798204af1180885651b77bf03adc903743a86a39c7392c472891649610844635"}}, - {name = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/7b/24/46dc0380146f33e2e4aa088b92374b598f5bdcde1718c77e8d1a0094f1a4/aiohttp-3.12.14-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "4f1205f97de92c37dd71cf2d5bcfb65fdaed3c255d246172cce729a8d849b4da"}}, - {name = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/2f/0a/46599d7d19b64f4d0fe1b57bdf96a9a40b5c125f0ae0d8899bc22e91fdce/aiohttp-3.12.14-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "76ae6f1dd041f85065d9df77c6bc9c9703da9b5c018479d20262acc3df97d419"}}, - {name = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/08/86/b21b682e33d5ca317ef96bd21294984f72379454e689d7da584df1512a19/aiohttp-3.12.14-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "a194ace7bc43ce765338ca2dfb5661489317db216ea7ea700b0332878b392cab"}}, - {name = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/4f/45/f639482530b1396c365f23c5e3b1ae51c9bc02ba2b2248ca0c855a730059/aiohttp-3.12.14-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "16260e8e03744a6fe3fcb05259eeab8e08342c4c33decf96a9dad9f1187275d0"}}, - {name = "aiohttp-3.12.14-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/7e/e5/39635a9e06eed1d73671bd4079a3caf9cf09a49df08490686f45a710b80e/aiohttp-3.12.14-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8c779e5ebbf0e2e15334ea404fcce54009dc069210164a244d2eac8352a44b28"}}, - {name = "aiohttp-3.12.14-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/51/e1/7f1c77515d369b7419c5b501196526dad3e72800946c0099594c1f0c20b4/aiohttp-3.12.14-cp311-cp311-win32.whl",hashes = {sha256 = "a289f50bf1bd5be227376c067927f78079a7bdeccf8daa6a9e65c38bae14324b"}}, - {name = "aiohttp-3.12.14-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/06/24/a6bf915c85b7a5b07beba3d42b3282936b51e4578b64a51e8e875643c276/aiohttp-3.12.14-cp311-cp311-win_amd64.whl",hashes = {sha256 = "0b8a69acaf06b17e9c54151a6c956339cf46db4ff72b3ac28516d0f7068f4ced"}}, - {name = "aiohttp-3.12.14-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/0c/88/f161f429f9de391eee6a5c2cffa54e2ecd5b7122ae99df247f7734dfefcb/aiohttp-3.12.14-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "906d5075b5ba0dd1c66fcaaf60eb09926a9fef3ca92d912d2a0bbdbecf8b1248"}}, - {name = "aiohttp-3.12.14-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/fe/b5/24fa382a69a25d242e2baa3e56d5ea5227d1b68784521aaf3a1a8b34c9a4/aiohttp-3.12.14-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "c875bf6fc2fd1a572aba0e02ef4e7a63694778c5646cdbda346ee24e630d30fb"}}, - {name = "aiohttp-3.12.14-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/09/67/fda1bc34adbfaa950d98d934a23900918f9d63594928c70e55045838c943/aiohttp-3.12.14-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "fbb284d15c6a45fab030740049d03c0ecd60edad9cd23b211d7e11d3be8d56fd"}}, - {name = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/36/96/3ce1ea96d3cf6928b87cfb8cdd94650367f5c2f36e686a1f5568f0f13754/aiohttp-3.12.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "38e360381e02e1a05d36b223ecab7bc4a6e7b5ab15760022dc92589ee1d4238c"}}, - {name = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/be/04/ddea06cb4bc7d8db3745cf95e2c42f310aad485ca075bd685f0e4f0f6b65/aiohttp-3.12.14-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "aaf90137b5e5d84a53632ad95ebee5c9e3e7468f0aab92ba3f608adcb914fa95"}}, - {name = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/73/66/63942f104d33ce6ca7871ac6c1e2ebab48b88f78b2b7680c37de60f5e8cd/aiohttp-3.12.14-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "e532a25e4a0a2685fa295a31acf65e027fbe2bea7a4b02cdfbbba8a064577663"}}, - {name = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/20/00/aab615742b953f04b48cb378ee72ada88555b47b860b98c21c458c030a23/aiohttp-3.12.14-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "eab9762c4d1b08ae04a6c77474e6136da722e34fdc0e6d6eab5ee93ac29f35d1"}}, - {name = "aiohttp-3.12.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d6/4f/ef6d9f77225cf27747368c37b3d69fac1f8d6f9d3d5de2d410d155639524/aiohttp-3.12.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "abe53c3812b2899889a7fca763cdfaeee725f5be68ea89905e4275476ffd7e61"}}, - {name = "aiohttp-3.12.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/37/e1/e98a43c15aa52e9219a842f18c59cbae8bbe2d50c08d298f17e9e8bafa38/aiohttp-3.12.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "5760909b7080aa2ec1d320baee90d03b21745573780a072b66ce633eb77a8656"}}, - {name = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/71/5c/29c6dfb49323bcdb0239bf3fc97ffcf0eaf86d3a60426a3287ec75d67721/aiohttp-3.12.14-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "02fcd3f69051467bbaa7f84d7ec3267478c7df18d68b2e28279116e29d18d4f3"}}, - {name = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/79/60/ec90782084090c4a6b459790cfd8d17be2c5662c9c4b2d21408b2f2dc36c/aiohttp-3.12.14-cp310-cp310-musllinux_1_2_armv7l.whl",hashes = {sha256 = "4dcd1172cd6794884c33e504d3da3c35648b8be9bfa946942d353b939d5f1288"}}, - {name = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/22/89/205d3ad30865c32bc472ac13f94374210745b05bd0f2856996cb34d53396/aiohttp-3.12.14-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "224d0da41355b942b43ad08101b1b41ce633a654128ee07e36d75133443adcda"}}, - {name = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/48/ae/2f66edaa8bd6db2a4cba0386881eb92002cdc70834e2a93d1d5607132c7e/aiohttp-3.12.14-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "e387668724f4d734e865c1776d841ed75b300ee61059aca0b05bce67061dcacc"}}, - {name = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/08/3a/fa73bfc6e21407ea57f7906a816f0dc73663d9549da703be05dbd76d2dc3/aiohttp-3.12.14-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "dec9cde5b5a24171e0b0a4ca064b1414950904053fb77c707efd876a2da525d8"}}, - {name = "aiohttp-3.12.14-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e3/b3/751124b8ceb0831c17960d06ee31a4732cb4a6a006fdbfa1153d07c52226/aiohttp-3.12.14-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "bbad68a2af4877cc103cd94af9160e45676fc6f0c14abb88e6e092b945c2c8e3"}}, - {name = "aiohttp-3.12.14-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/81/3c/72477a1d34edb8ab8ce8013086a41526d48b64f77e381c8908d24e1c18f5/aiohttp-3.12.14-cp310-cp310-win32.whl",hashes = {sha256 = "ee580cb7c00bd857b3039ebca03c4448e84700dc1322f860cf7a500a6f62630c"}}, - {name = "aiohttp-3.12.14-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a2/c4/8aec4ccf1b822ec78e7982bd5cf971113ecce5f773f04039c76a083116fc/aiohttp-3.12.14-cp310-cp310-win_amd64.whl",hashes = {sha256 = "cf4f05b8cea571e2ccc3ca744e35ead24992d90a72ca2cf7ab7a2efbac6716db"}}, - {name = "aiohttp-3.12.14-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/cf/54/8a65095784f5c8b2a60a8baa2baabb15b8d507efb0911d59f94af04ba908/aiohttp-3.12.14-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "b8cc6b05e94d837bcd71c6531e2344e1ff0fb87abe4ad78a9261d67ef5d83eae"}}, - {name = "aiohttp-3.12.14-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/d0/23/65a82d33841c790178aed8aa6b5e720e37f08bdf7256936fa3bc86f03257/aiohttp-3.12.14-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "d1dcb015ac6a3b8facd3677597edd5ff39d11d937456702f0bb2b762e390a21b"}}, - {name = "aiohttp-3.12.14-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/10/66/9d51ec40613aca2f38d6ac527b592686a302197109aa1c0fe045040835ec/aiohttp-3.12.14-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "3779ed96105cd70ee5e85ca4f457adbce3d9ff33ec3d0ebcdf6c5727f26b21b3"}}, - {name = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/48/9e/2f14e4780a461351325d7821fb64e9107189315dd8f6e8a67e7afdbf875c/aiohttp-3.12.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "717a0680729b4ebd7569c1dcd718c46b09b360745fd8eb12317abc74b14d14d0"}}, - {name = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/b8/26/26ef03e6cc4b7fb275eaa76b33c128f72729e8833e512b6770f877560b6e/aiohttp-3.12.14-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "b5dd3a2ef7c7e968dbbac8f5574ebeac4d2b813b247e8cec28174a2ba3627170"}}, - {name = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/68/cf/fffc2a9edacbd475cfb508075bad052426ce0b9100f1045536ee1b683872/aiohttp-3.12.14-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "4710f77598c0092239bc12c1fcc278a444e16c7032d91babf5abbf7166463f7b"}}, - {name = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/0b/c5/bb8b29ef079d3ecb5960ec1b547b56bc52ee5ffc43c8a30ef21f9afeb67b/aiohttp-3.12.14-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "f3e9f75ae842a6c22a195d4a127263dbf87cbab729829e0bd7857fb1672400b2"}}, - {name = "aiohttp-3.12.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/09/0d/d18e2d2754497bf91b9559425e8c4286af61bdbe42d49c43d955c7269680/aiohttp-3.12.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "5f9c8d55d6802086edd188e3a7d85a77787e50d56ce3eb4757a3205fa4657922"}}, - {name = "aiohttp-3.12.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/33/c8/2c32cd25deb9f590cb8d50ff33fb3bb2cc8d1761958989f6f64cf00ef1cb/aiohttp-3.12.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "79b29053ff3ad307880d94562cca80693c62062a098a5776ea8ef5ef4b28d140"}}, - {name = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/0f/36/1b36ae47b9d6afdd39072373bb7157b464996376d562d3c50950ddf6d10e/aiohttp-3.12.14-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "23e1332fff36bebd3183db0c7a547a1da9d3b4091509f6d818e098855f2f27d3"}}, - {name = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/2b/e8/6864b7812351821168e80ca102d7fa244a78fefe9690995a40e8b5c19f4b/aiohttp-3.12.14-cp39-cp39-musllinux_1_2_armv7l.whl",hashes = {sha256 = "a564188ce831fd110ea76bcc97085dd6c625b427db3f1dbb14ca4baa1447dcbc"}}, - {name = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/9b/55/f90e3eb25330f8a564a6e6b4d3cc15d3630bd28b0795a025e397e3279411/aiohttp-3.12.14-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "a7a1b4302f70bb3ec40ca86de82def532c97a80db49cac6a6700af0de41af5ee"}}, - {name = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/1b/f7/39c3570434bb7e81601155ba71327735b26548473cca2d5c7f5badabb140/aiohttp-3.12.14-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "1b07ccef62950a2519f9bfc1e5b294de5dd84329f444ca0b329605ea787a3de5"}}, - {name = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/46/0d/caee8733fbe511c34a54e93ee26c4b8d505e12785444d31f772a610df7ab/aiohttp-3.12.14-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "938bd3ca6259e7e48b38d84f753d548bd863e0c222ed6ee6ace3fd6752768a84"}}, - {name = "aiohttp-3.12.14-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/24/f3/5d21196abf74dee66c5809e764cc27a2275e54c9355019c21be3bf77dd77/aiohttp-3.12.14-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8bc784302b6b9f163b54c4e93d7a6f09563bd01ff2b841b29ed3ac126e5040bf"}}, - {name = "aiohttp-3.12.14-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/54/bb/b4226f4fd0597d5245f284d10be48bf1ef610ab4f57d4239686fb03d1814/aiohttp-3.12.14-cp39-cp39-win32.whl",hashes = {sha256 = "a3416f95961dd7d5393ecff99e3f41dc990fb72eda86c11f2a60308ac6dcd7a0"}}, - {name = "aiohttp-3.12.14-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a0/c0/2f1cefb7b077bf5c19f01bdf0d82b89de0bf2801b441eda23ada0b8966ac/aiohttp-3.12.14-cp39-cp39-win_amd64.whl",hashes = {sha256 = "196858b8820d7f60578f8b47e5669b3195c21d8ab261e39b1d705346458f445f"}}, ] marker = "\"default\" in dependency_groups or \"dev\" in extras" @@ -1563,17 +1399,73 @@ dependencies = [ ] [[packages]] -name = "async-timeout" -version = "5.0.1" -requires-python = ">=3.8" -sdist = {name = "async_timeout-5.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hashes = {sha256 = "d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}} +name = "multidict" +version = "6.6.3" +requires-python = ">=3.9" +sdist = {name = "multidict-6.6.3.tar.gz", url = "https://files.pythonhosted.org/packages/3d/2c/5dad12e82fbdf7470f29bff2171484bf07cb3b16ada60a6589af8f376440/multidict-6.6.3.tar.gz", hashes = {sha256 = "798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc"}} wheels = [ - {name = "async_timeout-5.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl",hashes = {sha256 = "39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}}, + {name = "multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/52/1d/0bebcbbb4f000751fbd09957257903d6e002943fc668d841a4cf2fb7f872/multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55"}}, + {name = "multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/8f/cbe241b0434cfe257f65c2b1bcf9e8d5fb52bc708c5061fb29b0fed22bdf/multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b"}}, + {name = "multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/32/d2/0b3b23f9dbad5b270b22a3ac3ea73ed0a50ef2d9a390447061178ed6bdb8/multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65"}}, + {name = "multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/fd/fe/6eb68927e823999e3683bc49678eb20374ba9615097d085298fd5b386564/multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3"}}, + {name = "multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e7/ab/320d8507e7726c460cb77117848b3834ea0d59e769f36fdae495f7669929/multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c"}}, + {name = "multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/76/60/38ee422db515ac69834e60142a1a69111ac96026e76e8e9aa347fd2e4591/multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6"}}, + {name = "multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/27/fb/905224fde2dff042b030c27ad95a7ae744325cf54b890b443d30a789b80e/multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8"}}, + {name = "multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/76/35/dc38ab361051beae08d1a53965e3e1a418752fc5be4d3fb983c5582d8784/multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca"}}, + {name = "multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/a3/0a485b7f36e422421b17e2bbb5a81c1af10eac1d4476f2ff92927c730479/multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884"}}, + {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b4/59/bcdd52c1dab7c0e0d75ff19cac751fbd5f850d1fc39172ce809a74aa9ea4/multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7"}}, + {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/bb/a4/2d96aaa6eae8067ce108d4acee6f45ced5728beda55c0f02ae1072c730d1/multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl",hashes = {sha256 = "6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b"}}, + {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/25/d2/ed9f847fa5c7d0677d4f02ea2c163d5e48573de3f57bacf5670e43a5ffaa/multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c"}}, + {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/1f/af/9155850372563fc550803d3f25373308aa70f59b52cff25854086ecb4a79/multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b"}}, + {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/36/2f/c6a728f699896252cf309769089568a33c6439626648843f78743660709d/multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl",hashes = {sha256 = "fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1"}}, + {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d0/60/689880776d6b18fa2b70f6cc74ff87dd6c6b9b47bd9cf74c16fecfaa6ad9/multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6"}}, + {name = "multidict-6.6.3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/75/5e/325b11f2222a549019cf2ef879c1f81f94a0d40ace3ef55cf529915ba6cc/multidict-6.6.3-cp313-cp313-win32.whl",hashes = {sha256 = "5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e"}}, + {name = "multidict-6.6.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b1/ad/cf46e73f5d6e3c775cabd2a05976547f3f18b39bee06260369a42501f053/multidict-6.6.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9"}}, + {name = "multidict-6.6.3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/c5/c9/2e3fe950db28fb7c62e1a5f46e1e38759b072e2089209bc033c2798bb5ec/multidict-6.6.3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600"}}, + {name = "multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/3a/58/aaf8114cf34966e084a8cc9517771288adb53465188843d5a19862cb6dc3/multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl",hashes = {sha256 = "02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134"}}, + {name = "multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/71/af/5402e7b58a1f5b987a07ad98f2501fdba2a4f4b4c30cf114e3ce8db64c87/multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37"}}, + {name = "multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/39/65/ab3c8cafe21adb45b24a50266fd747147dec7847425bc2a0f6934b3ae9ce/multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8"}}, + {name = "multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/49/ba/9fcc1b332f67cc0c0c8079e263bfab6660f87fe4e28a35921771ff3eea0d/multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1"}}, + {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/a4/14/0145a251f555f7c754ce2dcbcd012939bbd1f34f066fa5d28a50e722a054/multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373"}}, + {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/9e/d4/d5c0bd2bbb173b586c249a151a26d2fb3ec7d53c96e42091c9fef4e1f10c/multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e"}}, + {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/21/32/c9a2d8444a50ec48c4733ccc67254100c10e1c8ae8e40c7a2d2183b59b97/multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f"}}, + {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/68/d0/14fa1699f4ef629eae08ad6201c6b476098f5efb051b296f4c26be7a9fdf/multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0"}}, + {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/da/88/84a27570fbe303c65607d517a5f147cd2fc046c2d1da02b84b17b9bdc2aa/multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc"}}, + {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/1c/60/dca352a0c999ce96a5d8b8ee0b2b9f729dcad2e0b0c195f8286269a2074c/multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f"}}, + {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/50/ef/433fa3ed06028f03946f3993223dada70fb700f763f70c00079533c34578/multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl",hashes = {sha256 = "e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471"}}, + {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/1b/1f/487612ab56fbe35715320905215a57fede20de7db40a261759690dc80471/multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2"}}, + {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/da/6f/ce8b79de16cd885c6f9052c96a3671373d00c59b3ee635ea93e6e81b8ccf/multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648"}}, + {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/bb/fe/a2514a6aba78e5abefa1624ca85ae18f542d95ac5cde2e3815a9fbf369aa/multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl",hashes = {sha256 = "70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d"}}, + {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8c/22/b788718d63bb3cce752d107a57c85fcd1a212c6c778628567c9713f9345a/multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c"}}, + {name = "multidict-6.6.3-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/22/d6/fdb3d0670819f2228f3f7d9af613d5e652c15d170c83e5f1c94fbc55a25b/multidict-6.6.3-cp313-cp313t-win32.whl",hashes = {sha256 = "639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e"}}, + {name = "multidict-6.6.3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b6/d6/a9d2c808f2c489ad199723197419207ecbfbc1776f6e155e1ecea9c883aa/multidict-6.6.3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d"}}, + {name = "multidict-6.6.3-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f2/40/b68001cba8188dd267590a111f9661b6256debc327137667e832bf5d66e8/multidict-6.6.3-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb"}}, + {name = "multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/0e/a0/6b57988ea102da0623ea814160ed78d45a2645e4bbb499c2896d12833a70/multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6"}}, + {name = "multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/7a/d1e92665b0850c6c0508f101f9cf0410c1afa24973e1115fe9c6a185ebf7/multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f"}}, + {name = "multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/52/6f/dd104490e01be6ef8bf9573705d8572f8c2d2c561f06e3826b081d9e6591/multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55"}}, + {name = "multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/44/fe/06e0e01b1b0611e6581b7fd5a85b43dacc08b6cea3034f902f383b0873e5/multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b"}}, + {name = "multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ce/71/4f0e558fb77696b89c233c1ee2d92f3e1d5459070a0e89153c9e9e804186/multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888"}}, + {name = "multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/e3/25/cca0e68228addad24903801ed1ab42e21307a1b4b6dd2cf63da5d3ae082a/multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d"}}, + {name = "multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/6e/a3/46f2d420d86bbcb8fe660b26a10a219871a0fbf4d43cb846a4031533f3e0/multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680"}}, + {name = "multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/9e/73/1c743542fe00794a2ec7466abd3f312ccb8fad8dff9f36d42e18fb1ec33e/multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a"}}, + {name = "multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/a4/11/6ec9dcbe2264b92778eeb85407d1df18812248bf3506a5a1754bc035db0c/multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961"}}, + {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/9b/2b/631b1e2afeb5f1696846d747d36cda075bfdc0bc7245d6ba5c319278d6c4/multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65"}}, + {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/bf/0e/7e3b93f79efeb6111d3bf9a1a69e555ba1d07ad1c11bceb56b7310d0d7ee/multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl",hashes = {sha256 = "e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643"}}, + {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ad/9e/086846c1d6601948e7de556ee464a2d4c85e33883e749f46b9547d7b0704/multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063"}}, + {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/8c/7b/86ec260118e522f1a31550e87b23542294880c97cfbf6fb18cc67b044c66/multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3"}}, + {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/8c/bd/22ce8f47abb0be04692c9fc4638508b8340987b18691aa7775d927b73f72/multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl",hashes = {sha256 = "346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75"}}, + {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/9c/91b7ac1691be95cd1f4a26e36a74b97cda6aa9820632d31aab4410f46ebd/multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10"}}, + {name = "multidict-6.6.3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/6f/5c/4d7adc739884f7a9fbe00d1eac8c034023ef8bad71f2ebe12823ca2e3649/multidict-6.6.3-cp312-cp312-win32.whl",hashes = {sha256 = "73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5"}}, + {name = "multidict-6.6.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6a/a3/0fbc7afdf7cb1aa12a086b02959307848eb6bcc8f66fcb66c0cb57e2a2c1/multidict-6.6.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17"}}, + {name = "multidict-6.6.3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/b8/95/8c825bd70ff9b02462dc18d1295dd08d3e9e4eb66856d292ffa62cfe1920/multidict-6.6.3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b"}}, + {name = "multidict-6.6.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl",hashes = {sha256 = "8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a"}}, ] -marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" +marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] -dependencies = [] +dependencies = [ + "typing-extensions>=4.1.0; python_version < \"3.11\"", +] [[packages]] name = "h2" @@ -1664,129 +1556,6 @@ dependencies = [ "markdown-it-py<4.0.0,>=1.0.0", ] -[[packages]] -name = "multidict" -version = "6.6.3" -requires-python = ">=3.9" -sdist = {name = "multidict-6.6.3.tar.gz", url = "https://files.pythonhosted.org/packages/3d/2c/5dad12e82fbdf7470f29bff2171484bf07cb3b16ada60a6589af8f376440/multidict-6.6.3.tar.gz", hashes = {sha256 = "798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc"}} -wheels = [ - {name = "multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/52/1d/0bebcbbb4f000751fbd09957257903d6e002943fc668d841a4cf2fb7f872/multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55"}}, - {name = "multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/8f/cbe241b0434cfe257f65c2b1bcf9e8d5fb52bc708c5061fb29b0fed22bdf/multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b"}}, - {name = "multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/32/d2/0b3b23f9dbad5b270b22a3ac3ea73ed0a50ef2d9a390447061178ed6bdb8/multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65"}}, - {name = "multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/fd/fe/6eb68927e823999e3683bc49678eb20374ba9615097d085298fd5b386564/multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3"}}, - {name = "multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e7/ab/320d8507e7726c460cb77117848b3834ea0d59e769f36fdae495f7669929/multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c"}}, - {name = "multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/76/60/38ee422db515ac69834e60142a1a69111ac96026e76e8e9aa347fd2e4591/multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6"}}, - {name = "multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/27/fb/905224fde2dff042b030c27ad95a7ae744325cf54b890b443d30a789b80e/multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8"}}, - {name = "multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/76/35/dc38ab361051beae08d1a53965e3e1a418752fc5be4d3fb983c5582d8784/multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca"}}, - {name = "multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/a3/0a485b7f36e422421b17e2bbb5a81c1af10eac1d4476f2ff92927c730479/multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884"}}, - {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b4/59/bcdd52c1dab7c0e0d75ff19cac751fbd5f850d1fc39172ce809a74aa9ea4/multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7"}}, - {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/bb/a4/2d96aaa6eae8067ce108d4acee6f45ced5728beda55c0f02ae1072c730d1/multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl",hashes = {sha256 = "6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b"}}, - {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/25/d2/ed9f847fa5c7d0677d4f02ea2c163d5e48573de3f57bacf5670e43a5ffaa/multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c"}}, - {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/1f/af/9155850372563fc550803d3f25373308aa70f59b52cff25854086ecb4a79/multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b"}}, - {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/36/2f/c6a728f699896252cf309769089568a33c6439626648843f78743660709d/multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl",hashes = {sha256 = "fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1"}}, - {name = "multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d0/60/689880776d6b18fa2b70f6cc74ff87dd6c6b9b47bd9cf74c16fecfaa6ad9/multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6"}}, - {name = "multidict-6.6.3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/75/5e/325b11f2222a549019cf2ef879c1f81f94a0d40ace3ef55cf529915ba6cc/multidict-6.6.3-cp313-cp313-win32.whl",hashes = {sha256 = "5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e"}}, - {name = "multidict-6.6.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b1/ad/cf46e73f5d6e3c775cabd2a05976547f3f18b39bee06260369a42501f053/multidict-6.6.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9"}}, - {name = "multidict-6.6.3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/c5/c9/2e3fe950db28fb7c62e1a5f46e1e38759b072e2089209bc033c2798bb5ec/multidict-6.6.3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600"}}, - {name = "multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/3a/58/aaf8114cf34966e084a8cc9517771288adb53465188843d5a19862cb6dc3/multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl",hashes = {sha256 = "02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134"}}, - {name = "multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/71/af/5402e7b58a1f5b987a07ad98f2501fdba2a4f4b4c30cf114e3ce8db64c87/multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37"}}, - {name = "multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/39/65/ab3c8cafe21adb45b24a50266fd747147dec7847425bc2a0f6934b3ae9ce/multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8"}}, - {name = "multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/49/ba/9fcc1b332f67cc0c0c8079e263bfab6660f87fe4e28a35921771ff3eea0d/multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1"}}, - {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/a4/14/0145a251f555f7c754ce2dcbcd012939bbd1f34f066fa5d28a50e722a054/multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373"}}, - {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/9e/d4/d5c0bd2bbb173b586c249a151a26d2fb3ec7d53c96e42091c9fef4e1f10c/multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e"}}, - {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/21/32/c9a2d8444a50ec48c4733ccc67254100c10e1c8ae8e40c7a2d2183b59b97/multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f"}}, - {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/68/d0/14fa1699f4ef629eae08ad6201c6b476098f5efb051b296f4c26be7a9fdf/multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0"}}, - {name = "multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/da/88/84a27570fbe303c65607d517a5f147cd2fc046c2d1da02b84b17b9bdc2aa/multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc"}}, - {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/1c/60/dca352a0c999ce96a5d8b8ee0b2b9f729dcad2e0b0c195f8286269a2074c/multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f"}}, - {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/50/ef/433fa3ed06028f03946f3993223dada70fb700f763f70c00079533c34578/multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl",hashes = {sha256 = "e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471"}}, - {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/1b/1f/487612ab56fbe35715320905215a57fede20de7db40a261759690dc80471/multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2"}}, - {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/da/6f/ce8b79de16cd885c6f9052c96a3671373d00c59b3ee635ea93e6e81b8ccf/multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648"}}, - {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/bb/fe/a2514a6aba78e5abefa1624ca85ae18f542d95ac5cde2e3815a9fbf369aa/multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl",hashes = {sha256 = "70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d"}}, - {name = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8c/22/b788718d63bb3cce752d107a57c85fcd1a212c6c778628567c9713f9345a/multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c"}}, - {name = "multidict-6.6.3-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/22/d6/fdb3d0670819f2228f3f7d9af613d5e652c15d170c83e5f1c94fbc55a25b/multidict-6.6.3-cp313-cp313t-win32.whl",hashes = {sha256 = "639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e"}}, - {name = "multidict-6.6.3-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b6/d6/a9d2c808f2c489ad199723197419207ecbfbc1776f6e155e1ecea9c883aa/multidict-6.6.3-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d"}}, - {name = "multidict-6.6.3-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f2/40/b68001cba8188dd267590a111f9661b6256debc327137667e832bf5d66e8/multidict-6.6.3-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb"}}, - {name = "multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/0e/a0/6b57988ea102da0623ea814160ed78d45a2645e4bbb499c2896d12833a70/multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6"}}, - {name = "multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/7a/d1e92665b0850c6c0508f101f9cf0410c1afa24973e1115fe9c6a185ebf7/multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f"}}, - {name = "multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/52/6f/dd104490e01be6ef8bf9573705d8572f8c2d2c561f06e3826b081d9e6591/multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55"}}, - {name = "multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/44/fe/06e0e01b1b0611e6581b7fd5a85b43dacc08b6cea3034f902f383b0873e5/multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b"}}, - {name = "multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ce/71/4f0e558fb77696b89c233c1ee2d92f3e1d5459070a0e89153c9e9e804186/multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888"}}, - {name = "multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/e3/25/cca0e68228addad24903801ed1ab42e21307a1b4b6dd2cf63da5d3ae082a/multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d"}}, - {name = "multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/6e/a3/46f2d420d86bbcb8fe660b26a10a219871a0fbf4d43cb846a4031533f3e0/multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680"}}, - {name = "multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/9e/73/1c743542fe00794a2ec7466abd3f312ccb8fad8dff9f36d42e18fb1ec33e/multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a"}}, - {name = "multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/a4/11/6ec9dcbe2264b92778eeb85407d1df18812248bf3506a5a1754bc035db0c/multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961"}}, - {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/9b/2b/631b1e2afeb5f1696846d747d36cda075bfdc0bc7245d6ba5c319278d6c4/multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65"}}, - {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/bf/0e/7e3b93f79efeb6111d3bf9a1a69e555ba1d07ad1c11bceb56b7310d0d7ee/multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl",hashes = {sha256 = "e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643"}}, - {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ad/9e/086846c1d6601948e7de556ee464a2d4c85e33883e749f46b9547d7b0704/multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063"}}, - {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/8c/7b/86ec260118e522f1a31550e87b23542294880c97cfbf6fb18cc67b044c66/multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3"}}, - {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/8c/bd/22ce8f47abb0be04692c9fc4638508b8340987b18691aa7775d927b73f72/multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl",hashes = {sha256 = "346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75"}}, - {name = "multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/9c/91b7ac1691be95cd1f4a26e36a74b97cda6aa9820632d31aab4410f46ebd/multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10"}}, - {name = "multidict-6.6.3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/6f/5c/4d7adc739884f7a9fbe00d1eac8c034023ef8bad71f2ebe12823ca2e3649/multidict-6.6.3-cp312-cp312-win32.whl",hashes = {sha256 = "73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5"}}, - {name = "multidict-6.6.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6a/a3/0fbc7afdf7cb1aa12a086b02959307848eb6bcc8f66fcb66c0cb57e2a2c1/multidict-6.6.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17"}}, - {name = "multidict-6.6.3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/b8/95/8c825bd70ff9b02462dc18d1295dd08d3e9e4eb66856d292ffa62cfe1920/multidict-6.6.3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b"}}, - {name = "multidict-6.6.3-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/08/f0/1a39863ced51f639c81a5463fbfa9eb4df59c20d1a8769ab9ef4ca57ae04/multidict-6.6.3-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "18f4eba0cbac3546b8ae31e0bbc55b02c801ae3cbaf80c247fcdd89b456ff58c"}}, - {name = "multidict-6.6.3-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/c9/0e/a7cfa451c7b0365cd844e90b41e21fab32edaa1e42fc0c9f68461ce44ed7/multidict-6.6.3-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "ef43b5dd842382329e4797c46f10748d8c2b6e0614f46b4afe4aee9ac33159df"}}, - {name = "multidict-6.6.3-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c6/bb/a14a4efc5ee748cc1904b0748be278c31b9295ce5f4d2ef66526f410b94d/multidict-6.6.3-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "bf9bd1fd5eec01494e0f2e8e446a74a85d5e49afb63d75a9934e4a5423dba21d"}}, - {name = "multidict-6.6.3-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/c2/f8/410677d563c2d55e063ef74fe578f9d53fe6b0a51649597a5861f83ffa15/multidict-6.6.3-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "5bd8d6f793a787153956cd35e24f60485bf0651c238e207b9a54f7458b16d539"}}, - {name = "multidict-6.6.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/fd/df/2b787f80059314a98e1ec6a4cc7576244986df3e56b3c755e6fc7c99e038/multidict-6.6.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1bf99b4daf908c73856bd87ee0a2499c3c9a3d19bb04b9c6025e66af3fd07462"}}, - {name = "multidict-6.6.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/05/f2/f9117089151b9a8ab39f9019620d10d9718eec2ac89e7ca9d30f3ec78e96/multidict-6.6.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "0b9e59946b49dafaf990fd9c17ceafa62976e8471a14952163d10a7a630413a9"}}, - {name = "multidict-6.6.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/93/2d/7115300ec5b699faa152c56799b089a53ed69e399c3c2d528251f0aeda1a/multidict-6.6.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "e2db616467070d0533832d204c54eea6836a5e628f2cb1e6dfd8cd6ba7277cb7"}}, - {name = "multidict-6.6.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/15/ea/ff4bab367623e39c20d3b07637225c7688d79e4f3cc1f3b9f89867677f9a/multidict-6.6.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "7394888236621f61dcdd25189b2768ae5cc280f041029a5bcf1122ac63df79f9"}}, - {name = "multidict-6.6.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/74/07/2c9246cda322dfe08be85f1b8739646f2c4c5113a1422d7a407763422ec4/multidict-6.6.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "f114d8478733ca7388e7c7e0ab34b72547476b97009d643644ac33d4d3fe1821"}}, - {name = "multidict-6.6.3-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a8/62/279c13d584207d5697a752a66ffc9bb19355a95f7659140cb1b3cf82180e/multidict-6.6.3-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "cdf22e4db76d323bcdc733514bf732e9fb349707c98d341d40ebcc6e9318ef3d"}}, - {name = "multidict-6.6.3-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/69/cc/e06636f48c6d51e724a8bc8d9e1db5f136fe1df066d7cafe37ef4000f86a/multidict-6.6.3-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "e995a34c3d44ab511bfc11aa26869b9d66c2d8c799fa0e74b28a473a692532d6"}}, - {name = "multidict-6.6.3-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/89/a4/66c9d8fb9acf3b226cdd468ed009537ac65b520aebdc1703dd6908b19d33/multidict-6.6.3-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "766a4a5996f54361d8d5a9050140aa5362fe48ce51c755a50c0bc3706460c430"}}, - {name = "multidict-6.6.3-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/cf/01/c69e0317be556e46257826d5449feb4e6aa0d18573e567a48a2c14156f1f/multidict-6.6.3-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "3893a0d7d28a7fe6ca7a1f760593bc13038d1d35daf52199d431b61d2660602b"}}, - {name = "multidict-6.6.3-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/c0/da/9cc1da0299762d20e626fe0042e71b5694f9f72d7d3f9678397cbaa71b2b/multidict-6.6.3-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "934796c81ea996e61914ba58064920d6cad5d99140ac3167901eb932150e2e56"}}, - {name = "multidict-6.6.3-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e6/91/b22756afec99cc31105ddd4a52f95ab32b1a4a58f4d417979c570c4a922e/multidict-6.6.3-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "9ed948328aec2072bc00f05d961ceadfd3e9bfc2966c1319aeaf7b7c21219183"}}, - {name = "multidict-6.6.3-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/be/f1/adcc185b878036a20399d5be5228f3cbe7f823d78985d101d425af35c800/multidict-6.6.3-cp311-cp311-win32.whl",hashes = {sha256 = "9f5b28c074c76afc3e4c610c488e3493976fe0e596dd3db6c8ddfbb0134dcac5"}}, - {name = "multidict-6.6.3-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/e0/d4/27652c1c6526ea6b4f5ddd397e93f4232ff5de42bea71d339bc6a6cc497f/multidict-6.6.3-cp311-cp311-win_amd64.whl",hashes = {sha256 = "bc7f6fbc61b1c16050a389c630da0b32fc6d4a3d191394ab78972bf5edc568c2"}}, - {name = "multidict-6.6.3-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/16/18/23f4932019804e56d3c2413e237f866444b774b0263bcb81df2fdecaf593/multidict-6.6.3-cp311-cp311-win_arm64.whl",hashes = {sha256 = "d4e47d8faffaae822fb5cba20937c048d4f734f43572e7079298a6c39fb172cb"}}, - {name = "multidict-6.6.3-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/0b/67/414933982bce2efce7cbcb3169eaaf901e0f25baec69432b4874dfb1f297/multidict-6.6.3-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "a2be5b7b35271f7fff1397204ba6708365e3d773579fe2a30625e16c4b4ce817"}}, - {name = "multidict-6.6.3-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/fe/d8a3ee1fad37dc2ef4f75488b0d9d4f25bf204aad8306cbab63d97bff64a/multidict-6.6.3-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "12f4581d2930840295c461764b9a65732ec01250b46c6b2c510d7ee68872b140"}}, - {name = "multidict-6.6.3-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/1f/e0/265d89af8c98240265d82b8cbcf35897f83b76cd59ee3ab3879050fd8c45/multidict-6.6.3-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "dd7793bab517e706c9ed9d7310b06c8672fd0aeee5781bfad612f56b8e0f7d14"}}, - {name = "multidict-6.6.3-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/e6/05/6b759379f7e8e04ccc97cfb2a5dcc5cdbd44a97f072b2272dc51281e6a40/multidict-6.6.3-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "72d8815f2cd3cf3df0f83cac3f3ef801d908b2d90409ae28102e0553af85545a"}}, - {name = "multidict-6.6.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/4e/f5/8d5a15488edd9a91fa4aad97228d785df208ed6298580883aa3d9def1959/multidict-6.6.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "531e331a2ee53543ab32b16334e2deb26f4e6b9b28e41f8e0c87e99a6c8e2d69"}}, - {name = "multidict-6.6.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/6e/b5/a8f317d47d0ac5bb746d6d8325885c8967c2a8ce0bb57be5399e3642cccb/multidict-6.6.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "42ca5aa9329a63be8dc49040f63817d1ac980e02eeddba763a9ae5b4027b9c9c"}}, - {name = "multidict-6.6.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/76/88/18b2a0d5e80515fa22716556061189c2853ecf2aa2133081ebbe85ebea38/multidict-6.6.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "208b9b9757060b9faa6f11ab4bc52846e4f3c2fb8b14d5680c8aac80af3dc751"}}, - {name = "multidict-6.6.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/62/bf/ebfcfd6b55a1b05ef16d0775ae34c0fe15e8dab570d69ca9941073b969e7/multidict-6.6.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "acf6b97bd0884891af6a8b43d0f586ab2fcf8e717cbd47ab4bdddc09e20652d8"}}, - {name = "multidict-6.6.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/44/11/780615a98fd3775fc309d0234d563941af69ade2df0bb82c91dda6ddaea1/multidict-6.6.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "68e9e12ed00e2089725669bdc88602b0b6f8d23c0c95e52b95f0bc69f7fe9b55"}}, - {name = "multidict-6.6.3-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/28/3d/35f33045e21034b388686213752cabc3a1b9d03e20969e6fa8f1b1d82db1/multidict-6.6.3-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "05db2f66c9addb10cfa226e1acb363450fab2ff8a6df73c622fefe2f5af6d4e7"}}, - {name = "multidict-6.6.3-cp310-cp310-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/6e/cc/ff84c03b95b430015d2166d9aae775a3985d757b94f6635010d0038d9241/multidict-6.6.3-cp310-cp310-musllinux_1_2_armv7l.whl",hashes = {sha256 = "0db58da8eafb514db832a1b44f8fa7906fdd102f7d982025f816a93ba45e3dcb"}}, - {name = "multidict-6.6.3-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/2e/f0/8cd49a0b37bdea673a4b793c2093f2f4ba8e7c9d6d7c9bd672fd6d38cd11/multidict-6.6.3-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "14117a41c8fdb3ee19c743b1c027da0736fdb79584d61a766da53d399b71176c"}}, - {name = "multidict-6.6.3-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/96/19/5d9a0cfdafe65d82b616a45ae950975820289069f885328e8185e64283c2/multidict-6.6.3-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "877443eaaabcd0b74ff32ebeed6f6176c71850feb7d6a1d2db65945256ea535c"}}, - {name = "multidict-6.6.3-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/e6/dc/c90066151da87d1e489f147b9b4327927241e65f1876702fafec6729c014/multidict-6.6.3-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "70b72e749a4f6e7ed8fb334fa8d8496384840319512746a5f42fa0aec79f4d61"}}, - {name = "multidict-6.6.3-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/ec/39/458afb0cccbb0ee9164365273be3e039efddcfcb94ef35924b7dbdb05db0/multidict-6.6.3-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "43571f785b86afd02b3855c5ac8e86ec921b760298d6f82ff2a61daf5a35330b"}}, - {name = "multidict-6.6.3-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/35/38/0016adac3990426610a081787011177e661875546b434f50a26319dc8372/multidict-6.6.3-cp310-cp310-win32.whl",hashes = {sha256 = "20c5a0c3c13a15fd5ea86c42311859f970070e4e24de5a550e99d7c271d76318"}}, - {name = "multidict-6.6.3-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f3/d2/17897a8f3f2c5363d969b4c635aa40375fe1f09168dc09a7826780bfb2a4/multidict-6.6.3-cp310-cp310-win_amd64.whl",hashes = {sha256 = "ab0a34a007704c625e25a9116c6770b4d3617a071c8a7c30cd338dfbadfe6485"}}, - {name = "multidict-6.6.3-cp310-cp310-win_arm64.whl",url = "https://files.pythonhosted.org/packages/2d/5f/d4a717c1e457fe44072e33fa400d2b93eb0f2819c4d669381f925b7cba1f/multidict-6.6.3-cp310-cp310-win_arm64.whl",hashes = {sha256 = "769841d70ca8bdd140a715746199fc6473414bd02efd678d75681d2d6a8986c5"}}, - {name = "multidict-6.6.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl",hashes = {sha256 = "8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a"}}, - {name = "multidict-6.6.3-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/d2/64/ba29bd6dfc895e592b2f20f92378e692ac306cf25dd0be2f8e0a0f898edb/multidict-6.6.3-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "c8161b5a7778d3137ea2ee7ae8a08cce0010de3b00ac671c5ebddeaa17cefd22"}}, - {name = "multidict-6.6.3-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/ca/cd/872ae4c134257dacebff59834983c1615d6ec863b6e3d360f3203aad8400/multidict-6.6.3-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "1328201ee930f069961ae707d59c6627ac92e351ed5b92397cf534d1336ce557"}}, - {name = "multidict-6.6.3-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/15/35/d417d8f62f2886784b76df60522d608aba39dfc83dd53b230ca71f2d4c53/multidict-6.6.3-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "b1db4d2093d6b235de76932febf9d50766cf49a5692277b2c28a501c9637f616"}}, - {name = "multidict-6.6.3-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/85/59/25cddf781f12cddb2386baa29744a3fdd160eb705539b48065f0cffd86d5/multidict-6.6.3-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "53becb01dd8ebd19d1724bebe369cfa87e4e7f29abbbe5c14c98ce4c383e16cd"}}, - {name = "multidict-6.6.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c4/21/4055b6a527954c572498a8068c26bd3b75f2b959080e17e12104b592273c/multidict-6.6.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "41bb9d1d4c303886e2d85bade86e59885112a7f4277af5ad47ab919a2251f306"}}, - {name = "multidict-6.6.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/58/98/17f1f80bdba0b2fef49cf4ba59cebf8a81797f745f547abb5c9a4039df62/multidict-6.6.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "775b464d31dac90f23192af9c291dc9f423101857e33e9ebf0020a10bfcf4144"}}, - {name = "multidict-6.6.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f8/0e/a5e595fdd0820069f0c29911d5dc9dc3a75ec755ae733ce59a4e6962ae42/multidict-6.6.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "d04d01f0a913202205a598246cf77826fe3baa5a63e9f6ccf1ab0601cf56eca0"}}, - {name = "multidict-6.6.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/66/9e/0f51e4cffea2daf24c137feabc9ec848ce50f8379c9badcbac00b41ab55e/multidict-6.6.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "d25594d3b38a2e6cabfdcafef339f754ca6e81fbbdb6650ad773ea9775af35ab"}}, - {name = "multidict-6.6.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/49/a0/a7cfc13c9a71ceb8c1c55457820733af9ce01e121139271f7b13e30c29d2/multidict-6.6.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "35712f1748d409e0707b165bf49f9f17f9e28ae85470c41615778f8d4f7d9609"}}, - {name = "multidict-6.6.3-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c7/50/7ae0d1149ac71cab6e20bb7faf2a1868435974994595dadfdb7377f7140f/multidict-6.6.3-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1c8082e5814b662de8589d6a06c17e77940d5539080cbab9fe6794b5241b76d9"}}, - {name = "multidict-6.6.3-cp39-cp39-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/b4/ac/2d0bf836c9c63a57360d57b773359043b371115e1c78ff648993bf19abd0/multidict-6.6.3-cp39-cp39-musllinux_1_2_armv7l.whl",hashes = {sha256 = "61af8a4b771f1d4d000b3168c12c3120ccf7284502a94aa58c68a81f5afac090"}}, - {name = "multidict-6.6.3-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/85/e1/68a65f069df298615591e70e48bfd379c27d4ecb252117c18bf52eebc237/multidict-6.6.3-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "448e4a9afccbf297577f2eaa586f07067441e7b63c8362a3540ba5a38dc0f14a"}}, - {name = "multidict-6.6.3-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/ae/ab/702f1baca649f88ea1dc6259fc2aa4509f4ad160ba48c8e61fbdb4a5a365/multidict-6.6.3-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "233ad16999afc2bbd3e534ad8dbe685ef8ee49a37dbc2cdc9514e57b6d589ced"}}, - {name = "multidict-6.6.3-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/5e/0b/726e690bfbf887985a8710ef2f25f1d6dd184a35bd3b36429814f810a2fc/multidict-6.6.3-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "bb933c891cd4da6bdcc9733d048e994e22e1883287ff7540c2a0f3b117605092"}}, - {name = "multidict-6.6.3-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/bb/839486b27bcbcc2e0d875fb9d4012b4b6aa99639137343106aa7210e047a/multidict-6.6.3-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "37b09ca60998e87734699e88c2363abfd457ed18cfbf88e4009a4e83788e63ed"}}, - {name = "multidict-6.6.3-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/e3/46/574d75ab7b9ae8690fe27e89f5fcd0121633112b438edfb9ed2be8be096b/multidict-6.6.3-cp39-cp39-win32.whl",hashes = {sha256 = "f54cb79d26d0cd420637d184af38f0668558f3c4bbe22ab7ad830e67249f2e0b"}}, - {name = "multidict-6.6.3-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/78/c3/8b3bc755508b777868349f4bfa844d3d31832f075ee800a3d6f1807338c5/multidict-6.6.3-cp39-cp39-win_amd64.whl",hashes = {sha256 = "295adc9c0551e5d5214b45cf29ca23dbc28c2d197a9c30d51aed9e037cb7c578"}}, - {name = "multidict-6.6.3-cp39-cp39-win_arm64.whl",url = "https://files.pythonhosted.org/packages/b2/30/5a66e7e4550e80975faee5b5dd9e9bd09194d2fd8f62363119b9e46e204b/multidict-6.6.3-cp39-cp39-win_arm64.whl",hashes = {sha256 = "15332783596f227db50fb261c2c251a58ac3873c457f3a550a95d5c0aa3c770d"}}, -] -marker = "\"default\" in dependency_groups or \"dev\" in extras" - -[packages.tool.pdm] -dependencies = [ - "typing-extensions>=4.1.0; python_version < \"3.11\"", -] - [[packages]] name = "regex" version = "2024.11.6" @@ -1823,53 +1592,6 @@ wheels = [ {name = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/93/2d/dd56bb76bd8e95bbce684326302f287455b56242a4f9c61f1bc76e28360e/regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}}, {name = "regex-2024.11.6-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/0b/55/31877a249ab7a5156758246b9c59539abbeba22461b7d8adc9e8475ff73e/regex-2024.11.6-cp312-cp312-win32.whl",hashes = {sha256 = "32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}}, {name = "regex-2024.11.6-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/38/ec/ad2d7de49a600cdb8dd78434a1aeffe28b9d6fc42eb36afab4a27ad23384/regex-2024.11.6-cp312-cp312-win_amd64.whl",hashes = {sha256 = "a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}}, - {name = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/58/58/7e4d9493a66c88a7da6d205768119f51af0f684fe7be7bac8328e217a52c/regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}}, - {name = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/34/4c/8f8e631fcdc2ff978609eaeef1d6994bf2f028b59d9ac67640ed051f1218/regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}}, - {name = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c5/1b/f0e4d13e6adf866ce9b069e191f303a30ab1277e037037a365c3aad5cc9c/regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}}, - {name = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/25/4d/ab21047f446693887f25510887e6820b93f791992994f6498b0318904d4a/regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}}, - {name = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/45/ee/c867e15cd894985cb32b731d89576c41a4642a57850c162490ea34b78c3b/regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}}, - {name = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/b3/12/b0f480726cf1c60f6536fa5e1c95275a77624f3ac8fdccf79e6727499e28/regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}}, - {name = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/bf/ce/0d0e61429f603bac433910d99ef1a02ce45a8967ffbe3cbee48599e62d88/regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}}, - {name = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/e4/c1/243c83c53d4a419c1556f43777ccb552bccdf79d08fda3980e4e77dd9137/regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}}, - {name = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c5/f4/75eb0dd4ce4b37f04928987f1d22547ddaf6c4bae697623c1b05da67a8aa/regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}}, - {name = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/16/5d/95c568574e630e141a69ff8a254c2f188b4398e813c40d49228c9bbd9875/regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}}, - {name = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/8e/b5/f8495c7917f15cc6fee1e7f395e324ec3e00ab3c665a7dc9d27562fd5290/regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}}, - {name = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/1c/80/6dd7118e8cb212c3c60b191b932dc57db93fb2e36fb9e0e92f72a5909af9/regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}}, - {name = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/11/9b/5a05d2040297d2d254baf95eeeb6df83554e5e1df03bc1a6687fc4ba1f66/regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}}, - {name = "regex-2024.11.6-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/26/b7/b14e2440156ab39e0177506c08c18accaf2b8932e39fb092074de733d868/regex-2024.11.6-cp311-cp311-win32.whl",hashes = {sha256 = "c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}}, - {name = "regex-2024.11.6-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/80/32/763a6cc01d21fb3819227a1cc3f60fd251c13c37c27a73b8ff4315433a8e/regex-2024.11.6-cp311-cp311-win_amd64.whl",hashes = {sha256 = "02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}}, - {name = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/95/3c/4651f6b130c6842a8f3df82461a8950f923925db8b6961063e82744bddcc/regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}}, - {name = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/15/51/9f35d12da8434b489c7b7bffc205c474a0a9432a889457026e9bc06a297a/regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}}, - {name = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/bd/18/b731f5510d1b8fb63c6b6d3484bfa9a59b84cc578ac8b5172970e05ae07c/regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}}, - {name = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/78/a2/6dd36e16341ab95e4c6073426561b9bfdeb1a9c9b63ab1b579c2e96cb105/regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}}, - {name = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/1b/2b/323e72d5d2fd8de0d9baa443e1ed70363ed7e7b2fb526f5950c5cb99c364/regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}}, - {name = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/90/30/63373b9ea468fbef8a907fd273e5c329b8c9535fee36fc8dba5fecac475d/regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}}, - {name = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/f2/98/26d3830875b53071f1f0ae6d547f1d98e964dd29ad35cbf94439120bb67a/regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}}, - {name = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/87/55/eb2a068334274db86208ab9d5599ffa63631b9f0f67ed70ea7c82a69bbc8/regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}}, - {name = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",url = "https://files.pythonhosted.org/packages/74/c0/be707bcfe98254d8f9d2cff55d216e946f4ea48ad2fd8cf1428f8c5332ba/regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",hashes = {sha256 = "f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}}, - {name = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/49/dc/bb45572ceb49e0f6509f7596e4ba7031f6819ecb26bc7610979af5a77f45/regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}}, - {name = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/5a/db/f43fd75dc4c0c2d96d0881967897926942e935d700863666f3c844a72ce6/regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}}, - {name = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/99/d7/f94154db29ab5a89d69ff893159b19ada89e76b915c1293e98603d39838c/regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}}, - {name = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/f7/17/3cbfab1f23356fbbf07708220ab438a7efa1e0f34195bf857433f79f1788/regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}}, - {name = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/7e/f2/48b393b51900456155de3ad001900f94298965e1cad1c772b87f9cfea011/regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}}, - {name = "regex-2024.11.6-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/45/3f/ef9589aba93e084cd3f8471fded352826dcae8489b650d0b9b27bc5bba8a/regex-2024.11.6-cp310-cp310-win32.whl",hashes = {sha256 = "b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}}, - {name = "regex-2024.11.6-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/42/7e/5f1b92c8468290c465fd50c5318da64319133231415a8aa6ea5ab995a815/regex-2024.11.6-cp310-cp310-win_amd64.whl",hashes = {sha256 = "5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}}, - {name = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/89/23/c4a86df398e57e26f93b13ae63acce58771e04bdde86092502496fa57f9c/regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}}, - {name = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/8b/45c24ab7a51a1658441b961b86209c43e6bb9d39caf1e63f46ce6ea03bc7/regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}}, - {name = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7a/d1/598de10b17fdafc452d11f7dada11c3be4e379a8671393e4e3da3c4070df/regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}}, - {name = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/49/70/c7eaa219efa67a215846766fde18d92d54cb590b6a04ffe43cef30057622/regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}}, - {name = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/89/e5/ef52c7eb117dd20ff1697968219971d052138965a4d3d9b95e92e549f505/regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}}, - {name = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/5f/3f/9f5da81aff1d4167ac52711acf789df13e789fe6ac9545552e49138e3282/regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}}, - {name = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/86/44/2101cc0890c3621b90365c9ee8d7291a597c0722ad66eccd6ffa7f1bcc09/regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}}, - {name = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/ce/2e/3e0668d8d1c7c3c0d397bf54d92fc182575b3a26939aed5000d3cc78760f/regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}}, - {name = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",url = "https://files.pythonhosted.org/packages/a6/49/1bc4584254355e3dba930a3a2fd7ad26ccba3ebbab7d9100db0aff2eedb0/regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl",hashes = {sha256 = "764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}}, - {name = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c8/dd/42879c1fc8a37a887cd08e358af3d3ba9e23038cd77c7fe044a86d9450ba/regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}}, - {name = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/89/96/c05a0fe173cd2acd29d5e13c1adad8b706bcaa71b169e1ee57dcf2e74584/regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}}, - {name = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b5/f3/a757748066255f97f14506483436c5f6aded7af9e37bca04ec30c90ca683/regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}}, - {name = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/5c/93/c6d2092fd479dcaeea40fc8fa673822829181ded77d294a7f950f1dda6e2/regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}}, - {name = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/ff/9c/daa99532c72f25051a90ef90e1413a8d54413a9e64614d9095b0c1c154d0/regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}}, - {name = "regex-2024.11.6-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/13/5d/61a533ccb8c231b474ac8e3a7d70155b00dfc61af6cafdccd1947df6d735/regex-2024.11.6-cp39-cp39-win32.whl",hashes = {sha256 = "41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}}, - {name = "regex-2024.11.6-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/dc/7b/e59b7f7c91ae110d154370c24133f947262525b5d6406df65f23422acc17/regex-2024.11.6-cp39-cp39-win_amd64.whl",hashes = {sha256 = "b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}}, ] marker = "\"default\" in dependency_groups or \"recommended\" in extras" @@ -1945,7 +1667,7 @@ sdist = {name = "platformdirs-4.3.8.tar.gz", url = "https://files.pythonhosted.o wheels = [ {name = "platformdirs-4.3.8-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl",hashes = {sha256 = "ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}}, ] -marker = "\"dev\" in extras" +marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [] @@ -2019,58 +1741,7 @@ wheels = [ {name = "yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/af/85/9363f77bdfa1e4d690957cd39d192c4cacd1c58965df0470a4905253b54f/yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004"}}, {name = "yarl-1.20.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/35/99/9918c8739ba271dcd935400cff8b32e3cd319eaf02fcd023d5dcd487a7c8/yarl-1.20.1-cp312-cp312-win32.whl",hashes = {sha256 = "daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5"}}, {name = "yarl-1.20.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/eb/83/5d9092950565481b413b31a23e75dd3418ff0a277d6e0abf3729d4d1ce25/yarl-1.20.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698"}}, - {name = "yarl-1.20.1-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/b1/18/893b50efc2350e47a874c5c2d67e55a0ea5df91186b2a6f5ac52eff887cd/yarl-1.20.1-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "47ee6188fea634bdfaeb2cc420f5b3b17332e6225ce88149a17c413c77ff269e"}}, - {name = "yarl-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/89/ed/b8773448030e6fc47fa797f099ab9eab151a43a25717f9ac043844ad5ea3/yarl-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "d0f6500f69e8402d513e5eedb77a4e1818691e8f45e6b687147963514d84b44b"}}, - {name = "yarl-1.20.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e3/e3/409bd17b1e42619bf69f60e4f031ce1ccb29bd7380117a55529e76933464/yarl-1.20.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "7a8900a42fcdaad568de58887c7b2f602962356908eedb7628eaf6021a6e435b"}}, - {name = "yarl-1.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f8/77/64d8431a4d77c856eb2d82aa3de2ad6741365245a29b3a9543cd598ed8c5/yarl-1.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "bad6d131fda8ef508b36be3ece16d0902e80b88ea7200f030a0f6c11d9e508d4"}}, - {name = "yarl-1.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/8d/d2/0c7e4def093dcef0bd9fa22d4d24b023788b0a33b8d0088b51aa51e21e99/yarl-1.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "df018d92fe22aaebb679a7f89fe0c0f368ec497e3dda6cb81a567610f04501f1"}}, - {name = "yarl-1.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f0/f3/fc514f4b2cf02cb59d10cbfe228691d25929ce8f72a38db07d3febc3f706/yarl-1.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "8f969afbb0a9b63c18d0feecf0db09d164b7a44a053e78a7d05f5df163e43833"}}, - {name = "yarl-1.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/ea/6d/a313ac8d8391381ff9006ac05f1d4331cee3b1efaa833a53d12253733255/yarl-1.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "812303eb4aa98e302886ccda58d6b099e3576b1b9276161469c25803a8db277d"}}, - {name = "yarl-1.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/00/70/8f78a95d6935a70263d46caa3dd18e1f223cf2f2ff2037baa01a22bc5b22/yarl-1.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "98c4a7d166635147924aa0bf9bfe8d8abad6fffa6102de9c99ea04a1376f91e8"}}, - {name = "yarl-1.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/cb/05/42773027968968f4f15143553970ee36ead27038d627f457cc44bbbeecf3/yarl-1.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "12e768f966538e81e6e7550f9086a6236b16e26cd964cf4df35349970f3551cf"}}, - {name = "yarl-1.20.1-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/05/be/665634aa196954156741ea591d2f946f1b78ceee8bb8f28488bf28c0dd62/yarl-1.20.1-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "fe41919b9d899661c5c28a8b4b0acf704510b88f27f0934ac7a7bebdd8938d5e"}}, - {name = "yarl-1.20.1-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/eb/90/73448401d36fa4e210ece5579895731f190d5119c4b66b43b52182e88cd5/yarl-1.20.1-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "8601bc010d1d7780592f3fc1bdc6c72e2b6466ea34569778422943e1a1f3c389"}}, - {name = "yarl-1.20.1-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/c3/b0/fce922d46dc1eb43c811f1889f7daa6001b27a4005587e94878570300881/yarl-1.20.1-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "daadbdc1f2a9033a2399c42646fbd46da7992e868a5fe9513860122d7fe7a73f"}}, - {name = "yarl-1.20.1-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f1/0d/b172628fce039dae8977fd22caeff3eeebffd52e86060413f5673767c427/yarl-1.20.1-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "03aa1e041727cb438ca762628109ef1333498b122e4c76dd858d186a37cec845"}}, - {name = "yarl-1.20.1-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/6b/9b/5b886d7671f4580209e855974fe1cecec409aa4a89ea58b8f0560dc529b1/yarl-1.20.1-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "642980ef5e0fa1de5fa96d905c7e00cb2c47cb468bfcac5a18c58e27dbf8d8d1"}}, - {name = "yarl-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/be/75ef5fd0fcd8f083a5d13f78fd3f009528132a1f2a1d7c925c39fa20aa79/yarl-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "86971e2795584fe8c002356d3b97ef6c61862720eeff03db2a7c86b678d85b3e"}}, - {name = "yarl-1.20.1-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/50/4f/62faab3b479dfdcb741fe9e3f0323e2a7d5cd1ab2edc73221d57ad4834b2/yarl-1.20.1-cp311-cp311-win32.whl",hashes = {sha256 = "597f40615b8d25812f14562699e287f0dcc035d25eb74da72cae043bb884d773"}}, - {name = "yarl-1.20.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f0/09/d9c7942f8f05c32ec72cd5c8e041c8b29b5807328b68b4801ff2511d4d5e/yarl-1.20.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "26ef53a9e726e61e9cd1cda6b478f17e350fb5800b4bd1cd9fe81c4d91cfeb2e"}}, - {name = "yarl-1.20.1-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/cb/65/7fed0d774abf47487c64be14e9223749468922817b5e8792b8a64792a1bb/yarl-1.20.1-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "6032e6da6abd41e4acda34d75a816012717000fa6839f37124a47fcefc49bec4"}}, - {name = "yarl-1.20.1-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/7b/988f55a52da99df9e56dc733b8e4e5a6ae2090081dc2754fc8fd34e60aa0/yarl-1.20.1-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "2c7b34d804b8cf9b214f05015c4fee2ebe7ed05cf581e7192c06555c71f4446a"}}, - {name = "yarl-1.20.1-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f7/de/30d98f03e95d30c7e3cc093759982d038c8833ec2451001d45ef4854edc1/yarl-1.20.1-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "0c869f2651cc77465f6cd01d938d91a11d9ea5d798738c1dc077f3de0b5e5fed"}}, - {name = "yarl-1.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/e0/7a/f2f314f5ebfe9200724b0b748de2186b927acb334cf964fd312eb86fc286/yarl-1.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "62915e6688eb4d180d93840cda4110995ad50c459bf931b8b3775b37c264af1e"}}, - {name = "yarl-1.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/15/3f/718d26f189db96d993d14b984ce91de52e76309d0fd1d4296f34039856aa/yarl-1.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "41ebd28167bc6af8abb97fec1a399f412eec5fd61a3ccbe2305a18b84fb4ca73"}}, - {name = "yarl-1.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/a5/76/8fcfbf5fa2369157b9898962a4a7d96764b287b085b5b3d9ffae69cdefd1/yarl-1.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "21242b4288a6d56f04ea193adde174b7e347ac46ce6bc84989ff7c1b1ecea84e"}}, - {name = "yarl-1.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/3c/95/d7fc301cc4661785967acc04f54a4a42d5124905e27db27bb578aac49b5c/yarl-1.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "bea21cdae6c7eb02ba02a475f37463abfe0a01f5d7200121b03e605d6a0439f8"}}, - {name = "yarl-1.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/65/94/e21269718349582eee81efc5c1c08ee71c816bfc1585b77d0ec3f58089eb/yarl-1.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "1f8a891e4a22a89f5dde7862994485e19db246b70bb288d3ce73a34422e55b23"}}, - {name = "yarl-1.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/32/ae/8616d1f07853704523519f6131d21f092e567c5af93de7e3e94b38d7f065/yarl-1.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "dd803820d44c8853a109a34e3660e5a61beae12970da479cf44aa2954019bf70"}}, - {name = "yarl-1.20.1-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/48/aa/0ace06280861ef055855333707db5e49c6e3a08840a7ce62682259d0a6c0/yarl-1.20.1-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "b982fa7f74c80d5c0c7b5b38f908971e513380a10fecea528091405f519b9ebb"}}, - {name = "yarl-1.20.1-cp310-cp310-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/20/52/1e9d0e6916f45a8fb50e6844f01cb34692455f1acd548606cbda8134cd1e/yarl-1.20.1-cp310-cp310-musllinux_1_2_armv7l.whl",hashes = {sha256 = "33f29ecfe0330c570d997bcf1afd304377f2e48f61447f37e846a6058a4d33b2"}}, - {name = "yarl-1.20.1-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/f2/65/60452df742952c630e82f394cd409de10610481d9043aa14c61bf846b7b1/yarl-1.20.1-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "835ab2cfc74d5eb4a6a528c57f05688099da41cf4957cf08cad38647e4a83b30"}}, - {name = "yarl-1.20.1-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/7b/f5/6cd4ff38dcde57a70f23719a838665ee17079640c77087404c3d34da6727/yarl-1.20.1-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "46b5e0ccf1943a9a6e766b2c2b8c732c55b34e28be57d8daa2b3c1d1d4009309"}}, - {name = "yarl-1.20.1-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/d1/90/c42eefd79d0d8222cb3227bdd51b640c0c1d0aa33fe4cc86c36eccba77d3/yarl-1.20.1-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "df47c55f7d74127d1b11251fe6397d84afdde0d53b90bedb46a23c0e534f9d24"}}, - {name = "yarl-1.20.1-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/03/c8/cea6b232cb4617514232e0f8a718153a95b5d82b5290711b201545825532/yarl-1.20.1-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "76d12524d05841276b0e22573f28d5fbcb67589836772ae9244d90dd7d66aa13"}}, - {name = "yarl-1.20.1-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/ce/a3/eaa0ab9712f1f3d01faf43cf6f1f7210ce4ea4a7e9b28b489a2261ca8db9/yarl-1.20.1-cp310-cp310-win32.whl",hashes = {sha256 = "6c4fbf6b02d70e512d7ade4b1f998f237137f1417ab07ec06358ea04f69134f8"}}, - {name = "yarl-1.20.1-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8f/34/e4abde70a9256465fe31c88ed02c3f8502b7b5dead693a4f350a06413f28/yarl-1.20.1-cp310-cp310-win_amd64.whl",hashes = {sha256 = "aef6c4d69554d44b7f9d923245f8ad9a707d971e6209d51279196d8e8fe1ae16"}}, {name = "yarl-1.20.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/b4/2d/2345fce04cfd4bee161bf1e7d9cdc702e3e16109021035dbb24db654a622/yarl-1.20.1-py3-none-any.whl",hashes = {sha256 = "83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77"}}, - {name = "yarl-1.20.1-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/01/75/0d37402d208d025afa6b5b8eb80e466d267d3fd1927db8e317d29a94a4cb/yarl-1.20.1-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "e42ba79e2efb6845ebab49c7bf20306c4edf74a0b20fc6b2ccdd1a219d12fad3"}}, - {name = "yarl-1.20.1-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/84/1fb6c85ae0cf9901046f07d0ac9eb162f7ce6d95db541130aa542ed377e6/yarl-1.20.1-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "41493b9b7c312ac448b7f0a42a089dffe1d6e6e981a2d76205801a023ed26a2b"}}, - {name = "yarl-1.20.1-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f3/9c/eae746b24c4ea29a5accba9a06c197a70fa38a49c7df244e0d3951108861/yarl-1.20.1-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "f5a5928ff5eb13408c62a968ac90d43f8322fd56d87008b8f9dabf3c0f6ee983"}}, - {name = "yarl-1.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/fb/30/693e71003ec4bc1daf2e4cf7c478c417d0985e0a8e8f00b2230d517876fc/yarl-1.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "30c41ad5d717b3961b2dd785593b67d386b73feca30522048d37298fee981805"}}, - {name = "yarl-1.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/0f/a2/5264dbebf90763139aeb0b0b3154763239398400f754ae19a0518b654117/yarl-1.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "59febc3969b0781682b469d4aca1a5cab7505a4f7b85acf6db01fa500fa3f6ba"}}, - {name = "yarl-1.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e7/17/77c7a89b3c05856489777e922f41db79ab4faf58621886df40d812c7facd/yarl-1.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "d2b6fb3622b7e5bf7a6e5b679a69326b4279e805ed1699d749739a61d242449e"}}, - {name = "yarl-1.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/6d/55/28409330b8ef5f2f681f5b478150496ec9cf3309b149dab7ec8ab5cfa3f0/yarl-1.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "749d73611db8d26a6281086f859ea7ec08f9c4c56cec864e52028c8b328db723"}}, - {name = "yarl-1.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/85/58/cb0257cbd4002828ff735f44d3c5b6966c4fd1fc8cc1cd3cd8a143fbc513/yarl-1.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9427925776096e664c39e131447aa20ec738bdd77c049c48ea5200db2237e000"}}, - {name = "yarl-1.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/53/f6/c77960370cfa46f6fb3d6a5a79a49d3abfdb9ef92556badc2dcd2748bc2a/yarl-1.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "ff70f32aa316393eaf8222d518ce9118148eddb8a53073c2403863b41033eed5"}}, - {name = "yarl-1.20.1-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/64/ab/be0b10b8e029553c10905b6b00c64ecad3ebc8ace44b02293a62579343f6/yarl-1.20.1-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c7ddf7a09f38667aea38801da8b8d6bfe81df767d9dfc8c88eb45827b195cd1c"}}, - {name = "yarl-1.20.1-cp39-cp39-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/c5/c3/3f327bd3905a4916029bf5feb7f86dcf864c7704f099715f62155fb386b2/yarl-1.20.1-cp39-cp39-musllinux_1_2_armv7l.whl",hashes = {sha256 = "57edc88517d7fc62b174fcfb2e939fbc486a68315d648d7e74d07fac42cec240"}}, - {name = "yarl-1.20.1-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/d1/42/040bdd5d3b3bb02b4a6ace4ed4075e02f85df964d6e6cb321795d2a6496a/yarl-1.20.1-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "dab096ce479d5894d62c26ff4f699ec9072269d514b4edd630a393223f45a0ee"}}, - {name = "yarl-1.20.1-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/0d/1c/911867b8e8c7463b84dfdc275e0d99b04b66ad5132b503f184fe76be8ea4/yarl-1.20.1-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "14a85f3bd2d7bb255be7183e5d7d6e70add151a98edf56a770d6140f5d5f4010"}}, - {name = "yarl-1.20.1-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/e2/31/8c389f6c6ca0379b57b2da87f1f126c834777b4931c5ee8427dd65d0ff6b/yarl-1.20.1-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "2c89b5c792685dd9cd3fa9761c1b9f46fc240c2a3265483acc1565769996a3f8"}}, - {name = "yarl-1.20.1-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/7f/09/ae4a649fb3964324c70a3e2b61f45e566d9ffc0affd2b974cbf628957673/yarl-1.20.1-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "69e9b141de5511021942a6866990aea6d111c9042235de90e08f94cf972ca03d"}}, - {name = "yarl-1.20.1-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/8d/43/bbb4ed4c34d5bb62b48bf957f68cd43f736f79059d4f85225ab1ef80f4b9/yarl-1.20.1-cp39-cp39-win32.whl",hashes = {sha256 = "b5f307337819cdfdbb40193cad84978a029f847b0a357fbe49f712063cfc4f06"}}, - {name = "yarl-1.20.1-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d7/cd/ce185848a7dba68ea69e932674b5c1a42a1852123584bccc5443120f857c/yarl-1.20.1-cp39-cp39-win_amd64.whl",hashes = {sha256 = "eae7bfe2069f9c1c5b05fc7fe5d612e5bbc089a39309904ee8b829e322dcad00"}}, ] marker = "\"default\" in dependency_groups or \"dev\" in extras" @@ -2135,61 +1806,26 @@ wheels = [ {name = "propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/a4/7c/3f539fcae630408d0bd8bf3208b9a647ccad10976eda62402a80adf8fc34/propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1"}}, {name = "propcache-0.3.2-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/7c/d2/34b9eac8c35f79f8a962546b3e97e9d4b990c420ee66ac8255d5d9611648/propcache-0.3.2-cp312-cp312-win32.whl",hashes = {sha256 = "df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1"}}, {name = "propcache-0.3.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/19/61/d582be5d226cf79071681d1b46b848d6cb03d7b70af7063e33a2787eaa03/propcache-0.3.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c"}}, - {name = "propcache-0.3.2-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/80/8d/e8b436717ab9c2cfc23b116d2c297305aa4cd8339172a456d61ebf5669b8/propcache-0.3.2-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "0b8d2f607bd8f80ddc04088bc2a037fdd17884a6fcadc47a96e334d72f3717be"}}, - {name = "propcache-0.3.2-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/d6/29/1e34000e9766d112171764b9fa3226fa0153ab565d0c242c70e9945318a7/propcache-0.3.2-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "06766d8f34733416e2e34f46fea488ad5d60726bb9481d3cddf89a6fa2d9603f"}}, - {name = "propcache-0.3.2-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/46/92/1ad5af0df781e76988897da39b5f086c2bf0f028b7f9bd1f409bb05b6874/propcache-0.3.2-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "a2dc1f4a1df4fecf4e6f68013575ff4af84ef6f478fe5344317a65d38a8e6dc9"}}, - {name = "propcache-0.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b3/ce/e96392460f9fb68461fabab3e095cb00c8ddf901205be4eae5ce246e5b7e/propcache-0.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "be29c4f4810c5789cf10ddf6af80b041c724e629fa51e308a7a0fb19ed1ef7bf"}}, - {name = "propcache-0.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c5/2a/866726ea345299f7ceefc861a5e782b045545ae6940851930a6adaf1fca6/propcache-0.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "59d61f6970ecbd8ff2e9360304d5c8876a6abd4530cb752c06586849ac8a9dc9"}}, - {name = "propcache-0.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/de/03/07d992ccb6d930398689187e1b3c718339a1c06b8b145a8d9650e4726166/propcache-0.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "62180e0b8dbb6b004baec00a7983e4cc52f5ada9cd11f48c3528d8cfa7b96a66"}}, - {name = "propcache-0.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/5d/e6/116ba39448753b1330f48ab8ba927dcd6cf0baea8a0ccbc512dfb49ba670/propcache-0.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c144ca294a204c470f18cf4c9d78887810d04a3e2fbb30eea903575a779159df"}}, - {name = "propcache-0.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/a6/85/f01f5d97e54e428885a5497ccf7f54404cbb4f906688a1690cd51bf597dc/propcache-0.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "c5c2a784234c28854878d68978265617aa6dc0780e53d44b4d67f3651a17a9a2"}}, - {name = "propcache-0.3.2-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/e3/79/7bf5ab9033b8b8194cc3f7cf1aaa0e9c3256320726f64a3e1f113a812dce/propcache-0.3.2-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "5745bc7acdafa978ca1642891b82c19238eadc78ba2aaa293c6863b304e552d7"}}, - {name = "propcache-0.3.2-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/31/0b/bd3e0c00509b609317df4a18e6b05a450ef2d9a963e1d8bc9c9415d86f30/propcache-0.3.2-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "c0075bf773d66fa8c9d41f66cc132ecc75e5bb9dd7cce3cfd14adc5ca184cb95"}}, - {name = "propcache-0.3.2-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/7a/23/fae0ff9b54b0de4e819bbe559508da132d5683c32d84d0dc2ccce3563ed4/propcache-0.3.2-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "5f57aa0847730daceff0497f417c9de353c575d8da3579162cc74ac294c5369e"}}, - {name = "propcache-0.3.2-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b7/7f/ad6a3c22630aaa5f618b4dc3c3598974a72abb4c18e45a50b3cdd091eb2f/propcache-0.3.2-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "eef914c014bf72d18efb55619447e0aecd5fb7c2e3fa7441e2e5d6099bddff7e"}}, - {name = "propcache-0.3.2-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/5b/2c/ba4f1c0e8a4b4c75910742f0d333759d441f65a1c7f34683b4a74c0ee015/propcache-0.3.2-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "2a4092e8549031e82facf3decdbc0883755d5bbcc62d3aea9d9e185549936dcf"}}, - {name = "propcache-0.3.2-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/88/e4/ebe30fc399e98572019eee82ad0caf512401661985cbd3da5e3140ffa1b0/propcache-0.3.2-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "85871b050f174bc0bfb437efbdb68aaf860611953ed12418e4361bc9c392749e"}}, - {name = "propcache-0.3.2-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/96/0a/7d5260b914e01d1d0906f7f38af101f8d8ed0dc47426219eeaf05e8ea7c2/propcache-0.3.2-cp311-cp311-win32.whl",hashes = {sha256 = "36c8d9b673ec57900c3554264e630d45980fd302458e4ac801802a7fd2ef7897"}}, - {name = "propcache-0.3.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/e1/2d/89fe4489a884bc0da0c3278c552bd4ffe06a1ace559db5ef02ef24ab446b/propcache-0.3.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "e53af8cb6a781b02d2ea079b5b853ba9430fcbe18a8e3ce647d5982a3ff69f39"}}, - {name = "propcache-0.3.2-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/ab/14/510deed325e262afeb8b360043c5d7c960da7d3ecd6d6f9496c9c56dc7f4/propcache-0.3.2-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "22d9962a358aedbb7a2e36187ff273adeaab9743373a272976d2e348d08c7770"}}, - {name = "propcache-0.3.2-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/cd/4e/ad52a7925ff01c1325653a730c7ec3175a23f948f08626a534133427dcff/propcache-0.3.2-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "0d0fda578d1dc3f77b6b5a5dce3b9ad69a8250a891760a548df850a5e8da87f3"}}, - {name = "propcache-0.3.2-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/63/7c/e9399ba5da7780871db4eac178e9c2e204c23dd3e7d32df202092a1ed400/propcache-0.3.2-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "3def3da3ac3ce41562d85db655d18ebac740cb3fa4367f11a52b3da9d03a5cc3"}}, - {name = "propcache-0.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/22/e1/58da211eb8fdc6fc854002387d38f415a6ca5f5c67c1315b204a5d3e9d7a/propcache-0.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "9bec58347a5a6cebf239daba9bda37dffec5b8d2ce004d9fe4edef3d2815137e"}}, - {name = "propcache-0.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c4/0a/550ea0f52aac455cb90111c8bab995208443e46d925e51e2f6ebdf869525/propcache-0.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "55ffda449a507e9fbd4aca1a7d9aa6753b07d6166140e5a18d2ac9bc49eac220"}}, - {name = "propcache-0.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/5a/af/9893b7d878deda9bb69fcf54600b247fba7317761b7db11fede6e0f28bd0/propcache-0.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "64a67fb39229a8a8491dd42f864e5e263155e729c2e7ff723d6e25f596b1e8cb"}}, - {name = "propcache-0.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/7c/bb/38fd08b278ca85cde36d848091ad2b45954bc5f15cce494bb300b9285831/propcache-0.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "9da1cf97b92b51253d5b68cf5a2b9e0dafca095e36b7f2da335e27dc6172a614"}}, - {name = "propcache-0.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/78/8c/9fe55bd01d362bafb413dfe508c48753111a1e269737fa143ba85693592c/propcache-0.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "5f559e127134b07425134b4065be45b166183fdcb433cb6c24c8e4149056ad50"}}, - {name = "propcache-0.3.2-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/54/14/4701c33852937a22584e08abb531d654c8bcf7948a8f87ad0a4822394147/propcache-0.3.2-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "aff2e4e06435d61f11a428360a932138d0ec288b0a31dd9bd78d200bd4a2b339"}}, - {name = "propcache-0.3.2-cp310-cp310-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/16/44/447f2253d859602095356007657ee535e0093215ea0b3d1d6a41d16e5201/propcache-0.3.2-cp310-cp310-musllinux_1_2_armv7l.whl",hashes = {sha256 = "4927842833830942a5d0a56e6f4839bc484785b8e1ce8d287359794818633ba0"}}, - {name = "propcache-0.3.2-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/f2/b3/e4756258749bb2d3b46defcff606a2f47410bab82be5824a67e84015b267/propcache-0.3.2-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "6107ddd08b02654a30fb8ad7a132021759d750a82578b94cd55ee2772b6ebea2"}}, - {name = "propcache-0.3.2-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/1e/df/e6d3c7574233164b6330b9fd697beeac402afd367280e6dc377bb99b43d9/propcache-0.3.2-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "70bd8b9cd6b519e12859c99f3fc9a93f375ebd22a50296c3a295028bea73b9e7"}}, - {name = "propcache-0.3.2-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/b2/53/e4d31dd5170b4a0e2e6b730f2385a96410633b4833dc25fe5dffd1f73294/propcache-0.3.2-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "2183111651d710d3097338dd1893fcf09c9f54e27ff1a8795495a16a469cc90b"}}, - {name = "propcache-0.3.2-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/7f/fe/74d54cf9fbe2a20ff786e5f7afcfde446588f0cf15fb2daacfbc267b866c/propcache-0.3.2-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "fb075ad271405dcad8e2a7ffc9a750a3bf70e533bd86e89f0603e607b93aa64c"}}, - {name = "propcache-0.3.2-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/22/ec/c469c9d59dada8a7679625e0440b544fe72e99311a4679c279562051f6fc/propcache-0.3.2-cp310-cp310-win32.whl",hashes = {sha256 = "404d70768080d3d3bdb41d0771037da19d8340d50b08e104ca0e7f9ce55fce70"}}, - {name = "propcache-0.3.2-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/38/35/07a471371ac89d418f8d0b699c75ea6dca2041fbda360823de21f6a9ce0a/propcache-0.3.2-cp310-cp310-win_amd64.whl",hashes = {sha256 = "7435d766f978b4ede777002e6b3b6641dd229cd1da8d3d3106a45770365f9ad9"}}, {name = "propcache-0.3.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl",hashes = {sha256 = "98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f"}}, - {name = "propcache-0.3.2-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/6c/39/8ea9bcfaaff16fd0b0fc901ee522e24c9ec44b4ca0229cfffb8066a06959/propcache-0.3.2-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "a7fad897f14d92086d6b03fdd2eb844777b0c4d7ec5e3bac0fbae2ab0602bbe5"}}, - {name = "propcache-0.3.2-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/d3/85/cab84c86966e1d354cf90cdc4ba52f32f99a5bca92a1529d666d957d7686/propcache-0.3.2-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "1f43837d4ca000243fd7fd6301947d7cb93360d03cd08369969450cc6b2ce3b4"}}, - {name = "propcache-0.3.2-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/23/f7/9cb719749152d8b26d63801b3220ce2d3931312b2744d2b3a088b0ee9947/propcache-0.3.2-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "261df2e9474a5949c46e962065d88eb9b96ce0f2bd30e9d3136bcde84befd8f2"}}, - {name = "propcache-0.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a2/a2/0b2b5a210ff311260002a315f6f9531b65a36064dfb804655432b2f7d3e3/propcache-0.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e514326b79e51f0a177daab1052bc164d9d9e54133797a3a58d24c9c87a3fe6d"}}, - {name = "propcache-0.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/3f/e0/7aff5de0c535f783b0c8be5bdb750c305c1961d69fbb136939926e155d98/propcache-0.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "d4a996adb6904f85894570301939afeee65f072b4fd265ed7e569e8d9058e4ec"}}, - {name = "propcache-0.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/92/1d/65fa889eb3b2a7d6e4ed3c2b568a9cb8817547a1450b572de7bf24872800/propcache-0.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "76cace5d6b2a54e55b137669b30f31aa15977eeed390c7cbfb1dafa8dfe9a701"}}, - {name = "propcache-0.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/9a/e2/eecf6989870988dfd731de408a6fa366e853d361a06c2133b5878ce821ad/propcache-0.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "31248e44b81d59d6addbb182c4720f90b44e1efdc19f58112a3c3a1615fb47ef"}}, - {name = "propcache-0.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/12/06/c32be4950967f18f77489268488c7cdc78cbfc65a8ba8101b15e526b83dc/propcache-0.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "abb7fa19dbf88d3857363e0493b999b8011eea856b846305d8c0512dfdf8fbb1"}}, - {name = "propcache-0.3.2-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/46/6c/17b521a6b3b7cbe277a4064ff0aa9129dd8c89f425a5a9b6b4dd51cc3ff4/propcache-0.3.2-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d81ac3ae39d38588ad0549e321e6f773a4e7cc68e7751524a22885d5bbadf886"}}, - {name = "propcache-0.3.2-cp39-cp39-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/62/cb/3bdba2b736b3e45bc0e40f4370f745b3e711d439ffbffe3ae416393eece9/propcache-0.3.2-cp39-cp39-musllinux_1_2_armv7l.whl",hashes = {sha256 = "cc2782eb0f7a16462285b6f8394bbbd0e1ee5f928034e941ffc444012224171b"}}, - {name = "propcache-0.3.2-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/29/bd/760c5c6a60a4a2c55a421bc34a25ba3919d49dee411ddb9d1493bb51d46e/propcache-0.3.2-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "db429c19a6c7e8a1c320e6a13c99799450f411b02251fb1b75e6217cf4a14fcb"}}, - {name = "propcache-0.3.2-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/76/58/ced2757a46f55b8c84358d6ab8de4faf57cba831c51e823654da7144b13a/propcache-0.3.2-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "21d8759141a9e00a681d35a1f160892a36fb6caa715ba0b832f7747da48fb6ea"}}, - {name = "propcache-0.3.2-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/bb/ec/d98ea8d5a4d8fe0e372033f5254eddf3254344c0c5dc6c49ab84349e4733/propcache-0.3.2-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "2ca6d378f09adb13837614ad2754fa8afaee330254f404299611bce41a8438cb"}}, - {name = "propcache-0.3.2-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/56/84/b6d8a7ecf3f62d7dd09d9d10bbf89fad6837970ef868b35b5ffa0d24d9de/propcache-0.3.2-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "34a624af06c048946709f4278b4176470073deda88d91342665d95f7c6270fbe"}}, - {name = "propcache-0.3.2-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/bf/32/889f4903ddfe4a9dc61da71ee58b763758cf2d608fe1decede06e6467f8d/propcache-0.3.2-cp39-cp39-win32.whl",hashes = {sha256 = "4ba3fef1c30f306b1c274ce0b8baaa2c3cdd91f645c48f06394068f37d3837a1"}}, - {name = "propcache-0.3.2-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/67/74/d666795fb9ba1dc139d30de64f3b6fd1ff9c9d3d96ccfdb992cd715ce5d2/propcache-0.3.2-cp39-cp39-win_amd64.whl",hashes = {sha256 = "7a2368eed65fc69a7a7a40b27f22e85e7627b74216f0846b04ba5c116e191ec9"}}, ] marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "aiofiles" +version = "24.1.0" +requires-python = ">=3.8" +sdist = {name = "aiofiles-24.1.0.tar.gz", url = "https://files.pythonhosted.org/packages/0b/03/a88171e277e8caa88a4c77808c20ebb04ba74cc4681bf1e9416c862de237/aiofiles-24.1.0.tar.gz", hashes = {sha256 = "22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}} +wheels = [ + {name = "aiofiles-24.1.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a5/45/30bb92d442636f570cb5651bc661f52b610e2eec3f891a5dc3a4c3667db0/aiofiles-24.1.0-py3-none-any.whl",hashes = {sha256 = "b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "aiohappyeyeballs" version = "2.6.1" @@ -2203,6 +1839,21 @@ marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "aiologic" +version = "0.14.0" +requires-python = ">=3.8" +sdist = {name = "aiologic-0.14.0.tar.gz", url = "https://files.pythonhosted.org/packages/7e/2d/e893dcfa041dab1d045abfc8898239747cde19881796640861609138d360/aiologic-0.14.0.tar.gz", hashes = {sha256 = "c87925fa2bfe9ae292859e1094eb8fb6d456c8202a16405b0a44134803c8a791"}} +wheels = [ + {name = "aiologic-0.14.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/4d/1f/f797b684fb4e11a5066ab464b460b5cfdbaedea9c4a3d0f0afc8e894ada0/aiologic-0.14.0-py3-none-any.whl",hashes = {sha256 = "cc59d39dc1d5e2575b4a6b5faf678b551fb0f910c7cb42e4c5f5689ffedcce78"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "wrapt>=1.16.0", +] + [[packages]] name = "aiosignal" version = "1.4.0" @@ -2276,58 +1927,7 @@ wheels = [ {name = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1c/80/9a0eb48b944050f94cc51ee1c413eb14a39543cc4f760ed12657a5a3c45a/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43"}}, {name = "frozenlist-1.7.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/f3/74/87601e0fb0369b7a2baf404ea921769c53b7ae00dee7dcfe5162c8c6dbf0/frozenlist-1.7.0-cp312-cp312-win32.whl",hashes = {sha256 = "426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3"}}, {name = "frozenlist-1.7.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/0b/15/c026e9a9fc17585a9d461f65d8593d281fedf55fbf7eb53f16c6df2392f9/frozenlist-1.7.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a"}}, - {name = "frozenlist-1.7.0-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/34/7e/803dde33760128acd393a27eb002f2020ddb8d99d30a44bfbaab31c5f08a/frozenlist-1.7.0-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "aa51e147a66b2d74de1e6e2cf5921890de6b0f4820b257465101d7f37b49fb5a"}}, - {name = "frozenlist-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/75/a9/9c2c5760b6ba45eae11334db454c189d43d34a4c0b489feb2175e5e64277/frozenlist-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "9b35db7ce1cd71d36ba24f80f0c9e7cff73a28d7a74e91fe83e23d27c7828750"}}, - {name = "frozenlist-1.7.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/47/be/4038e2d869f8a2da165f35a6befb9158c259819be22eeaf9c9a8f6a87771/frozenlist-1.7.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "34a69a85e34ff37791e94542065c8416c1afbf820b68f720452f636d5fb990cd"}}, - {name = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/79/26/85314b8a83187c76a37183ceed886381a5f992975786f883472fcb6dc5f2/frozenlist-1.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "4a646531fa8d82c87fe4bb2e596f23173caec9185bfbca5d583b4ccfb95183e2"}}, - {name = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/1f/fd/e5b64f7d2c92a41639ffb2ad44a6a82f347787abc0c7df5f49057cf11770/frozenlist-1.7.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "79b2ffbba483f4ed36a0f236ccb85fbb16e670c9238313709638167670ba235f"}}, - {name = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/20/fb/03395c0a43a5976af4bf7534759d214405fbbb4c114683f434dfdd3128ef/frozenlist-1.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "a26f205c9ca5829cbf82bb2a84b5c36f7184c4316617d7ef1b271a56720d6b30"}}, - {name = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/d0/15/c01c8e1dffdac5d9803507d824f27aed2ba76b6ed0026fab4d9866e82f1f/frozenlist-1.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "bcacfad3185a623fa11ea0e0634aac7b691aa925d50a440f39b458e41c561d98"}}, - {name = "frozenlist-1.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/14/99/3f4c6fe882c1f5514b6848aa0a69b20cb5e5d8e8f51a339d48c0e9305ed0/frozenlist-1.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "72c1b0fe8fe451b34f12dce46445ddf14bd2a5bcad7e324987194dc8e3a74c86"}}, - {name = "frozenlist-1.7.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/4d/83/220a374bd7b2aeba9d0725130665afe11de347d95c3620b9b82cc2fcab97/frozenlist-1.7.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "61d1a5baeaac6c0798ff6edfaeaa00e0e412d49946c53fae8d4b8e8b3566c4ae"}}, - {name = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/03/3c/3e3390d75334a063181625343e8daab61b77e1b8214802cc4e8a1bb678fc/frozenlist-1.7.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7edf5c043c062462f09b6820de9854bf28cc6cc5b6714b383149745e287181a8"}}, - {name = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/23/1e/58232c19608b7a549d72d9903005e2d82488f12554a32de2d5fb59b9b1ba/frozenlist-1.7.0-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "d50ac7627b3a1bd2dcef6f9da89a772694ec04d9a61b66cf87f7d9446b4a0c31"}}, - {name = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/c0/a4/e4a567e01702a88a74ce8a324691e62a629bf47d4f8607f24bf1c7216e7f/frozenlist-1.7.0-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "ce48b2fece5aeb45265bb7a58259f45027db0abff478e3077e12b05b17fb9da7"}}, - {name = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/73/a6/63b3374f7d22268b41a9db73d68a8233afa30ed164c46107b33c4d18ecdd/frozenlist-1.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "fe2365ae915a1fafd982c146754e1de6ab3478def8a59c86e1f7242d794f97d5"}}, - {name = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/6d/eb/d18b3f6e64799a79673c4ba0b45e4cfbe49c240edfd03a68be20002eaeaa/frozenlist-1.7.0-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "45a6f2fdbd10e074e8814eb98b05292f27bad7d1883afbe009d96abdcf3bc898"}}, - {name = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5a/f5/720f3812e3d06cd89a1d5db9ff6450088b8f5c449dae8ffb2971a44da506/frozenlist-1.7.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "21884e23cffabb157a9dd7e353779077bf5b8f9a58e9b262c6caad2ef5f80a56"}}, - {name = "frozenlist-1.7.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/69/68/03efbf545e217d5db8446acfd4c447c15b7c8cf4dbd4a58403111df9322d/frozenlist-1.7.0-cp311-cp311-win32.whl",hashes = {sha256 = "284d233a8953d7b24f9159b8a3496fc1ddc00f4db99c324bd5fb5f22d8698ea7"}}, - {name = "frozenlist-1.7.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/58/17/fe61124c5c333ae87f09bb67186d65038834a47d974fc10a5fadb4cc5ae1/frozenlist-1.7.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "387cbfdcde2f2353f19c2f66bbb52406d06ed77519ac7ee21be0232147c2592d"}}, - {name = "frozenlist-1.7.0-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/af/36/0da0a49409f6b47cc2d060dc8c9040b897b5902a8a4e37d9bc1deb11f680/frozenlist-1.7.0-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "cc4df77d638aa2ed703b878dd093725b72a824c3c546c076e8fdf276f78ee84a"}}, - {name = "frozenlist-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/77/f0/77c11d13d39513b298e267b22eb6cb559c103d56f155aa9a49097221f0b6/frozenlist-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "716a9973a2cc963160394f701964fe25012600f3d311f60c790400b00e568b61"}}, - {name = "frozenlist-1.7.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/37/12/9d07fa18971a44150593de56b2f2947c46604819976784bcf6ea0d5db43b/frozenlist-1.7.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "a0fd1bad056a3600047fb9462cff4c5322cebc59ebf5d0a3725e0ee78955001d"}}, - {name = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/70/34/f73539227e06288fcd1f8a76853e755b2b48bca6747e99e283111c18bcd4/frozenlist-1.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "3789ebc19cb811163e70fe2bd354cea097254ce6e707ae42e56f45e31e96cb8e"}}, - {name = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/fb/68/c1d9c2f4a6e438e14613bad0f2973567586610cc22dcb1e1241da71de9d3/frozenlist-1.7.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "af369aa35ee34f132fcfad5be45fbfcde0e3a5f6a1ec0712857f286b7d20cca9"}}, - {name = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b9/d0/98e8f9a515228d708344d7c6986752be3e3192d1795f748c24bcf154ad99/frozenlist-1.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "ac64b6478722eeb7a3313d494f8342ef3478dff539d17002f849101b212ef97c"}}, - {name = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/79/df/8a11bcec5600557f40338407d3e5bea80376ed1c01a6c0910fcfdc4b8993/frozenlist-1.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "f89f65d85774f1797239693cef07ad4c97fdd0639544bad9ac4b869782eb1981"}}, - {name = "frozenlist-1.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/50/82/41cb97d9c9a5ff94438c63cc343eb7980dac4187eb625a51bdfdb7707314/frozenlist-1.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "1073557c941395fdfcfac13eb2456cb8aad89f9de27bae29fabca8e563b12615"}}, - {name = "frozenlist-1.7.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/13/47/f9179ee5ee4f55629e4f28c660b3fdf2775c8bfde8f9c53f2de2d93f52a9/frozenlist-1.7.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "1ed8d2fa095aae4bdc7fdd80351009a48d286635edffee66bf865e37a9125c50"}}, - {name = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/1a/52/df81e41ec6b953902c8b7e3a83bee48b195cb0e5ec2eabae5d8330c78038/frozenlist-1.7.0-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "24c34bea555fe42d9f928ba0a740c553088500377448febecaa82cc3e88aa1fa"}}, - {name = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/84/17/30d6ea87fa95a9408245a948604b82c1a4b8b3e153cea596421a2aef2754/frozenlist-1.7.0-cp310-cp310-musllinux_1_2_armv7l.whl",hashes = {sha256 = "69cac419ac6a6baad202c85aaf467b65ac860ac2e7f2ac1686dc40dbb52f6577"}}, - {name = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/8f/00/ecbeb51669e3c3df76cf2ddd66ae3e48345ec213a55e3887d216eb4fbab3/frozenlist-1.7.0-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "960d67d0611f4c87da7e2ae2eacf7ea81a5be967861e0c63cf205215afbfac59"}}, - {name = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/1a/c0/c224ce0e0eb31cc57f67742071bb470ba8246623c1823a7530be0e76164c/frozenlist-1.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "41be2964bd4b15bf575e5daee5a5ce7ed3115320fb3c2b71fca05582ffa4dc9e"}}, - {name = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/55/3c/34cb694abf532f31f365106deebdeac9e45c19304d83cf7d51ebbb4ca4d1/frozenlist-1.7.0-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "46d84d49e00c9429238a7ce02dc0be8f6d7cd0cd405abd1bebdc991bf27c15bd"}}, - {name = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/98/c0/2052d8b6cecda2e70bd81299e3512fa332abb6dcd2969b9c80dfcdddbf75/frozenlist-1.7.0-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "15900082e886edb37480335d9d518cec978afc69ccbc30bd18610b7c1b22a718"}}, - {name = "frozenlist-1.7.0-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/c5/bf/7dcebae315436903b1d98ffb791a09d674c88480c158aa171958a3ac07f0/frozenlist-1.7.0-cp310-cp310-win32.whl",hashes = {sha256 = "400ddd24ab4e55014bba442d917203c73b2846391dd42ca5e38ff52bb18c3c5e"}}, - {name = "frozenlist-1.7.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8f/5f/f69818f017fa9a3d24d1ae39763e29b7f60a59e46d5f91b9c6b21622f4cd/frozenlist-1.7.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "6eb93efb8101ef39d32d50bce242c84bcbddb4f7e9febfa7b524532a239b4464"}}, {name = "frozenlist-1.7.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ee/45/b82e3c16be2182bff01179db177fe144d58b5dc787a7d4492c6ed8b9317f/frozenlist-1.7.0-py3-none-any.whl",hashes = {sha256 = "9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e"}}, - {name = "frozenlist-1.7.0-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/dd/b1/ee59496f51cd244039330015d60f13ce5a54a0f2bd8d79e4a4a375ab7469/frozenlist-1.7.0-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "cea3dbd15aea1341ea2de490574a4a37ca080b2ae24e4b4f4b51b9057b4c3630"}}, - {name = "frozenlist-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/75/e1/d518391ce36a6279b3fa5bc14327dde80bcb646bb50d059c6ca0756b8d05/frozenlist-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "7d536ee086b23fecc36c2073c371572374ff50ef4db515e4e503925361c24f71"}}, - {name = "frozenlist-1.7.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b7/8d/a0d04f28b6e821a9685c22e67b5fb798a5a7b68752f104bfbc2dccf080c4/frozenlist-1.7.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "dfcebf56f703cb2e346315431699f00db126d158455e513bd14089d992101e44"}}, - {name = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/93/3a/a5334c0535c8b7c78eeabda1579179e44fe3d644e07118e59a2276dedaf1/frozenlist-1.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "974c5336e61d6e7eb1ea5b929cb645e882aadab0095c5a6974a111e6479f8878"}}, - {name = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/0a/67/8258d971f519dc3f278c55069a775096cda6610a267b53f6248152b72b2f/frozenlist-1.7.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl",hashes = {sha256 = "c70db4a0ab5ab20878432c40563573229a7ed9241506181bba12f6b7d0dc41cb"}}, - {name = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/fc/89/8225905bf889b97c6d935dd3aeb45668461e59d415cb019619383a8a7c3b/frozenlist-1.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "1137b78384eebaf70560a36b7b229f752fb64d463d38d1304939984d5cb887b6"}}, - {name = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/54/6e/ef52375aa93d4bc510d061df06205fa6dcfd94cd631dd22956b09128f0d4/frozenlist-1.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "e793a9f01b3e8b5c0bc646fb59140ce0efcc580d22a3468d70766091beb81b35"}}, - {name = "frozenlist-1.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/ee/55/62c87d1a6547bfbcd645df10432c129100c5bd0fd92a384de6e3378b07c1/frozenlist-1.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "74739ba8e4e38221d2c5c03d90a7e542cb8ad681915f4ca8f68d04f810ee0a87"}}, - {name = "frozenlist-1.7.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/45/d2/263fea1f658b8ad648c7d94d18a87bca7e8c67bd6a1bbf5445b1bd5b158c/frozenlist-1.7.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "1e63344c4e929b1a01e29bc184bbb5fd82954869033765bfe8d65d09e336a677"}}, - {name = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7b/22/7145e35d12fb368d92124f679bea87309495e2e9ddf14c6533990cb69218/frozenlist-1.7.0-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "2ea2a7369eb76de2217a842f22087913cdf75f63cf1307b9024ab82dfb525938"}}, - {name = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/44/1e/7dae8c54301beb87bcafc6144b9a103bfd2c8f38078c7902984c9a0c4e5b/frozenlist-1.7.0-cp39-cp39-musllinux_1_2_armv7l.whl",hashes = {sha256 = "836b42f472a0e006e02499cef9352ce8097f33df43baaba3e0a28a964c26c7d2"}}, - {name = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/4b/1e/99c93e54aa382e949a98976a73b9b20c3aae6d9d893f31bbe4991f64e3a8/frozenlist-1.7.0-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "e22b9a99741294b2571667c07d9f8cceec07cb92aae5ccda39ea1b6052ed4319"}}, - {name = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/5e/9c/ca5105fa7fb5abdfa8837581be790447ae051da75d32f25c8f81082ffc45/frozenlist-1.7.0-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "9a19e85cc503d958abe5218953df722748d87172f71b73cf3c9257a91b999890"}}, - {name = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/8d/4d/e99014756093b4ddbb67fb8f0df11fe7a415760d69ace98e2ac6d5d43402/frozenlist-1.7.0-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "f22dac33bb3ee8fe3e013aa7b91dc12f60d61d05b7fe32191ffa84c3aafe77bd"}}, - {name = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8b/72/a19a40bcdaa28a51add2aaa3a1a294ec357f36f27bd836a012e070c5e8a5/frozenlist-1.7.0-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "9ccec739a99e4ccf664ea0775149f2749b8a6418eb5b8384b4dc0a7d15d304cb"}}, - {name = "frozenlist-1.7.0-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/08/49/0042469993e023a758af81db68c76907cd29e847d772334d4d201cbe9a42/frozenlist-1.7.0-cp39-cp39-win32.whl",hashes = {sha256 = "b3950f11058310008a87757f3eee16a8e1ca97979833239439586857bc25482e"}}, - {name = "frozenlist-1.7.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/5a/45/827d86ee475c877f5f766fbc23fb6acb6fada9e52f1c9720e2ba3eae32da/frozenlist-1.7.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "43a82fce6769c70f2f5a06248b614a7d268080a9d20f7457ef10ecee5af82b63"}}, ] marker = "\"default\" in dependency_groups or \"dev\" in extras" @@ -2362,6 +1962,19 @@ marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "audioread" +version = "3.0.1" +requires-python = ">=3.6" +sdist = {name = "audioread-3.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/db/d2/87016ca9f083acadffb2d8da59bfa3253e4da7eeb9f71fb8e7708dc97ecd/audioread-3.0.1.tar.gz", hashes = {sha256 = "ac5460a5498c48bdf2e8e767402583a4dcd13f4414d286f42ce4379e8b35066d"}} +wheels = [ + {name = "audioread-3.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/57/8d/30aa32745af16af0a9a650115fbe81bde7c610ed5c21b381fca0196f3a7f/audioread-3.0.1-py3-none-any.whl",hashes = {sha256 = "4cdce70b8adc0da0a3c9e0d85fb10b3ace30fbdf8d1670fd443929b61d117c33"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "babel" version = "2.17.0" @@ -2431,87 +2044,76 @@ dependencies = [] [[packages]] name = "coverage" -version = "7.10.6" +version = "7.10.7" requires-python = ">=3.9" -sdist = {name = "coverage-7.10.6.tar.gz", url = "https://files.pythonhosted.org/packages/14/70/025b179c993f019105b79575ac6edb5e084fb0f0e63f15cdebef4e454fb5/coverage-7.10.6.tar.gz", hashes = {sha256 = "f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90"}} -wheels = [ - {name = "coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d3/aa/76cf0b5ec00619ef208da4689281d48b57f2c7fde883d14bf9441b74d59f/coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e"}}, - {name = "coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/65/91/8e41b8c7c505d398d7730206f3cbb4a875a35ca1041efc518051bfce0f6b/coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb"}}, - {name = "coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/87/7f/f718e732a423d442e6616580a951b8d1ec3575ea48bcd0e2228386805e79/coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034"}}, - {name = "coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/e6/52/c1106120e6d801ac03e12b5285e971e758e925b6f82ee9b86db3aa10045d/coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1"}}, - {name = "coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/3d/ec/3a8645b1bb40e36acde9c0609f08942852a4af91a937fe2c129a38f2d3f5/coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a"}}, - {name = "coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a1/70/09ecb68eeb1155b28a1d16525fd3a9b65fbe75337311a99830df935d62b6/coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb"}}, - {name = "coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/c6/80/47df374b893fa812e953b5bc93dcb1427a7b3d7a1a7d2db33043d17f74b9/coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl",hashes = {sha256 = "f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d"}}, - {name = "coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/4a/65/9f98640979ecee1b0d1a7164b589de720ddf8100d1747d9bbdb84be0c0fb/coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747"}}, - {name = "coverage-7.10.6-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/1f/55/eeb6603371e6629037f47bd25bef300387257ed53a3c5fdb159b7ac8c651/coverage-7.10.6-cp314-cp314-win32.whl",hashes = {sha256 = "6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5"}}, - {name = "coverage-7.10.6-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/15/d1/a0912b7611bc35412e919a2cd59ae98e7ea3b475e562668040a43fb27897/coverage-7.10.6-cp314-cp314-win_amd64.whl",hashes = {sha256 = "adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713"}}, - {name = "coverage-7.10.6-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ef/2d/11880bb8ef80a45338e0b3e0725e4c2d73ffbb4822c29d987078224fd6a5/coverage-7.10.6-cp314-cp314-win_arm64.whl",hashes = {sha256 = "a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32"}}, - {name = "coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/83/c0/1f00caad775c03a700146f55536ecd097a881ff08d310a58b353a1421be0/coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65"}}, - {name = "coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a9/c4/b1c5d2bd7cc412cbeb035e257fd06ed4e3e139ac871d16a07434e145d18d/coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6"}}, - {name = "coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/3f/07/4468d37c94724bf6ec354e4ec2f205fda194343e3e85fd2e59cec57e6a54/coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0"}}, - {name = "coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/82/d8/f8fb351be5fee31690cd8da768fd62f1cfab33c31d9f7baba6cd8960f6b8/coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e"}}, - {name = "coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e8/70/65d4d7cfc75c5c6eb2fed3ee5cdf420fd8ae09c4808723a89a81d5b1b9c3/coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5"}}, - {name = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/3c/069df106d19024324cde10e4ec379fe2fb978017d25e97ebee23002fbadf/coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7"}}, - {name = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/fc/8a/2974d53904080c5dc91af798b3a54a4ccb99a45595cc0dcec6eb9616a57d/coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl",hashes = {sha256 = "ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5"}}, - {name = "coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/30/38/9616a6b49c686394b318974d7f6e08f38b8af2270ce7488e879888d1e5db/coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0"}}, - {name = "coverage-7.10.6-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/76/16/3ed2d6312b371a8cf804abf4e14895b70e4c3491c6e53536d63fd0958a8d/coverage-7.10.6-cp314-cp314t-win32.whl",hashes = {sha256 = "441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7"}}, - {name = "coverage-7.10.6-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d5/e5/d38d0cb830abede2adb8b147770d2a3d0e7fecc7228245b9b1ae6c24930a/coverage-7.10.6-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930"}}, - {name = "coverage-7.10.6-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f4/51/e48e550f6279349895b0ffcd6d2a690e3131ba3a7f4eafccc141966d4dea/coverage-7.10.6-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b"}}, - {name = "coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/bd/e7/917e5953ea29a28c1057729c1d5af9084ab6d9c66217523fd0e10f14d8f6/coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6"}}, - {name = "coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/eb/86/2e161b93a4f11d0ea93f9bebb6a53f113d5d6e416d7561ca41bb0a29996b/coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80"}}, - {name = "coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/0e/66/d03348fdd8df262b3a7fb4ee5727e6e4936e39e2f3a842e803196946f200/coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003"}}, - {name = "coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/73/dd/508420fb47d09d904d962f123221bc249f64b5e56aa93d5f5f7603be475f/coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27"}}, - {name = "coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e9/1f/9020135734184f439da85c70ea78194c2730e56c2d18aee6e8ff1719d50d/coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4"}}, - {name = "coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a4/a4/3d228f3942bb5a2051fde28c136eea23a761177dc4ff4ef54533164ce255/coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d"}}, - {name = "coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/36/e3/293dce8cdb9a83de971637afc59b7190faad60603b40e32635cbd15fbf61/coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc"}}, - {name = "coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/90/26/64eecfa214e80dd1d101e420cab2901827de0e49631d666543d0e53cf597/coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc"}}, - {name = "coverage-7.10.6-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/3e/70/bd80588338f65ea5b0d97e424b820fb4068b9cfb9597fbd91963086e004b/coverage-7.10.6-cp313-cp313-win32.whl",hashes = {sha256 = "160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e"}}, - {name = "coverage-7.10.6-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a7/14/0b831122305abcc1060c008f6c97bbdc0a913ab47d65070a01dc50293c2b/coverage-7.10.6-cp313-cp313-win_amd64.whl",hashes = {sha256 = "628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32"}}, - {name = "coverage-7.10.6-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/83/c6/81a83778c1f83f1a4a168ed6673eeedc205afb562d8500175292ca64b94e/coverage-7.10.6-cp313-cp313-win_arm64.whl",hashes = {sha256 = "df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2"}}, - {name = "coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d7/1c/ccccf4bf116f9517275fa85047495515add43e41dfe8e0bef6e333c6b344/coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b"}}, - {name = "coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/92/97/8a3ceff833d27c7492af4f39d5da6761e9ff624831db9e9f25b3886ddbca/coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393"}}, - {name = "coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/92/d8/50b4a32580cf41ff0423777a2791aaf3269ab60c840b62009aec12d3970d/coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27"}}, - {name = "coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/7e/7e/6a7df5a6fb440a0179d94a348eb6616ed4745e7df26bf2a02bc4db72c421/coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df"}}, - {name = "coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/3a/4c/a270a414f4ed5d196b9d3d67922968e768cd971d1b251e1b4f75e9362f75/coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb"}}, - {name = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/9c/8b/3210d663d594926c12f373c5370bf1e7c5c3a427519a8afa65b561b9a55c/coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282"}}, - {name = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/72/d0/e1961eff67e9e1dba3fc5eb7a4caf726b35a5b03776892da8d79ec895775/coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4"}}, - {name = "coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3a/06/d6478d152cd189b33eac691cba27a40704990ba95de49771285f34a5861e/coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21"}}, - {name = "coverage-7.10.6-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/ed/73/737440247c914a332f0b47f7598535b29965bf305e19bbc22d4c39615d2b/coverage-7.10.6-cp313-cp313t-win32.whl",hashes = {sha256 = "92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0"}}, - {name = "coverage-7.10.6-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bd/76/b92d3214740f2357ef4a27c75a526eb6c28f79c402e9f20a922c295c05e2/coverage-7.10.6-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5"}}, - {name = "coverage-7.10.6-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/fc/8e/6dcb29c599c8a1f654ec6cb68d76644fe635513af16e932d2d4ad1e5ac6e/coverage-7.10.6-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b"}}, - {name = "coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/26/06/263f3305c97ad78aab066d116b52250dd316e74fcc20c197b61e07eb391a/coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea"}}, - {name = "coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e9/60/1e1ded9a4fe80d843d7d53b3e395c1db3ff32d6c301e501f393b2e6c1c1f/coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634"}}, - {name = "coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/b8/25/52136173c14e26dfed8b106ed725811bb53c30b896d04d28d74cb64318b3/coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6"}}, - {name = "coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/cb/1d/ae25a7dc58fcce8b172d42ffe5313fc267afe61c97fa872b80ee72d9515a/coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9"}}, - {name = "coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f5/7a/1f561d47743710fe996957ed7c124b421320f150f1d38523d8d9102d3e2a/coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c"}}, - {name = "coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/6c/ad/8b97cd5d28aecdfde792dcbf646bac141167a5cacae2cd775998b45fabb5/coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a"}}, - {name = "coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/33/6a/95c32b558d9a61858ff9d79580d3877df3eb5bc9eed0941b1f187c89e143/coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5"}}, - {name = "coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/0d/9c/8ce95dee640a38e760d5b747c10913e7a06554704d60b41e73fdea6a1ffd/coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972"}}, - {name = "coverage-7.10.6-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/04/12/7a55b0bdde78a98e2eb2356771fd2dcddb96579e8342bb52aa5bc52e96f0/coverage-7.10.6-cp312-cp312-win32.whl",hashes = {sha256 = "a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d"}}, - {name = "coverage-7.10.6-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/36/4a/32b185b8b8e327802c9efce3d3108d2fe2d9d31f153a0f7ecfd59c773705/coverage-7.10.6-cp312-cp312-win_amd64.whl",hashes = {sha256 = "856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629"}}, - {name = "coverage-7.10.6-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/08/3a/d5d8dc703e4998038c3099eaf77adddb00536a3cec08c8dcd556a36a3eb4/coverage-7.10.6-cp312-cp312-win_arm64.whl",hashes = {sha256 = "acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80"}}, - {name = "coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/d4/16/2bea27e212c4980753d6d563a0803c150edeaaddb0771a50d2afc410a261/coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f"}}, - {name = "coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2a/51/e7159e068831ab37e31aac0969d47b8c5ee25b7d307b51e310ec34869315/coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc"}}, - {name = "coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/e7/c0/246ccbea53d6099325d25cd208df94ea435cd55f0db38099dd721efc7a1f/coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a"}}, - {name = "coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/7d/fb/7435ef8ab9b2594a6e3f58505cc30e98ae8b33265d844007737946c59389/coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a"}}, - {name = "coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/51/f8/d9d64e8da7bcddb094d511154824038833c81e3a039020a9d6539bf303e9/coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62"}}, - {name = "coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/43/28/c43ba0ef19f446d6463c751315140d8f2a521e04c3e79e5c5fe211bfa430/coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153"}}, - {name = "coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/79/3e/53635bd0b72beaacf265784508a0b386defc9ab7fad99ff95f79ce9db555/coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5"}}, - {name = "coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/4c/55/0964aa87126624e8c159e32b0bc4e84edef78c89a1a4b924d28dd8265625/coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619"}}, - {name = "coverage-7.10.6-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/eb/ab/6cfa9dc518c6c8e14a691c54e53a9433ba67336c760607e299bfcf520cb1/coverage-7.10.6-cp311-cp311-win32.whl",hashes = {sha256 = "e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba"}}, - {name = "coverage-7.10.6-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/5b/18/99b25346690cbc55922e7cfef06d755d4abee803ef335baff0014268eff4/coverage-7.10.6-cp311-cp311-win_amd64.whl",hashes = {sha256 = "f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e"}}, - {name = "coverage-7.10.6-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/d8/ed/81d86648a07ccb124a5cf1f1a7788712b8d7216b593562683cd5c9b0d2c1/coverage-7.10.6-cp311-cp311-win_arm64.whl",hashes = {sha256 = "99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c"}}, - {name = "coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/a8/1d/2e64b43d978b5bd184e0756a41415597dfef30fcbd90b747474bd749d45f/coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356"}}, - {name = "coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/23/62/b1e0f513417c02cc10ef735c3ee5186df55f190f70498b3702d516aad06f/coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301"}}, - {name = "coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/e7/16/b800640b7a43e7c538429e4d7223e0a94fd72453a1a048f70bf766f12e96/coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460"}}, - {name = "coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/fb/6f/5e03631c3305cad187eaf76af0b559fff88af9a0b0c180d006fb02413d7a/coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd"}}, - {name = "coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/eb/a1/f30ea0fb400b080730125b490771ec62b3375789f90af0bb68bfb8a921d7/coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb"}}, - {name = "coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/02/8e/cfa8fee8e8ef9a6bb76c7bef039f3302f44e615d2194161a21d3d83ac2e9/coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6"}}, - {name = "coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/93/a9/51be09b75c55c4f6c16d8d73a6a1d46ad764acca0eab48fa2ffaef5958fe/coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945"}}, - {name = "coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e9/a6/ba188b376529ce36483b2d585ca7bdac64aacbe5aa10da5978029a9c94db/coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e"}}, - {name = "coverage-7.10.6-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/d0/4c/37ed872374a21813e0d3215256180c9a382c3f5ced6f2e5da0102fc2fd3e/coverage-7.10.6-cp310-cp310-win32.whl",hashes = {sha256 = "86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1"}}, - {name = "coverage-7.10.6-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8e/36/9311352fdc551dec5b973b61f4e453227ce482985a9368305880af4f85dd/coverage-7.10.6-cp310-cp310-win_amd64.whl",hashes = {sha256 = "e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528"}}, - {name = "coverage-7.10.6-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/44/0c/50db5379b615854b5cf89146f8f5bd1d5a9693d7f3a987e269693521c404/coverage-7.10.6-py3-none-any.whl",hashes = {sha256 = "92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3"}}, +sdist = {name = "coverage-7.10.7.tar.gz", url = "https://files.pythonhosted.org/packages/51/26/d22c300112504f5f9a9fd2297ce33c35f3d353e4aeb987c8419453b2a7c2/coverage-7.10.7.tar.gz", hashes = {sha256 = "f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239"}} +wheels = [ + {name = "coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/23/9c/5844ab4ca6a4dd97a1850e030a15ec7d292b5c5cb93082979225126e35dd/coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520"}}, + {name = "coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f0/89/673f6514b0961d1f0e20ddc242e9342f6da21eaba3489901b565c0689f34/coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32"}}, + {name = "coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/05/e8/261cae479e85232828fb17ad536765c88dd818c8470aca690b0ac6feeaa3/coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f"}}, + {name = "coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/82/62/14ed6546d0207e6eda876434e3e8475a3e9adbe32110ce896c9e0c06bb9a/coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a"}}, + {name = "coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ff/49/07f00db9ac6478e4358165a08fb41b469a1b053212e8a00cb02f0d27a05f/coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360"}}, + {name = "coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/a2/59/c5201c62dbf165dfbc91460f6dbbaa85a8b82cfa6131ac45d6c1bfb52deb/coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69"}}, + {name = "coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/07/ae/5920097195291a51fb00b3a70b9bbd2edbfe3c84876a1762bd1ef1565ebc/coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14"}}, + {name = "coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/b9/3c/a815dde77a2981f5743a60b63df31cb322c944843e57dbd579326625a413/coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl",hashes = {sha256 = "39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe"}}, + {name = "coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/aa/99/f5cdd8421ea656abefb6c0ce92556709db2265c41e8f9fc6c8ae0f7824c9/coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl",hashes = {sha256 = "925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e"}}, + {name = "coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c3/7a/e9a2da6a1fc5d007dd51fca083a663ab930a8c4d149c087732a5dbaa0029/coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd"}}, + {name = "coverage-7.10.7-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/ef/5b/0b5799aa30380a949005a353715095d6d1da81927d6dbed5def2200a4e25/coverage-7.10.7-cp314-cp314-win32.whl",hashes = {sha256 = "b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2"}}, + {name = "coverage-7.10.7-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/da/b0/e802fbb6eb746de006490abc9bb554b708918b6774b722bb3a0e6aa1b7de/coverage-7.10.7-cp314-cp314-win_amd64.whl",hashes = {sha256 = "1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681"}}, + {name = "coverage-7.10.7-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9e/e8/71d0c8e374e31f39e3389bb0bd19e527d46f00ea8571ec7ec8fd261d8b44/coverage-7.10.7-cp314-cp314-win_arm64.whl",hashes = {sha256 = "097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880"}}, + {name = "coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/62/09/9a5608d319fa3eba7a2019addeacb8c746fb50872b57a724c9f79f146969/coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63"}}, + {name = "coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/f5/6f/f58d46f33db9f2e3647b2d0764704548c184e6f5e014bef528b7f979ef84/coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2"}}, + {name = "coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/74/5c/183ffc817ba68e0b443b8c934c8795553eb0c14573813415bd59941ee165/coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d"}}, + {name = "coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/0f/48/71a8abe9c1ad7e97548835e3cc1adbf361e743e9d60310c5f75c9e7bf847/coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0"}}, + {name = "coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/84/fd/193a8fb132acfc0a901f72020e54be5e48021e1575bb327d8ee1097a28fd/coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699"}}, + {name = "coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/b1/8f/74ecc30607dd95ad50e3034221113ccb1c6d4e8085cc761134782995daae/coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9"}}, + {name = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/0f/55/79ff53a769f20d71b07023ea115c9167c0bb56f281320520cf64c5298a96/coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f"}}, + {name = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/88/e2/dac66c140009b61ac3fc13af673a574b00c16efdf04f9b5c740703e953c0/coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl",hashes = {sha256 = "0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1"}}, + {name = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/a2/f1/f48f645e3f33bb9ca8a496bc4a9671b52f2f353146233ebd7c1df6160440/coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0"}}, + {name = "coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/bb/3b/8442618972c51a7affeead957995cfa8323c0c9bcf8fa5a027421f720ff4/coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399"}}, + {name = "coverage-7.10.7-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/b2/dc/101f3fa3a45146db0cb03f5b4376e24c0aac818309da23e2de0c75295a91/coverage-7.10.7-cp314-cp314t-win32.whl",hashes = {sha256 = "67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235"}}, + {name = "coverage-7.10.7-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/4c/a1/74c51803fc70a8a40d7346660379e144be772bab4ac7bb6e6b905152345c/coverage-7.10.7-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d"}}, + {name = "coverage-7.10.7-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/12/65/f116a6d2127df30bcafbceef0302d8a64ba87488bf6f73a6d8eebf060873/coverage-7.10.7-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a"}}, + {name = "coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d"}}, + {name = "coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/72/4f/732fff31c119bb73b35236dd333030f32c4bfe909f445b423e6c7594f9a2/coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b"}}, + {name = "coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/87/02/ae7e0af4b674be47566707777db1aa375474f02a1d64b9323e5813a6cdd5/coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e"}}, + {name = "coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b"}}, + {name = "coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/b1/20/b6ea4f69bbb52dac0aebd62157ba6a9dddbfe664f5af8122dac296c3ee15/coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49"}}, + {name = "coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/f9/28/4831523ba483a7f90f7b259d2018fef02cb4d5b90bc7c1505d6e5a84883c/coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911"}}, + {name = "coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/a7/9f/4331142bc98c10ca6436d2d620c3e165f31e6c58d43479985afce6f3191c/coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0"}}, + {name = "coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ce/60/bda83b96602036b77ecf34e6393a3836365481b69f7ed7079ab85048202b/coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f"}}, + {name = "coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/5f/af/152633ff35b2af63977edd835d8e6430f0caef27d171edf2fc76c270ef31/coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl",hashes = {sha256 = "b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c"}}, + {name = "coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/9d/71/d92105d122bd21cebba877228990e1646d862e34a98bb3374d3fece5a794/coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f"}}, + {name = "coverage-7.10.7-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/a2/9e/9fdb08f4bf476c912f0c3ca292e019aab6712c93c9344a1653986c3fd305/coverage-7.10.7-cp313-cp313-win32.whl",hashes = {sha256 = "dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698"}}, + {name = "coverage-7.10.7-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl",hashes = {sha256 = "cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843"}}, + {name = "coverage-7.10.7-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/14/3a/d720d7c989562a6e9a14b2c9f5f2876bdb38e9367126d118495b89c99c37/coverage-7.10.7-cp313-cp313-win_arm64.whl",hashes = {sha256 = "4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546"}}, + {name = "coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/bb/22/e04514bf2a735d8b0add31d2b4ab636fc02370730787c576bb995390d2d5/coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c"}}, + {name = "coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/11/0b/91128e099035ece15da3445d9015e4b4153a6059403452d324cbb0a575fa/coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15"}}, + {name = "coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/8b/51/66420081e72801536a091a0c8f8c1f88a5c4bf7b9b1bdc6222c7afe6dc9b/coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4"}}, + {name = "coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/5d/22/9b8d458c2881b22df3db5bb3e7369e63d527d986decb6c11a591ba2364f7/coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0"}}, + {name = "coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f7/08/16bee2c433e60913c610ea200b276e8eeef084b0d200bdcff69920bd5828/coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0"}}, + {name = "coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/20/9d/e53eb9771d154859b084b90201e5221bca7674ba449a17c101a5031d4054/coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65"}}, + {name = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ad/b0/69bc7050f8d4e56a89fb550a1577d5d0d1db2278106f6f626464067b3817/coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541"}}, + {name = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/ef/4b/2514b060dbd1bc0aaf23b852c14bb5818f244c664cb16517feff6bb3a5ab/coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl",hashes = {sha256 = "2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6"}}, + {name = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/54/78/7ba2175007c246d75e496f64c06e94122bdb914790a1285d627a918bd271/coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999"}}, + {name = "coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c0/b3/fac9f7abbc841409b9a410309d73bfa6cfb2e51c3fada738cb607ce174f8/coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2"}}, + {name = "coverage-7.10.7-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/ee/51/a03bec00d37faaa891b3ff7387192cef20f01604e5283a5fabc95346befa/coverage-7.10.7-cp313-cp313t-win32.whl",hashes = {sha256 = "2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a"}}, + {name = "coverage-7.10.7-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/53/22/3cf25d614e64bf6d8e59c7c669b20d6d940bb337bdee5900b9ca41c820bb/coverage-7.10.7-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb"}}, + {name = "coverage-7.10.7-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/49/a1/00164f6d30d8a01c3c9c48418a7a5be394de5349b421b9ee019f380df2a0/coverage-7.10.7-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb"}}, + {name = "coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417"}}, + {name = "coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/37/66/593f9be12fc19fb36711f19a5371af79a718537204d16ea1d36f16bd78d2/coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973"}}, + {name = "coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/66/80/4c49f7ae09cafdacc73fbc30949ffe77359635c168f4e9ff33c9ebb07838/coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c"}}, + {name = "coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7"}}, + {name = "coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/2e/2dda59afd6103b342e096f246ebc5f87a3363b5412609946c120f4e7750d/coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6"}}, + {name = "coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/53/dc/8d8119c9051d50f3119bb4a75f29f1e4a6ab9415cd1fa8bf22fcc3fb3b5f/coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59"}}, + {name = "coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/b3/edaff9c5d79ee4d4b6d3fe046f2b1d799850425695b789d491a64225d493/coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b"}}, + {name = "coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/11/25/9a0728564bb05863f7e513e5a594fe5ffef091b325437f5430e8cfb0d530/coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a"}}, + {name = "coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/e0/fd/ca2650443bfbef5b0e74373aac4df67b08180d2f184b482c41499668e258/coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl",hashes = {sha256 = "5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb"}}, + {name = "coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/24/79/f692f125fb4299b6f963b0745124998ebb8e73ecdfce4ceceb06a8c6bec5/coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1"}}, + {name = "coverage-7.10.7-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/5e/75/61b9bbd6c7d24d896bfeec57acba78e0f8deac68e6baf2d4804f7aae1f88/coverage-7.10.7-cp312-cp312-win32.whl",hashes = {sha256 = "77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256"}}, + {name = "coverage-7.10.7-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ca/f3/3bf7905288b45b075918d372498f1cf845b5b579b723c8fd17168018d5f5/coverage-7.10.7-cp312-cp312-win_amd64.whl",hashes = {sha256 = "f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba"}}, + {name = "coverage-7.10.7-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/5c/44/3e32dbe933979d05cf2dac5e697c8599cfe038aaf51223ab901e208d5a62/coverage-7.10.7-cp312-cp312-win_arm64.whl",hashes = {sha256 = "bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf"}}, + {name = "coverage-7.10.7-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl",hashes = {sha256 = "f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260"}}, ] marker = "\"dev\" in extras" @@ -2519,19 +2121,17 @@ marker = "\"dev\" in extras" dependencies = [] [[packages]] -name = "exceptiongroup" -version = "1.3.0" -requires-python = ">=3.7" -sdist = {name = "exceptiongroup-1.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hashes = {sha256 = "b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}} +name = "decorator" +version = "5.2.1" +requires-python = ">=3.8" +sdist = {name = "decorator-5.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hashes = {sha256 = "65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}} wheels = [ - {name = "exceptiongroup-1.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl",hashes = {sha256 = "4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}}, + {name = "decorator-5.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl",hashes = {sha256 = "d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}}, ] -marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" +marker = "\"default\" in dependency_groups" [packages.tool.pdm] -dependencies = [ - "typing-extensions>=4.6.0; python_version < \"3.13\"", -] +dependencies = [] [[packages]] name = "h11" @@ -2547,12 +2147,51 @@ marker = "\"default\" in dependency_groups or \"dev\" in extras" dependencies = [] [[packages]] -name = "identify" -version = "2.6.12" -requires-python = ">=3.9" -sdist = {name = "identify-2.6.12.tar.gz", url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hashes = {sha256 = "d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6"}} +name = "html5tagger" +version = "1.3.0" +requires-python = ">=3.7" +sdist = {name = "html5tagger-1.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/9e/02/2ae5f46d517a2c1d4a17f2b1e4834c2c7cc0fb3a69c92389172fa16ab389/html5tagger-1.3.0.tar.gz", hashes = {sha256 = "84fa3dfb49e5c83b79bbd856ab7b1de8e2311c3bb46a8be925f119e3880a8da9"}} wheels = [ - {name = "identify-2.6.12-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl",hashes = {sha256 = "ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2"}}, + {name = "html5tagger-1.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/9b/12/2f5d43ee912ea14a6baba4b3db6d309b02d932e3b7074c3339b4aded98ff/html5tagger-1.3.0-py3-none-any.whl",hashes = {sha256 = "ce14313515edffec8ed8a36c5890d023922641171b4e6e5774ad1a74998f5351"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "httptools" +version = "0.6.4" +requires-python = ">=3.8.0" +sdist = {name = "httptools-0.6.4.tar.gz", url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hashes = {sha256 = "4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c"}} +wheels = [ + {name = "httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660"}}, + {name = "httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083"}}, + {name = "httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3"}}, + {name = "httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071"}}, + {name = "httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5"}}, + {name = "httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0"}}, + {name = "httptools-0.6.4-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl",hashes = {sha256 = "28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8"}}, + {name = "httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2"}}, + {name = "httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44"}}, + {name = "httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1"}}, + {name = "httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2"}}, + {name = "httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81"}}, + {name = "httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f"}}, + {name = "httptools-0.6.4-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl",hashes = {sha256 = "db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "identify" +version = "2.6.12" +requires-python = ">=3.9" +sdist = {name = "identify-2.6.12.tar.gz", url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hashes = {sha256 = "d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6"}} +wheels = [ + {name = "identify-2.6.12-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl",hashes = {sha256 = "ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2"}}, ] marker = "\"dev\" in extras" @@ -2573,34 +2212,47 @@ marker = "\"dev\" in extras" dependencies = [] [[packages]] -name = "importlib-metadata" -version = "8.7.0" -requires-python = ">=3.9" -sdist = {name = "importlib_metadata-8.7.0.tar.gz", url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hashes = {sha256 = "d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"}} +name = "jinja2" +version = "3.1.6" +requires-python = ">=3.7" +sdist = {name = "jinja2-3.1.6.tar.gz", url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hashes = {sha256 = "0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}} wheels = [ - {name = "importlib_metadata-8.7.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl",hashes = {sha256 = "e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"}}, + {name = "jinja2-3.1.6-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl",hashes = {sha256 = "85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}}, ] -marker = "python_full_version < \"3.10.2\" and python_version >= \"3.9\" and \"dev\" in extras" +marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [ - "zipp>=3.20", - "typing-extensions>=3.6.4; python_version < \"3.8\"", + "MarkupSafe>=2.0", ] [[packages]] -name = "jinja2" -version = "3.1.6" +name = "joblib" +version = "1.5.2" +requires-python = ">=3.9" +sdist = {name = "joblib-1.5.2.tar.gz", url = "https://files.pythonhosted.org/packages/e8/5d/447af5ea094b9e4c4054f82e223ada074c552335b9b4b2d14bd9b35a67c4/joblib-1.5.2.tar.gz", hashes = {sha256 = "3faa5c39054b2f03ca547da9b2f52fde67c06240c31853f306aea97f13647b55"}} +wheels = [ + {name = "joblib-1.5.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/1e/e8/685f47e0d754320684db4425a0967f7d3fa70126bffd76110b7009a0090f/joblib-1.5.2-py3-none-any.whl",hashes = {sha256 = "4e1f0bdbb987e6d843c70cf43714cb276623def372df3c22fe5266b2670bc241"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "lazy-loader" +version = "0.4" requires-python = ">=3.7" -sdist = {name = "jinja2-3.1.6.tar.gz", url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hashes = {sha256 = "0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}} +sdist = {name = "lazy_loader-0.4.tar.gz", url = "https://files.pythonhosted.org/packages/6f/6b/c875b30a1ba490860c93da4cabf479e03f584eba06fe5963f6f6644653d8/lazy_loader-0.4.tar.gz", hashes = {sha256 = "47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1"}} wheels = [ - {name = "jinja2-3.1.6-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl",hashes = {sha256 = "85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}}, + {name = "lazy_loader-0.4-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/83/60/d497a310bde3f01cb805196ac61b7ad6dc5dcf8dce66634dc34364b20b4f/lazy_loader-0.4-py3-none-any.whl",hashes = {sha256 = "342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc"}}, ] -marker = "\"dev\" in extras" +marker = "\"default\" in dependency_groups" [packages.tool.pdm] dependencies = [ - "MarkupSafe>=2.0", + "packaging", + "importlib-metadata; python_version < \"3.8\"", ] [[packages]] @@ -2663,46 +2315,6 @@ wheels = [ {name = "lxml-6.0.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/bc/1f/962ea2696759abe331c3b0e838bb17e92224f39c638c2068bf0d8345e913/lxml-6.0.1-cp312-cp312-win32.whl",hashes = {sha256 = "987ad5c3941c64031f59c226167f55a04d1272e76b241bfafc968bdb778e07fb"}}, {name = "lxml-6.0.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/41/e2/22c86a990b51b44442b75c43ecb2f77b8daba8c4ba63696921966eac7022/lxml-6.0.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "abb05a45394fd76bf4a60c1b7bec0e6d4e8dfc569fc0e0b1f634cd983a006ddc"}}, {name = "lxml-6.0.1-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/b2/21/dc0c73325e5eb94ef9c9d60dbb5dcdcb2e7114901ea9509735614a74e75a/lxml-6.0.1-cp312-cp312-win_arm64.whl",hashes = {sha256 = "c4be29bce35020d8579d60aa0a4e95effd66fcfce31c46ffddf7e5422f73a299"}}, - {name = "lxml-6.0.1-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/29/c8/262c1d19339ef644cdc9eb5aad2e85bd2d1fa2d7c71cdef3ede1a3eed84d/lxml-6.0.1-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "c6acde83f7a3d6399e6d83c1892a06ac9b14ea48332a5fbd55d60b9897b9570a"}}, - {name = "lxml-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/e5/d4/1b0afbeb801468a310642c3a6f6704e53c38a4a6eb1ca6faea013333e02f/lxml-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "0d21c9cacb6a889cbb8eeb46c77ef2c1dd529cde10443fdeb1de847b3193c541"}}, - {name = "lxml-6.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/5b/c1/8db9b5402bf52ceb758618313f7423cd54aea85679fcf607013707d854a8/lxml-6.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "847458b7cd0d04004895f1fb2cca8e7c0f8ec923c49c06b7a72ec2d48ea6aca2"}}, - {name = "lxml-6.0.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/e7/78/838e115358dd2369c1c5186080dd874a50a691fb5cd80db6afe5e816e2c6/lxml-6.0.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "1dc13405bf315d008fe02b1472d2a9d65ee1c73c0a06de5f5a45e6e404d9a1c0"}}, - {name = "lxml-6.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c7/b6/bdcb3a3ddd2438c5b1a1915161f34e8c85c96dc574b0ef3be3924f36315c/lxml-6.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "70f540c229a8c0a770dcaf6d5af56a5295e0fc314fc7ef4399d543328054bcea"}}, - {name = "lxml-6.0.1-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl",url = "https://files.pythonhosted.org/packages/73/e5/1bfb96185dc1a64c7c6fbb7369192bda4461952daa2025207715f9968205/lxml-6.0.1-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl",hashes = {sha256 = "d2f73aef768c70e8deb8c4742fca4fd729b132fda68458518851c7735b55297e"}}, - {name = "lxml-6.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/a2/ae/df3ea9ebc3c493b9c6bdc6bd8c554ac4e147f8d7839993388aab57ec606d/lxml-6.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "e7f4066b85a4fa25ad31b75444bd578c3ebe6b8ed47237896341308e2ce923c3"}}, - {name = "lxml-6.0.1-cp311-cp311-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/37/b3/65e1e33600542c08bc03a4c5c9c306c34696b0966a424a3be6ffec8038ed/lxml-6.0.1-cp311-cp311-manylinux_2_31_armv7l.whl",hashes = {sha256 = "0cce65db0cd8c750a378639900d56f89f7d6af11cd5eda72fde054d27c54b8ce"}}, - {name = "lxml-6.0.1-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7a/46/ee3ed8f3a60e9457d7aea46542d419917d81dbfd5700fe64b2a36fb5ef61/lxml-6.0.1-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c372d42f3eee5844b69dcab7b8d18b2f449efd54b46ac76970d6e06b8e8d9a66"}}, - {name = "lxml-6.0.1-cp311-cp311-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/9c/b9/8394538e7cdbeb3bfa36bc74924be1a4383e0bb5af75f32713c2c4aa0479/lxml-6.0.1-cp311-cp311-musllinux_1_2_armv7l.whl",hashes = {sha256 = "2e2b0e042e1408bbb1c5f3cfcb0f571ff4ac98d8e73f4bf37c5dd179276beedd"}}, - {name = "lxml-6.0.1-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b3/21/3ef7da1ea2a73976c1a5a311d7cde5d379234eec0968ee609517714940b4/lxml-6.0.1-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "cc73bb8640eadd66d25c5a03175de6801f63c535f0f3cf50cac2f06a8211f420"}}, - {name = "lxml-6.0.1-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/26/7d/0980016f124f00c572cba6f4243e13a8e80650843c66271ee692cddf25f3/lxml-6.0.1-cp311-cp311-win32.whl",hashes = {sha256 = "7c23fd8c839708d368e406282d7953cee5134f4592ef4900026d84566d2b4c88"}}, - {name = "lxml-6.0.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b1/08/28440437521f265eff4413eb2a65efac269c4c7db5fd8449b586e75d8de2/lxml-6.0.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "2516acc6947ecd3c41a4a4564242a87c6786376989307284ddb115f6a99d927f"}}, - {name = "lxml-6.0.1-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/7b/dc/617e67296d98099213a505d781f04804e7b12923ecd15a781a4ab9181992/lxml-6.0.1-cp311-cp311-win_arm64.whl",hashes = {sha256 = "cb46f8cfa1b0334b074f40c0ff94ce4d9a6755d492e6c116adb5f4a57fb6ad96"}}, - {name = "lxml-6.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/41/37/41961f53f83ded57b37e65e4f47d1c6c6ef5fd02cb1d6ffe028ba0efa7d4/lxml-6.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "b556aaa6ef393e989dac694b9c95761e32e058d5c4c11ddeef33f790518f7a5e"}}, - {name = "lxml-6.0.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/3d/47/8631ea73f3dc776fb6517ccde4d5bd5072f35f9eacbba8c657caa4037a69/lxml-6.0.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "64fac7a05ebb3737b79fd89fe5a5b6c5546aac35cfcfd9208eb6e5d13215771c"}}, - {name = "lxml-6.0.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/3d/b8/39ae30ca3b1516729faeef941ed84bf8f12321625f2644492ed8320cb254/lxml-6.0.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "038d3c08babcfce9dc89aaf498e6da205efad5b7106c3b11830a488d4eadf56b"}}, - {name = "lxml-6.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/9c/ea/048dea6cdfc7a72d40ae8ed7e7d23cf4a6b6a6547b51b492a3be50af0e80/lxml-6.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "445f2cee71c404ab4259bc21e20339a859f75383ba2d7fb97dfe7c163994287b"}}, - {name = "lxml-6.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/6b/d4/c2b46e432377c45d611ae2f669aa47971df1586c1a5240675801d0f02bac/lxml-6.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "e352d8578e83822d70bea88f3d08b9912528e4c338f04ab707207ab12f4b7aac"}}, - {name = "lxml-6.0.1-pp311-pypy311_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b6/db/8f620f1ac62cf32554821b00b768dd5957ac8e3fd051593532be5b40b438/lxml-6.0.1-pp311-pypy311_pp73-win_amd64.whl",hashes = {sha256 = "51bd5d1a9796ca253db6045ab45ca882c09c071deafffc22e06975b7ace36300"}}, - {name = "lxml-6.0.1-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/b2/06/29693634ad5fc8ae0bab6723ba913c821c780614eea9ab9ebb5b2105d0e4/lxml-6.0.1-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "3b38e20c578149fdbba1fd3f36cb1928a3aaca4b011dfd41ba09d11fb396e1b9"}}, - {name = "lxml-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/97/e0/69d4113afbda9441f0e4d5574d9336535ead6a0608ee6751b3db0832ade0/lxml-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "11a052cbd013b7140bbbb38a14e2329b6192478344c99097e378c691b7119551"}}, - {name = "lxml-6.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/eb/3d/8fa1dbf48a3ea0d6c646f0129bef89a5ecf9a1cfe935e26e07554261d728/lxml-6.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "21344d29c82ca8547ea23023bb8e7538fa5d4615a1773b991edf8176a870c1ea"}}, - {name = "lxml-6.0.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/2c/52/a48331a269900488b886d527611ab66238cddc6373054a60b3c15d4cefb2/lxml-6.0.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "aa8f130f4b2dc94baa909c17bb7994f0268a2a72b9941c872e8e558fd6709050"}}, - {name = "lxml-6.0.1-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/33/3b/8f6778a6fb9d30a692db2b1f5a9547dfcb674b27b397e1d864ca797486b1/lxml-6.0.1-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "4588806a721552692310ebe9f90c17ac6c7c5dac438cd93e3d74dd60531c3211"}}, - {name = "lxml-6.0.1-cp310-cp310-manylinux_2_26_i686.manylinux_2_28_i686.whl",url = "https://files.pythonhosted.org/packages/42/15/c9364f23fa89ef2d3dbb896912aa313108820286223cfa833a0a9e183c9e/lxml-6.0.1-cp310-cp310-manylinux_2_26_i686.manylinux_2_28_i686.whl",hashes = {sha256 = "8466faa66b0353802fb7c054a400ac17ce2cf416e3ad8516eadeff9cba85b741"}}, - {name = "lxml-6.0.1-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/04/af/11985b0d47786161ddcdc53dc06142dc863b81a38da7f221c7b997dd5d4b/lxml-6.0.1-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "50b5e54f6a9461b1e9c08b4a3420415b538d4773bd9df996b9abcbfe95f4f1fd"}}, - {name = "lxml-6.0.1-cp310-cp310-manylinux_2_31_armv7l.whl",url = "https://files.pythonhosted.org/packages/6a/42/74b35ccc9ef1bb53f0487a4dace5ff612f1652d27faafe91ada7f7b9ee60/lxml-6.0.1-cp310-cp310-manylinux_2_31_armv7l.whl",hashes = {sha256 = "6f393e10685b37f15b1daef8aa0d734ec61860bb679ec447afa0001a31e7253f"}}, - {name = "lxml-6.0.1-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b0/5a/b934534f83561ad71fb64ba1753992e836ea73776cfb56fc0758dbb46bdf/lxml-6.0.1-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "07038c62fd0fe2743e2f5326f54d464715373c791035d7dda377b3c9a5d0ad77"}}, - {name = "lxml-6.0.1-cp310-cp310-musllinux_1_2_armv7l.whl",url = "https://files.pythonhosted.org/packages/6c/26/d833a56ec8ca943b696f3a7a1e54f97cfb63754c951037de5e222c011f3b/lxml-6.0.1-cp310-cp310-musllinux_1_2_armv7l.whl",hashes = {sha256 = "7a44a5fb1edd11b3a65c12c23e1049c8ae49d90a24253ff18efbcb6aa042d012"}}, - {name = "lxml-6.0.1-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3f/cb/601aa274c7cda51d0cc84a13d9639096c1191de9d9adf58f6c195d4822a2/lxml-6.0.1-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "a57d9eb9aadf311c9e8785230eec83c6abb9aef2adac4c0587912caf8f3010b8"}}, - {name = "lxml-6.0.1-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/76/4e/e079f7b324e6d5f83007f30855448646e1cba74b5c30da1a081df75eba89/lxml-6.0.1-cp310-cp310-win32.whl",hashes = {sha256 = "d877874a31590b72d1fa40054b50dc33084021bfc15d01b3a661d85a302af821"}}, - {name = "lxml-6.0.1-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/65/0a/da298d7a96316c75ae096686de8d036d814ec3b72c7d643a2c226c364168/lxml-6.0.1-cp310-cp310-win_amd64.whl",hashes = {sha256 = "c43460f4aac016ee0e156bfa14a9de9b3e06249b12c228e27654ac3996a46d5b"}}, - {name = "lxml-6.0.1-cp310-cp310-win_arm64.whl",url = "https://files.pythonhosted.org/packages/0f/65/d7f61082fecf4543ab084e8bd3d4b9be0c1a0c83979f1fa2258e2a7987fb/lxml-6.0.1-cp310-cp310-win_arm64.whl",hashes = {sha256 = "615bb6c73fed7929e3a477a3297a797892846b253d59c84a62c98bdce3849a0a"}}, - {name = "lxml-6.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/ae/61/ad51fbecaf741f825d496947b19d8aea0dcd323fdc2be304e93ce59f66f0/lxml-6.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "0abfbaf4ebbd7fd33356217d317b6e4e2ef1648be6a9476a52b57ffc6d8d1780"}}, - {name = "lxml-6.0.1-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/1b/7f/310bef082cc69d0db46a8b9d8ca5f4a8fb41e1c5d299ef4ca5f391c4f12d/lxml-6.0.1-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "1ebbf2d9775be149235abebdecae88fe3b3dd06b1797cd0f6dffe6948e85309d"}}, - {name = "lxml-6.0.1-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/86/cc/dc5833def5998c783500666468df127d6d919e8b9678866904e5680b0b13/lxml-6.0.1-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "a389e9f11c010bd30531325805bbe97bdf7f728a73d0ec475adef57ffec60547"}}, - {name = "lxml-6.0.1-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/1b/dc/bdd4d413844b5348134444d64911f6f34b211f8b778361946d07623fc904/lxml-6.0.1-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "8f5cf2addfbbe745251132c955ad62d8519bb4b2c28b0aa060eca4541798d86e"}}, - {name = "lxml-6.0.1-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/14/e60e9d46972603753824eb7bea06fbe4153c627cc0f7110111253b7c9fc5/lxml-6.0.1-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "f1b60a3287bf33a2a54805d76b82055bcc076e445fd539ee9ae1fe85ed373691"}}, - {name = "lxml-6.0.1-pp310-pypy310_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/42/fa/268c9be8c69a418b8106e096687aba2b1a781fb6fc1b3f04955fac2be2b9/lxml-6.0.1-pp310-pypy310_pp73-win_amd64.whl",hashes = {sha256 = "f7bbfb0751551a8786915fc6b615ee56344dacc1b1033697625b553aefdd9837"}}, ] marker = "\"recommended\" in extras" @@ -2745,38 +2357,8 @@ wheels = [ {name = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}}, {name = "MarkupSafe-3.0.2-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl",hashes = {sha256 = "0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}}, {name = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl",hashes = {sha256 = "9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl",hashes = {sha256 = "6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}}, - {name = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl",hashes = {sha256 = "7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl",hashes = {sha256 = "fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}}, - {name = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl",hashes = {sha256 = "6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl",hashes = {sha256 = "eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl",hashes = {sha256 = "8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}}, - {name = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl",hashes = {sha256 = "6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}}, ] -marker = "\"dev\" in extras" +marker = "\"default\" in dependency_groups or \"dev\" in extras" [packages.tool.pdm] dependencies = [] @@ -2817,13 +2399,6 @@ requires-python = ">=3.8" sdist = {name = "multiprocess-0.70.16.tar.gz", url = "https://files.pythonhosted.org/packages/b5/ae/04f39c5d0d0def03247c2893d6f2b83c136bf3320a2154d7b8858f2ba72d/multiprocess-0.70.16.tar.gz", hashes = {sha256 = "161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1"}} wheels = [ {name = "multiprocess-0.70.16-py312-none-any.whl",url = "https://files.pythonhosted.org/packages/0a/7d/a988f258104dcd2ccf1ed40fdc97e26c4ac351eeaf81d76e266c52d84e2f/multiprocess-0.70.16-py312-none-any.whl",hashes = {sha256 = "fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e"}}, - {name = "multiprocess-0.70.16-py311-none-any.whl",url = "https://files.pythonhosted.org/packages/50/15/b56e50e8debaf439f44befec5b2af11db85f6e0f344c3113ae0be0593a91/multiprocess-0.70.16-py311-none-any.whl",hashes = {sha256 = "af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a"}}, - {name = "multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/ef/76/6e712a2623d146d314f17598df5de7224c85c0060ef63fd95cc15a25b3fa/multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl",hashes = {sha256 = "476887be10e2f59ff183c006af746cb6f1fd0eadcfd4ef49e605cbe2659920ee"}}, - {name = "multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/0f/ab/1e6e8009e380e22254ff539ebe117861e5bdb3bff1fc977920972237c6c7/multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl",hashes = {sha256 = "d951bed82c8f73929ac82c61f01a7b5ce8f3e5ef40f5b52553b4f547ce2b08ec"}}, - {name = "multiprocess-0.70.16-py310-none-any.whl",url = "https://files.pythonhosted.org/packages/bc/f7/7ec7fddc92e50714ea3745631f79bd9c96424cb2702632521028e57d3a36/multiprocess-0.70.16-py310-none-any.whl",hashes = {sha256 = "c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02"}}, - {name = "multiprocess-0.70.16-pp39-pypy39_pp73-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d8/94/8638a89f93c80df329116e6781a060506c7e91e1f4370dc831e9d17a041d/multiprocess-0.70.16-pp39-pypy39_pp73-macosx_10_13_x86_64.whl",hashes = {sha256 = "0dfd078c306e08d46d7a8d06fb120313d87aa43af60d66da43ffff40b44d2f41"}}, - {name = "multiprocess-0.70.16-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/89/21/222066f6bb8d8af287923ae3bd26cf4699a9ce020228ac273caca1de8250/multiprocess-0.70.16-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl",hashes = {sha256 = "e7b9d0f307cd9bd50851afaac0dba2cb6c44449efff697df7c7645f7d3f2be3a"}}, - {name = "multiprocess-0.70.16-py39-none-any.whl",url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl",hashes = {sha256 = "a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3"}}, ] marker = "\"default\" in dependency_groups" @@ -2858,6 +2433,70 @@ marker = "\"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "numba" +version = "0.62.1" +requires-python = ">=3.10" +sdist = {name = "numba-0.62.1.tar.gz", url = "https://files.pythonhosted.org/packages/a3/20/33dbdbfe60e5fd8e3dbfde299d106279a33d9f8308346022316781368591/numba-0.62.1.tar.gz", hashes = {sha256 = "7b774242aa890e34c21200a1fc62e5b5757d5286267e71103257f4e2af0d5161"}} +wheels = [ + {name = "numba-0.62.1-cp313-cp313-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/22/76/501ea2c07c089ef1386868f33dff2978f43f51b854e34397b20fc55e0a58/numba-0.62.1-cp313-cp313-macosx_10_15_x86_64.whl",hashes = {sha256 = "b72489ba8411cc9fdcaa2458d8f7677751e94f0109eeb53e5becfdc818c64afb"}}, + {name = "numba-0.62.1-cp313-cp313-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/80/68/444986ed95350c0611d5c7b46828411c222ce41a0c76707c36425d27ce29/numba-0.62.1-cp313-cp313-macosx_12_0_arm64.whl",hashes = {sha256 = "44a1412095534a26fb5da2717bc755b57da5f3053965128fe3dc286652cc6a92"}}, + {name = "numba-0.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/7e/bf2e3634993d57f95305c7cee4c9c6cb3c9c78404ee7b49569a0dfecfe33/numba-0.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "8c9460b9e936c5bd2f0570e20a0a5909ee6e8b694fd958b210e3bde3a6dba2d7"}}, + {name = "numba-0.62.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e8/b6/8a1723fff71f63bbb1354bdc60a1513a068acc0f5322f58da6f022d20247/numba-0.62.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "728f91a874192df22d74e3fd42c12900b7ce7190b1aad3574c6c61b08313e4c5"}}, + {name = "numba-0.62.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/9c/ec/9d414e7a80d6d1dc4af0e07c6bfe293ce0b04ea4d0ed6c45dad9bd6e72eb/numba-0.62.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "bbf3f88b461514287df66bc8d0307e949b09f2b6f67da92265094e8fa1282dd8"}}, + {name = "numba-0.62.1-cp312-cp312-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/5e/fa/30fa6873e9f821c0ae755915a3ca444e6ff8d6a7b6860b669a3d33377ac7/numba-0.62.1-cp312-cp312-macosx_10_15_x86_64.whl",hashes = {sha256 = "1b743b32f8fa5fff22e19c2e906db2f0a340782caf024477b97801b918cf0494"}}, + {name = "numba-0.62.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a9/d5/504ce8dc46e0dba2790c77e6b878ee65b60fe3e7d6d0006483ef6fde5a97/numba-0.62.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "90fa21b0142bcf08ad8e32a97d25d0b84b1e921bc9423f8dda07d3652860eef6"}}, + {name = "numba-0.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/50/5f/6a802741176c93f2ebe97ad90751894c7b0c922b52ba99a4395e79492205/numba-0.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "6ef84d0ac19f1bf80431347b6f4ce3c39b7ec13f48f233a48c01e2ec06ecbc59"}}, + {name = "numba-0.62.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/7e/df/efd21527d25150c4544eccc9d0b7260a5dec4b7e98b5a581990e05a133c0/numba-0.62.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "9315cc5e441300e0ca07c828a627d92a6802bcbf27c5487f31ae73783c58da53"}}, + {name = "numba-0.62.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/80/44/79bfdab12a02796bf4f1841630355c82b5a69933b1d50eb15c7fa37dabe8/numba-0.62.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "44e3aa6228039992f058f5ebfcfd372c83798e9464297bdad8cc79febcf7891e"}}, +] +marker = "python_version ~= \"3.12\"" + +[packages.tool.pdm] +dependencies = [ + "llvmlite<0.46,>=0.45.0dev0", + "numpy<2.4,>=1.22", +] + +[[packages]] +name = "llvmlite" +version = "0.45.1" +requires-python = ">=3.10" +sdist = {name = "llvmlite-0.45.1.tar.gz", url = "https://files.pythonhosted.org/packages/99/8d/5baf1cef7f9c084fb35a8afbde88074f0d6a727bc63ef764fe0e7543ba40/llvmlite-0.45.1.tar.gz", hashes = {sha256 = "09430bb9d0bb58fc45a45a57c7eae912850bedc095cd0810a57de109c69e1c32"}} +wheels = [ + {name = "llvmlite-0.45.1-cp313-cp313-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/1d/e2/c185bb7e88514d5025f93c6c4092f6120c6cea8fe938974ec9860fb03bbb/llvmlite-0.45.1-cp313-cp313-macosx_10_15_x86_64.whl",hashes = {sha256 = "d9ea9e6f17569a4253515cc01dade70aba536476e3d750b2e18d81d7e670eb15"}}, + {name = "llvmlite-0.45.1-cp313-cp313-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/09/b8/b5437b9ecb2064e89ccf67dccae0d02cd38911705112dd0dcbfa9cd9a9de/llvmlite-0.45.1-cp313-cp313-macosx_12_0_arm64.whl",hashes = {sha256 = "c9f3cadee1630ce4ac18ea38adebf2a4f57a89bd2740ce83746876797f6e0bfb"}}, + {name = "llvmlite-0.45.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/f7/97/ad1a907c0173a90dd4df7228f24a3ec61058bc1a9ff8a0caec20a0cc622e/llvmlite-0.45.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "57c48bf2e1083eedbc9406fb83c4e6483017879714916fe8be8a72a9672c995a"}}, + {name = "llvmlite-0.45.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/32/d8/c99c8ac7a326e9735401ead3116f7685a7ec652691aeb2615aa732b1fc4a/llvmlite-0.45.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "3aa3dfceda4219ae39cf18806c60eeb518c1680ff834b8b311bd784160b9ce40"}}, + {name = "llvmlite-0.45.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/09/56/ed35668130e32dbfad2eb37356793b0a95f23494ab5be7d9bf5cb75850ee/llvmlite-0.45.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "080e6f8d0778a8239cd47686d402cb66eb165e421efa9391366a9b7e5810a38b"}}, + {name = "llvmlite-0.45.1-cp312-cp312-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/e2/7c/82cbd5c656e8991bcc110c69d05913be2229302a92acb96109e166ae31fb/llvmlite-0.45.1-cp312-cp312-macosx_10_15_x86_64.whl",hashes = {sha256 = "28e763aba92fe9c72296911e040231d486447c01d4f90027c8e893d89d49b20e"}}, + {name = "llvmlite-0.45.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/9d/bc/5314005bb2c7ee9f33102c6456c18cc81745d7055155d1218f1624463774/llvmlite-0.45.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "1a53f4b74ee9fd30cb3d27d904dadece67a7575198bd80e687ee76474620735f"}}, + {name = "llvmlite-0.45.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/96/76/0f7154952f037cb320b83e1c952ec4a19d5d689cf7d27cb8a26887d7bbc1/llvmlite-0.45.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "5b3796b1b1e1c14dcae34285d2f4ea488402fbd2c400ccf7137603ca3800864f"}}, + {name = "llvmlite-0.45.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/00/b1/0b581942be2683ceb6862d558979e87387e14ad65a1e4db0e7dd671fa315/llvmlite-0.45.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "779e2f2ceefef0f4368548685f0b4adde34e5f4b457e90391f570a10b348d433"}}, + {name = "llvmlite-0.45.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/33/94/9ba4ebcf4d541a325fd8098ddc073b663af75cc8b065b6059848f7d4dce7/llvmlite-0.45.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "9e6c9949baf25d9aa9cd7cf0f6d011b9ca660dd17f5ba2b23bdbdb77cc86b116"}}, +] +marker = "python_version ~= \"3.12\"" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "pooch" +version = "1.8.2" +requires-python = ">=3.7" +sdist = {name = "pooch-1.8.2.tar.gz", url = "https://files.pythonhosted.org/packages/c6/77/b3d3e00c696c16cf99af81ef7b1f5fe73bd2a307abca41bd7605429fe6e5/pooch-1.8.2.tar.gz", hashes = {sha256 = "76561f0de68a01da4df6af38e9955c4c9d1a5c90da73f7e40276a5728ec83d10"}} +wheels = [ + {name = "pooch-1.8.2-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a8/87/77cc11c7a9ea9fd05503def69e3d18605852cd0d4b0d3b8f15bbeb3ef1d1/pooch-1.8.2-py3-none-any.whl",hashes = {sha256 = "3529a57096f7198778a5ceefd5ac3ef0e4d06a6ddaf9fc2d609b806f25302c47"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "platformdirs>=2.5.0", + "packaging>=20.0", + "requests>=2.19.0", +] + [[packages]] name = "pyarrow" version = "20.0.0" @@ -2891,33 +2530,6 @@ wheels = [ {name = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b2/66/2d976c0c7158fd25591c8ca55aee026e6d5745a021915a1835578707feb3/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e"}}, {name = "pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/31/a9/dfb999c2fc6911201dcbf348247f9cc382a8990f9ab45c12eabfd7243a38/pyarrow-20.0.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a"}}, {name = "pyarrow-20.0.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a0/8e/9adee63dfa3911be2382fb4d92e4b2e7d82610f9d9f668493bebaa2af50f/pyarrow-20.0.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b"}}, - {name = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/47/a2/b7930824181ceadd0c63c1042d01fa4ef63eee233934826a7a2a9af6e463/pyarrow-20.0.0-cp311-cp311-macosx_12_0_arm64.whl",hashes = {sha256 = "24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0"}}, - {name = "pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/9b/18/c765770227d7f5bdfa8a69f64b49194352325c66a5c3bb5e332dfd5867d9/pyarrow-20.0.0-cp311-cp311-macosx_12_0_x86_64.whl",hashes = {sha256 = "95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb"}}, - {name = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/fb/dfb2dfdd3e488bb14f822d7335653092dde150cffc2da97de6e7500681f9/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232"}}, - {name = "pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/58/0d/08a95878d38808051a953e887332d4a76bc06c6ee04351918ee1155407eb/pyarrow-20.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f"}}, - {name = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f3/cd/efa271234dfe38f0271561086eedcad7bc0f2ddd1efba423916ff0883684/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_aarch64.whl",hashes = {sha256 = "7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab"}}, - {name = "pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/46/1f/7f02009bc7fc8955c391defee5348f510e589a020e4b40ca05edcb847854/pyarrow-20.0.0-cp311-cp311-manylinux_2_28_x86_64.whl",hashes = {sha256 = "a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62"}}, - {name = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/4f/92/692c562be4504c262089e86757a9048739fe1acb4024f92d39615e7bab3f/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c"}}, - {name = "pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/a4/ec/9f5c7e7c828d8e0a3c7ef50ee62eca38a7de2fa6eb1b8fa43685c9414fef/pyarrow-20.0.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3"}}, - {name = "pyarrow-20.0.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/54/96/46613131b4727f10fd2ffa6d0d6f02efcc09a0e7374eff3b5771548aa95b/pyarrow-20.0.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc"}}, - {name = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5b/23/77094eb8ee0dbe88441689cb6afc40ac312a1e15d3a7acc0586999518222/pyarrow-20.0.0-cp310-cp310-macosx_12_0_arm64.whl",hashes = {sha256 = "c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7"}}, - {name = "pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/c3/d5/48cc573aff00d62913701d9fac478518f693b30c25f2c157550b0b2565cb/pyarrow-20.0.0-cp310-cp310-macosx_12_0_x86_64.whl",hashes = {sha256 = "d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4"}}, - {name = "pyarrow-20.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/37/df/4099b69a432b5cb412dd18adc2629975544d656df3d7fda6d73c5dba935d/pyarrow-20.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "6415a0d0174487456ddc9beaead703d0ded5966129fa4fd3114d76b5d1c5ceae"}}, - {name = "pyarrow-20.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/4c/27/99922a9ac1c9226f346e3a1e15e63dee6f623ed757ff2893f9d6994a69d3/pyarrow-20.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "15aa1b3b2587e74328a730457068dc6c89e6dcbf438d4369f572af9d320a25ee"}}, - {name = "pyarrow-20.0.0-cp310-cp310-manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/21/d1/71d91b2791b829c9e98f1e0d85be66ed93aff399f80abb99678511847eaa/pyarrow-20.0.0-cp310-cp310-manylinux_2_28_aarch64.whl",hashes = {sha256 = "5605919fbe67a7948c1f03b9f3727d82846c053cd2ce9303ace791855923fd20"}}, - {name = "pyarrow-20.0.0-cp310-cp310-manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/f1/ca/ae10fba419a6e94329707487835ec721f5a95f3ac9168500bcf7aa3813c7/pyarrow-20.0.0-cp310-cp310-manylinux_2_28_x86_64.whl",hashes = {sha256 = "a5704f29a74b81673d266e5ec1fe376f060627c2e42c5c7651288ed4b0db29e9"}}, - {name = "pyarrow-20.0.0-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7a/a6/aba40a2bf01b5d00cf9cd16d427a5da1fad0fb69b514ce8c8292ab80e968/pyarrow-20.0.0-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "00138f79ee1b5aca81e2bdedb91e3739b987245e11fa3c826f9e57c5d102fb75"}}, - {name = "pyarrow-20.0.0-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/93/6b/98b39650cd64f32bf2ec6d627a9bd24fcb3e4e6ea1873c5e1ea8a83b1a18/pyarrow-20.0.0-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "f2d67ac28f57a362f1a2c1e6fa98bfe2f03230f7e15927aecd067433b1e70ce8"}}, - {name = "pyarrow-20.0.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ab/32/340238be1eb5037e7b5de7e640ee22334417239bc347eadefaf8c373936d/pyarrow-20.0.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "4a8b029a07956b8d7bd742ffca25374dd3f634b35e46cc7a7c3fa4c75b297191"}}, - {name = "pyarrow-20.0.0-cp39-cp39-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/10/53/421820fa125138c868729b930d4bc487af2c4b01b1c6104818aab7e98f13/pyarrow-20.0.0-cp39-cp39-macosx_12_0_arm64.whl",hashes = {sha256 = "1bcbe471ef3349be7714261dea28fe280db574f9d0f77eeccc195a2d161fd861"}}, - {name = "pyarrow-20.0.0-cp39-cp39-macosx_12_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/70/fd75e03312b715e90d928fb91ed8d45c9b0520346e5231b1c69293afd4c7/pyarrow-20.0.0-cp39-cp39-macosx_12_0_x86_64.whl",hashes = {sha256 = "a18a14baef7d7ae49247e75641fd8bcbb39f44ed49a9fc4ec2f65d5031aa3b96"}}, - {name = "pyarrow-20.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/c4/e3/21e5758e46219fdedf5e6c800574dd9d17e962e80014cfe08d6d475be863/pyarrow-20.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "cb497649e505dc36542d0e68eca1a3c94ecbe9799cb67b578b55f2441a247fbc"}}, - {name = "pyarrow-20.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/ac/f5/ed6a4c4b11f9215092a35097a985485bb7d879cb79d93d203494e8604f4e/pyarrow-20.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "11529a2283cb1f6271d7c23e4a8f9f8b7fd173f7360776b668e509d712a02eec"}}, - {name = "pyarrow-20.0.0-cp39-cp39-manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/44/e5/466a63668ba25788ee8d38d55f853a60469ae7ad1cda343db9f3f45e0b0a/pyarrow-20.0.0-cp39-cp39-manylinux_2_28_aarch64.whl",hashes = {sha256 = "6fc1499ed3b4b57ee4e090e1cea6eb3584793fe3d1b4297bbf53f09b434991a5"}}, - {name = "pyarrow-20.0.0-cp39-cp39-manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/e8/d7/4c4d4e4cf6e53e16a519366dfe9223ee4a7a38e6e28c1c0d372b38ba3fe7/pyarrow-20.0.0-cp39-cp39-manylinux_2_28_x86_64.whl",hashes = {sha256 = "db53390eaf8a4dab4dbd6d93c85c5cf002db24902dbff0ca7d988beb5c9dd15b"}}, - {name = "pyarrow-20.0.0-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/07/d5/79effb32585b7c18897d3047a2163034f3f9c944d12f7b2fd8df6a2edc70/pyarrow-20.0.0-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "851c6a8260ad387caf82d2bbf54759130534723e37083111d4ed481cb253cc0d"}}, - {name = "pyarrow-20.0.0-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/09/5c/f707603552c058b2e9129732de99a67befb1f13f008cc58856304a62c38b/pyarrow-20.0.0-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "e22f80b97a271f0a7d9cd07394a7d348f80d3ac63ed7cc38b6d1b696ab3b2619"}}, - {name = "pyarrow-20.0.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/26/cc/1eb6a01c1bbc787f596c270c46bcd2273e35154a84afcb1d0cb4cc72457e/pyarrow-20.0.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "9965a050048ab02409fb7cbbefeedba04d3d67f2cc899eff505cc084345959ca"}}, ] marker = "\"default\" in dependency_groups" @@ -2941,11 +2553,6 @@ wheels = [ {name = "pycryptodomex-3.23.0-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/ca/18/4ca89ac737230b52ac8ffaca42f9c6f1fd07c81a6cd821e91af79db60632/pycryptodomex-3.23.0-cp313-cp313t-win32.whl",hashes = {sha256 = "a9d446e844f08299236780f2efa9898c818fe7e02f17263866b8550c7d5fb328"}}, {name = "pycryptodomex-3.23.0-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/73/34/13e01c322db027682e00986873eca803f11c56ade9ba5bbf3225841ea2d4/pycryptodomex-3.23.0-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "bc65bdd9fc8de7a35a74cab1c898cab391a4add33a8fe740bda00f5976ca4708"}}, {name = "pycryptodomex-3.23.0-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/54/68/9504c8796b1805d58f4425002bcca20f12880e6fa4dc2fc9a668705c7a08/pycryptodomex-3.23.0-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "c885da45e70139464f082018ac527fdaad26f1657a99ee13eecdce0f0ca24ab4"}}, - {name = "pycryptodomex-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/f3/b8/3e76d948c3c4ac71335bbe75dac53e154b40b0f8f1f022dfa295257a0c96/pycryptodomex-3.23.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "ebfff755c360d674306e5891c564a274a47953562b42fb74a5c25b8fc1fb1cb5"}}, - {name = "pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/6a/cf/80f4297a4820dfdfd1c88cf6c4666a200f204b3488103d027b5edd9176ec/pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "eca54f4bb349d45afc17e3011ed4264ef1cc9e266699874cdd1349c504e64798"}}, - {name = "pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d1/42/1e969ee0ad19fe3134b0e1b856c39bd0b70d47a4d0e81c2a8b05727394c9/pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "4f2596e643d4365e14d0879dc5aafe6355616c61c2176009270f3048f6d9a61f"}}, - {name = "pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/6e/c3/1de4f7631fea8a992a44ba632aa40e0008764c0fb9bf2854b0acf78c2cf2/pycryptodomex-3.23.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "fdfac7cda115bca3a5abb2f9e43bc2fb66c2b65ab074913643803ca7083a79ea"}}, - {name = "pycryptodomex-3.23.0-pp310-pypy310_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f2/5f/af7da8e6f1e42b52f44a24d08b8e4c726207434e2593732d39e7af5e7256/pycryptodomex-3.23.0-pp310-pypy310_pp73-win_amd64.whl",hashes = {sha256 = "14c37aaece158d0ace436f76a7bb19093db3b4deade9797abfc39ec6cd6cc2fe"}}, {name = "pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_universal2.whl",url = "https://files.pythonhosted.org/packages/dd/9c/1a8f35daa39784ed8adf93a694e7e5dc15c23c741bbda06e1d45f8979e9e/pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_universal2.whl",hashes = {sha256 = "06698f957fe1ab229a99ba2defeeae1c09af185baa909a31a5d1f9d42b1aaed6"}}, {name = "pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/7a/62/f5221a191a97157d240cf6643747558759126c76ee92f29a3f4aee3197a5/pycryptodomex-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl",hashes = {sha256 = "b2c2537863eccef2d41061e82a881dcabb04944c5c06c5aa7110b577cc487545"}}, {name = "pycryptodomex-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/8c/fd/5a054543c8988d4ed7b612721d7e78a4b9bf36bc3c5ad45ef45c22d0060e/pycryptodomex-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "43c446e2ba8df8889e0e16f02211c25b4934898384c1ec1ec04d7889c0333587"}}, @@ -3018,6 +2625,55 @@ marker = "\"default\" in dependency_groups" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "sanic-routing" +version = "23.12.0" +sdist = {name = "sanic-routing-23.12.0.tar.gz", url = "https://files.pythonhosted.org/packages/d1/5c/2a7edd14fbccca3719a8d680951d4b25f986752c781c61ccf156a6d1ebff/sanic-routing-23.12.0.tar.gz", hashes = {sha256 = "1dcadc62c443e48c852392dba03603f9862b6197fc4cba5bbefeb1ace0848b04"}} +wheels = [ + {name = "sanic_routing-23.12.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/cf/e3/3425c9a8773807ac2c01d6a56c8521733f09b627e5827e733c5cd36b9ac5/sanic_routing-23.12.0-py3-none-any.whl",hashes = {sha256 = "1558a72afcb9046ed3134a5edae02fc1552cff08f0fff2e8d5de0877ea43ed73"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "scikit-learn" +version = "1.7.2" +requires-python = ">=3.10" +sdist = {name = "scikit_learn-1.7.2.tar.gz", url = "https://files.pythonhosted.org/packages/98/c2/a7855e41c9d285dfe86dc50b250978105dce513d6e459ea66a6aeb0e1e0c/scikit_learn-1.7.2.tar.gz", hashes = {sha256 = "20e9e49ecd130598f1ca38a1d85090e1a600147b9c02fa6f15d69cb53d968fda"}} +wheels = [ + {name = "scikit_learn-1.7.2-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/82/dee5acf66837852e8e68df6d8d3a6cb22d3df997b733b032f513d95205b7/scikit_learn-1.7.2-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "fa8f63940e29c82d1e67a45d5297bdebbcb585f5a5a50c4914cc2e852ab77f33"}}, + {name = "scikit_learn-1.7.2-cp314-cp314-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/3c/30/9029e54e17b87cb7d50d51a5926429c683d5b4c1732f0507a6c3bed9bf65/scikit_learn-1.7.2-cp314-cp314-macosx_12_0_arm64.whl",hashes = {sha256 = "f95dc55b7902b91331fa4e5845dd5bde0580c9cd9612b1b2791b7e80c3d32615"}}, + {name = "scikit_learn-1.7.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/60/18/4a52c635c71b536879f4b971c2cedf32c35ee78f48367885ed8025d1f7ee/scikit_learn-1.7.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "9656e4a53e54578ad10a434dc1f993330568cfee176dff07112b8785fb413106"}}, + {name = "scikit_learn-1.7.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/99/7e/290362f6ab582128c53445458a5befd471ed1ea37953d5bcf80604619250/scikit_learn-1.7.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "96dc05a854add0e50d3f47a1ef21a10a595016da5b007c7d9cd9d0bffd1fcc61"}}, + {name = "scikit_learn-1.7.2-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/8e/87/24f541b6d62b1794939ae6422f8023703bbf6900378b2b34e0b4384dfefd/scikit_learn-1.7.2-cp314-cp314-win_amd64.whl",hashes = {sha256 = "bb24510ed3f9f61476181e4db51ce801e2ba37541def12dc9333b946fc7a9cf8"}}, + {name = "scikit_learn-1.7.2-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/ae/93/a3038cb0293037fd335f77f31fe053b89c72f17b1c8908c576c29d953e84/scikit_learn-1.7.2-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "0b7dacaa05e5d76759fb071558a8b5130f4845166d88654a0f9bdf3eb57851b7"}}, + {name = "scikit_learn-1.7.2-cp313-cp313-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/40/dd/9a88879b0c1104259136146e4742026b52df8540c39fec21a6383f8292c7/scikit_learn-1.7.2-cp313-cp313-macosx_12_0_arm64.whl",hashes = {sha256 = "abebbd61ad9e1deed54cca45caea8ad5f79e1b93173dece40bb8e0c658dbe6fe"}}, + {name = "scikit_learn-1.7.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/46/af/c5e286471b7d10871b811b72ae794ac5fe2989c0a2df07f0ec723030f5f5/scikit_learn-1.7.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "502c18e39849c0ea1a5d681af1dbcf15f6cce601aebb657aabbfe84133c1907f"}}, + {name = "scikit_learn-1.7.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/f1/fd/df59faa53312d585023b2da27e866524ffb8faf87a68516c23896c718320/scikit_learn-1.7.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "7a4c328a71785382fe3fe676a9ecf2c86189249beff90bf85e22bdb7efaf9ae0"}}, + {name = "scikit_learn-1.7.2-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a7/c7/03000262759d7b6f38c836ff9d512f438a70d8a8ddae68ee80de72dcfb63/scikit_learn-1.7.2-cp313-cp313-win_amd64.whl",hashes = {sha256 = "63a9afd6f7b229aad94618c01c252ce9e6fa97918c5ca19c9a17a087d819440c"}}, + {name = "scikit_learn-1.7.2-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/55/87/ef5eb1f267084532c8e4aef98a28b6ffe7425acbfd64b5e2f2e066bc29b3/scikit_learn-1.7.2-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "9acb6c5e867447b4e1390930e3944a005e2cb115922e693c08a323421a6966e8"}}, + {name = "scikit_learn-1.7.2-cp313-cp313t-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/93/f8/6c1e3fc14b10118068d7938878a9f3f4e6d7b74a8ddb1e5bed65159ccda8/scikit_learn-1.7.2-cp313-cp313t-macosx_12_0_arm64.whl",hashes = {sha256 = "2a41e2a0ef45063e654152ec9d8bcfc39f7afce35b08902bfe290c2498a67a6a"}}, + {name = "scikit_learn-1.7.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/83/87/066cafc896ee540c34becf95d30375fe5cbe93c3b75a0ee9aa852cd60021/scikit_learn-1.7.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "98335fb98509b73385b3ab2bd0639b1f610541d3988ee675c670371d6a87aa7c"}}, + {name = "scikit_learn-1.7.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/9c/2b/4903e1ccafa1f6453b1ab78413938c8800633988c838aa0be386cbb33072/scikit_learn-1.7.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "191e5550980d45449126e23ed1d5e9e24b2c68329ee1f691a3987476e115e09c"}}, + {name = "scikit_learn-1.7.2-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b5/aa/8444be3cfb10451617ff9d177b3c190288f4563e6c50ff02728be67ad094/scikit_learn-1.7.2-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "57dc4deb1d3762c75d685507fbd0bc17160144b2f2ba4ccea5dc285ab0d0e973"}}, + {name = "scikit_learn-1.7.2-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/a7/aa/3996e2196075689afb9fce0410ebdb4a09099d7964d061d7213700204409/scikit_learn-1.7.2-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "8d91a97fa2b706943822398ab943cde71858a50245e31bc71dba62aab1d60a96"}}, + {name = "scikit_learn-1.7.2-cp312-cp312-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/43/5d/779320063e88af9c4a7c2cf463ff11c21ac9c8bd730c4a294b0000b666c9/scikit_learn-1.7.2-cp312-cp312-macosx_12_0_arm64.whl",hashes = {sha256 = "acbc0f5fd2edd3432a22c69bed78e837c70cf896cd7993d71d51ba6708507476"}}, + {name = "scikit_learn-1.7.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/5c/d0/0c577d9325b05594fdd33aa970bf53fb673f051a45496842caee13cfd7fe/scikit_learn-1.7.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "e5bf3d930aee75a65478df91ac1225ff89cd28e9ac7bd1196853a9229b6adb0b"}}, + {name = "scikit_learn-1.7.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/82/70/8bf44b933837ba8494ca0fc9a9ab60f1c13b062ad0197f60a56e2fc4c43e/scikit_learn-1.7.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "b4d6e9deed1a47aca9fe2f267ab8e8fe82ee20b4526b2c0cd9e135cea10feb44"}}, + {name = "scikit_learn-1.7.2-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c6/99/ed35197a158f1fdc2fe7c3680e9c70d0128f662e1fee4ed495f4b5e13db0/scikit_learn-1.7.2-cp312-cp312-win_amd64.whl",hashes = {sha256 = "6088aa475f0785e01bcf8529f55280a3d7d298679f50c0bb70a2364a82d0b290"}}, +] +marker = "python_version ~= \"3.12\"" + +[packages.tool.pdm] +dependencies = [ + "numpy>=1.22.0", + "scipy>=1.8.0", + "joblib>=1.2.0", + "threadpoolctl>=3.1.0", +] + [[packages]] name = "snowballstemmer" version = "3.0.1" @@ -3031,6 +2687,111 @@ marker = "\"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "soundfile" +version = "0.13.1" +sdist = {name = "soundfile-0.13.1.tar.gz", url = "https://files.pythonhosted.org/packages/e1/41/9b873a8c055582859b239be17902a85339bec6a30ad162f98c9b0288a2cc/soundfile-0.13.1.tar.gz", hashes = {sha256 = "b2c68dab1e30297317080a5b43df57e302584c49e2942defdde0acccc53f0e5b"}} +wheels = [ + {name = "soundfile-0.13.1-py2.py3-none-any.whl",url = "https://files.pythonhosted.org/packages/64/28/e2a36573ccbcf3d57c00626a21fe51989380636e821b341d36ccca0c1c3a/soundfile-0.13.1-py2.py3-none-any.whl",hashes = {sha256 = "a23c717560da2cf4c7b5ae1142514e0fd82d6bbd9dfc93a50423447142f2c445"}}, + {name = "soundfile-0.13.1-py2.py3-none-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/ea/ab/73e97a5b3cc46bba7ff8650a1504348fa1863a6f9d57d7001c6b67c5f20e/soundfile-0.13.1-py2.py3-none-macosx_10_9_x86_64.whl",hashes = {sha256 = "82dc664d19831933fe59adad199bf3945ad06d84bc111a5b4c0d3089a5b9ec33"}}, + {name = "soundfile-0.13.1-py2.py3-none-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/a0/e5/58fd1a8d7b26fc113af244f966ee3aecf03cb9293cb935daaddc1e455e18/soundfile-0.13.1-py2.py3-none-macosx_11_0_arm64.whl",hashes = {sha256 = "743f12c12c4054921e15736c6be09ac26b3b3d603aef6fd69f9dde68748f2593"}}, + {name = "soundfile-0.13.1-py2.py3-none-manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/58/ae/c0e4a53d77cf6e9a04179535766b3321b0b9ced5f70522e4caf9329f0046/soundfile-0.13.1-py2.py3-none-manylinux_2_28_aarch64.whl",hashes = {sha256 = "9c9e855f5a4d06ce4213f31918653ab7de0c5a8d8107cd2427e44b42df547deb"}}, + {name = "soundfile-0.13.1-py2.py3-none-manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/57/5e/70bdd9579b35003a489fc850b5047beeda26328053ebadc1fb60f320f7db/soundfile-0.13.1-py2.py3-none-manylinux_2_28_x86_64.whl",hashes = {sha256 = "03267c4e493315294834a0870f31dbb3b28a95561b80b134f0bd3cf2d5f0e618"}}, + {name = "soundfile-0.13.1-py2.py3-none-win32.whl",url = "https://files.pythonhosted.org/packages/fe/df/8c11dc4dfceda14e3003bb81a0d0edcaaf0796dd7b4f826ea3e532146bba/soundfile-0.13.1-py2.py3-none-win32.whl",hashes = {sha256 = "c734564fab7c5ddf8e9be5bf70bab68042cd17e9c214c06e365e20d64f9a69d5"}}, + {name = "soundfile-0.13.1-py2.py3-none-win_amd64.whl",url = "https://files.pythonhosted.org/packages/14/e9/6b761de83277f2f02ded7e7ea6f07828ec78e4b229b80e4ca55dd205b9dc/soundfile-0.13.1-py2.py3-none-win_amd64.whl",hashes = {sha256 = "1e70a05a0626524a69e9f0f4dd2ec174b4e9567f4d8b6c11d38b5c289be36ee9"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "cffi>=1.0", + "numpy", +] + +[[packages]] +name = "cffi" +version = "2.0.0" +requires-python = ">=3.9" +sdist = {name = "cffi-2.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hashes = {sha256 = "44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}} +wheels = [ + {name = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}}, + {name = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}}, + {name = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}}, + {name = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}}, + {name = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}}, + {name = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}}, + {name = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}}, + {name = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}}, + {name = "cffi-2.0.0-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl",hashes = {sha256 = "087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}}, + {name = "cffi-2.0.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}}, + {name = "cffi-2.0.0-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl",hashes = {sha256 = "dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}}, + {name = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}}, + {name = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}}, + {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}}, + {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}}, + {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}}, + {name = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}}, + {name = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}}, + {name = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}}, + {name = "cffi-2.0.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl",hashes = {sha256 = "1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}}, + {name = "cffi-2.0.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}}, + {name = "cffi-2.0.0-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}}, + {name = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}}, + {name = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}}, + {name = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}}, + {name = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}}, + {name = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}}, + {name = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}}, + {name = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}}, + {name = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}}, + {name = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}}, + {name = "cffi-2.0.0-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl",hashes = {sha256 = "74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}}, + {name = "cffi-2.0.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}}, + {name = "cffi-2.0.0-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl",hashes = {sha256 = "256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}}, + {name = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}}, + {name = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}}, + {name = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl",hashes = {sha256 = "21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}}, + {name = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}}, + {name = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",hashes = {sha256 = "1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}}, + {name = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl",url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl",hashes = {sha256 = "81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}}, + {name = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}}, + {name = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}}, + {name = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}}, + {name = "cffi-2.0.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl",hashes = {sha256 = "da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}}, + {name = "cffi-2.0.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}}, + {name = "cffi-2.0.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "pycparser; implementation_name != \"PyPy\"", +] + +[[packages]] +name = "soxr" +version = "1.0.0" +requires-python = ">=3.9" +sdist = {name = "soxr-1.0.0.tar.gz", url = "https://files.pythonhosted.org/packages/42/7e/f4b461944662ad75036df65277d6130f9411002bfb79e9df7dff40a31db9/soxr-1.0.0.tar.gz", hashes = {sha256 = "e07ee6c1d659bc6957034f4800c60cb8b98de798823e34d2a2bba1caa85a4509"}} +wheels = [ + {name = "soxr-1.0.0-cp314-cp314t-macosx_10_14_x86_64.whl",url = "https://files.pythonhosted.org/packages/99/77/d3b3c25b4f1b1aa4a73f669355edcaee7a52179d0c50407697200a0e55b9/soxr-1.0.0-cp314-cp314t-macosx_10_14_x86_64.whl",hashes = {sha256 = "392a5c70c04eb939c9c176bd6f654dec9a0eaa9ba33d8f1024ed63cf68cdba0a"}}, + {name = "soxr-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/8a/ee/3ca73e18781bb2aff92b809f1c17c356dfb9a1870652004bd432e79afbfa/soxr-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "fdc41a1027ba46777186f26a8fba7893be913383414135577522da2fcc684490"}}, + {name = "soxr-1.0.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/bd/f0/eea8b5f587a2531657dc5081d2543a5a845f271a3bea1c0fdee5cebde021/soxr-1.0.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "449acd1dfaf10f0ce6dfd75c7e2ef984890df94008765a6742dafb42061c1a24"}}, + {name = "soxr-1.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/64/59/2430a48c705565eb09e78346950b586f253a11bd5313426ced3ecd9b0feb/soxr-1.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "38b35c99e408b8f440c9376a5e1dd48014857cd977c117bdaa4304865ae0edd0"}}, + {name = "soxr-1.0.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3c/1b/f84a2570a74094e921bbad5450b2a22a85d58585916e131d9b98029c3e69/soxr-1.0.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "a39b519acca2364aa726b24a6fd55acf29e4c8909102e0b858c23013c38328e5"}}, + {name = "soxr-1.0.0-cp312-abi3-macosx_10_14_x86_64.whl",url = "https://files.pythonhosted.org/packages/c5/c7/f92b81f1a151c13afb114f57799b86da9330bec844ea5a0d3fe6a8732678/soxr-1.0.0-cp312-abi3-macosx_10_14_x86_64.whl",hashes = {sha256 = "abecf4e39017f3fadb5e051637c272ae5778d838e5c3926a35db36a53e3a607f"}}, + {name = "soxr-1.0.0-cp312-abi3-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ff/1d/c945fea9d83ea1f2be9d116b3674dbaef26ed090374a77c394b31e3b083b/soxr-1.0.0-cp312-abi3-macosx_11_0_arm64.whl",hashes = {sha256 = "e973d487ee46aa8023ca00a139db6e09af053a37a032fe22f9ff0cc2e19c94b4"}}, + {name = "soxr-1.0.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/b5/80/10640970998a1d2199bef6c4d92205f36968cddaf3e4d0e9fe35ddd405bd/soxr-1.0.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "e8ce273cca101aff3d8c387db5a5a41001ba76ef1837883438d3c652507a9ccc"}}, + {name = "soxr-1.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/b1/87/2726603c13c2126cb8ded9e57381b7377f4f0df6ba4408e1af5ddbfdc3dd/soxr-1.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "e8f2a69686f2856d37823bbb7b78c3d44904f311fe70ba49b893af11d6b6047b"}}, + {name = "soxr-1.0.0-cp312-abi3-win_amd64.whl",url = "https://files.pythonhosted.org/packages/ce/04/530252227f4d0721a5524a936336485dfb429bb206a66baf8e470384f4a2/soxr-1.0.0-cp312-abi3-win_amd64.whl",hashes = {sha256 = "2a3b77b115ae7c478eecdbd060ed4f61beda542dfb70639177ac263aceda42a2"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "numpy", +] + [[packages]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" @@ -3057,6 +2818,116 @@ marker = "\"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "sympy" +version = "1.14.0" +requires-python = ">=3.9" +sdist = {name = "sympy-1.14.0.tar.gz", url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hashes = {sha256 = "d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517"}} +wheels = [ + {name = "sympy-1.14.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl",hashes = {sha256 = "e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "mpmath<1.4,>=1.1.0", +] + +[[packages]] +name = "mpmath" +version = "1.3.0" +sdist = {name = "mpmath-1.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hashes = {sha256 = "7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}} +wheels = [ + {name = "mpmath-1.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl",hashes = {sha256 = "a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "threadpoolctl" +version = "3.6.0" +requires-python = ">=3.9" +sdist = {name = "threadpoolctl-3.6.0.tar.gz", url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hashes = {sha256 = "8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e"}} +wheels = [ + {name = "threadpoolctl-3.6.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl",hashes = {sha256 = "43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "tracerite" +version = "1.1.3" +sdist = {name = "tracerite-1.1.3.tar.gz", url = "https://files.pythonhosted.org/packages/27/b2/37b825b881f23bc56384c3142214ccbe5d9de7e7c5fe3d155fa032738b98/tracerite-1.1.3.tar.gz", hashes = {sha256 = "119fc006f240aa03fffb41cf99cf82fda5c0449c7d4b6fe42c6340403578b31e"}} +wheels = [ + {name = "tracerite-1.1.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/e6/bf/c65d36ec5a93048dd55b3247be26059970daad72263e35ecace2f3188b2c/tracerite-1.1.3-py3-none-any.whl",hashes = {sha256 = "811d8e2e0fb563b77340eebe2e9f7b324acfe01e09ea58db8bcaecb24327c823"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "html5tagger>=1.2.1", +] + +[[packages]] +name = "ujson" +version = "5.11.0" +requires-python = ">=3.9" +sdist = {name = "ujson-5.11.0.tar.gz", url = "https://files.pythonhosted.org/packages/43/d9/3f17e3c5773fb4941c68d9a37a47b1a79c9649d6c56aefbed87cc409d18a/ujson-5.11.0.tar.gz", hashes = {sha256 = "e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0"}} +wheels = [ + {name = "ujson-5.11.0-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/28/08/4518146f4984d112764b1dfa6fb7bad691c44a401adadaa5e23ccd930053/ujson-5.11.0-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302"}}, + {name = "ujson-5.11.0-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/29/37/2107b9a62168867a692654d8766b81bd2fd1e1ba13e2ec90555861e02b0c/ujson-5.11.0-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d"}}, + {name = "ujson-5.11.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/9b/f8/25583c70f83788edbe3ca62ce6c1b79eff465d78dec5eb2b2b56b3e98b33/ujson-5.11.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638"}}, + {name = "ujson-5.11.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl",url = "https://files.pythonhosted.org/packages/ed/ca/19b3a632933a09d696f10dc1b0dfa1d692e65ad507d12340116ce4f67967/ujson-5.11.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl",hashes = {sha256 = "e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c"}}, + {name = "ujson-5.11.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/55/7a/4572af5324ad4b2bfdd2321e898a527050290147b4ea337a79a0e4e87ec7/ujson-5.11.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba"}}, + {name = "ujson-5.11.0-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/7b/71/a2b8c19cf4e1efe53cf439cdf7198ac60ae15471d2f1040b490c1f0f831f/ujson-5.11.0-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018"}}, + {name = "ujson-5.11.0-cp314-cp314-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/7a/3e/7b98668cba3bb3735929c31b999b374ebc02c19dfa98dfebaeeb5c8597ca/ujson-5.11.0-cp314-cp314-musllinux_1_2_i686.whl",hashes = {sha256 = "090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840"}}, + {name = "ujson-5.11.0-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/a1/ea/8870f208c20b43571a5c409ebb2fe9b9dba5f494e9e60f9314ac01ea8f78/ujson-5.11.0-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c"}}, + {name = "ujson-5.11.0-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/63/b6/c0e6607e37fa47929920a685a968c6b990a802dec65e9c5181e97845985d/ujson-5.11.0-cp314-cp314-win32.whl",hashes = {sha256 = "1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac"}}, + {name = "ujson-5.11.0-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/4e/56/f4fe86b4c9000affd63e9219e59b222dc48b01c534533093e798bf617a7e/ujson-5.11.0-cp314-cp314-win_amd64.whl",hashes = {sha256 = "849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629"}}, + {name = "ujson-5.11.0-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/0a/f3/669437f0280308db4783b12a6d88c00730b394327d8334cc7a32ef218e64/ujson-5.11.0-cp314-cp314-win_arm64.whl",hashes = {sha256 = "e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764"}}, + {name = "ujson-5.11.0-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/6e/cd/e9809b064a89fe5c4184649adeb13c1b98652db3f8518980b04227358574/ujson-5.11.0-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433"}}, + {name = "ujson-5.11.0-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/1b/be/ae26a6321179ebbb3a2e2685b9007c71bcda41ad7a77bbbe164005e956fc/ujson-5.11.0-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3"}}, + {name = "ujson-5.11.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ae/e9/fb4a220ee6939db099f4cfeeae796ecb91e7584ad4d445d4ca7f994a9135/ujson-5.11.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823"}}, + {name = "ujson-5.11.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl",url = "https://files.pythonhosted.org/packages/bd/f8/fc4b952b8f5fea09ea3397a0bd0ad019e474b204cabcb947cead5d4d1ffc/ujson-5.11.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl",hashes = {sha256 = "a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9"}}, + {name = "ujson-5.11.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/e5/af5491dfda4f8b77e24cf3da68ee0d1552f99a13e5c622f4cef1380925c3/ujson-5.11.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076"}}, + {name = "ujson-5.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c4/09/0945349dd41f25cc8c38d78ace49f14c5052c5bbb7257d2f466fa7bdb533/ujson-5.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c"}}, + {name = "ujson-5.11.0-cp314-cp314t-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/49/44/8e04496acb3d5a1cbee3a54828d9652f67a37523efa3d3b18a347339680a/ujson-5.11.0-cp314-cp314t-musllinux_1_2_i686.whl",hashes = {sha256 = "b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746"}}, + {name = "ujson-5.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/64/ae/4bc825860d679a0f208a19af2f39206dfd804ace2403330fdc3170334a2f/ujson-5.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef"}}, + {name = "ujson-5.11.0-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/30/ed/5a057199fb0a5deabe0957073a1c1c1c02a3e99476cd03daee98ea21fa57/ujson-5.11.0-cp314-cp314t-win32.whl",hashes = {sha256 = "aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5"}}, + {name = "ujson-5.11.0-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/aa/03/b19c6176bdf1dc13ed84b886e99677a52764861b6cc023d5e7b6ebda249d/ujson-5.11.0-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec"}}, + {name = "ujson-5.11.0-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/5d/ca/a0413a3874b2dc1708b8796ca895bf363292f9c70b2e8ca482b7dbc0259d/ujson-5.11.0-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab"}}, + {name = "ujson-5.11.0-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/1c/ec/2de9dd371d52c377abc05d2b725645326c4562fc87296a8907c7bcdf2db7/ujson-5.11.0-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53"}}, + {name = "ujson-5.11.0-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5b/a4/f611f816eac3a581d8a4372f6967c3ed41eddbae4008d1d77f223f1a4e0a/ujson-5.11.0-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752"}}, + {name = "ujson-5.11.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e9/c5/c161940967184de96f5cbbbcce45b562a4bf851d60f4c677704b1770136d/ujson-5.11.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50"}}, + {name = "ujson-5.11.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl",url = "https://files.pythonhosted.org/packages/2b/d6/c7b2444238f5b2e2d0e3dab300b9ddc3606e4b1f0e4bed5a48157cebc792/ujson-5.11.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl",hashes = {sha256 = "4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a"}}, + {name = "ujson-5.11.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/fe/a3/292551f936d3d02d9af148f53e1bc04306b00a7cf1fcbb86fa0d1c887242/ujson-5.11.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03"}}, + {name = "ujson-5.11.0-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/90/a6/82cfa70448831b1a9e73f882225980b5c689bf539ec6400b31656a60ea46/ujson-5.11.0-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701"}}, + {name = "ujson-5.11.0-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/84/5c/96e2266be50f21e9b27acaee8ca8f23ea0b85cb998c33d4f53147687839b/ujson-5.11.0-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60"}}, + {name = "ujson-5.11.0-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/8d/20/78abe3d808cf3bb3e76f71fca46cd208317bf461c905d79f0d26b9df20f1/ujson-5.11.0-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328"}}, + {name = "ujson-5.11.0-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/d8/50/8856e24bec5e2fc7f775d867aeb7a3f137359356200ac44658f1f2c834b2/ujson-5.11.0-cp313-cp313-win32.whl",hashes = {sha256 = "8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241"}}, + {name = "ujson-5.11.0-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/5b/d8/1baee0f4179a4d0f5ce086832147b6cc9b7731c24ca08e14a3fdb8d39c32/ujson-5.11.0-cp313-cp313-win_amd64.whl",hashes = {sha256 = "34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0"}}, + {name = "ujson-5.11.0-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/a9/8c/6d85ef5be82c6d66adced3ec5ef23353ed710a11f70b0b6a836878396334/ujson-5.11.0-cp313-cp313-win_arm64.whl",hashes = {sha256 = "ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9"}}, + {name = "ujson-5.11.0-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/b9/ef/a9cb1fce38f699123ff012161599fb9f2ff3f8d482b4b18c43a2dc35073f/ujson-5.11.0-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702"}}, + {name = "ujson-5.11.0-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/b1/05/dba51a00eb30bd947791b173766cbed3492269c150a7771d2750000c965f/ujson-5.11.0-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d"}}, + {name = "ujson-5.11.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/03/3c/fd11a224f73fbffa299fb9644e425f38b38b30231f7923a088dd513aabb4/ujson-5.11.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80"}}, + {name = "ujson-5.11.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl",url = "https://files.pythonhosted.org/packages/55/b9/405103cae24899df688a3431c776e00528bd4799e7d68820e7ebcf824f92/ujson-5.11.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl",hashes = {sha256 = "fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc"}}, + {name = "ujson-5.11.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",url = "https://files.pythonhosted.org/packages/17/7b/2dcbc2bbfdbf68f2368fb21ab0f6735e872290bb604c75f6e06b81edcb3f/ujson-5.11.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl",hashes = {sha256 = "8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c"}}, + {name = "ujson-5.11.0-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/d1/71/fea2ca18986a366c750767b694430d5ded6b20b6985fddca72f74af38a4c/ujson-5.11.0-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5"}}, + {name = "ujson-5.11.0-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/a3/bb/d4220bd7532eac6288d8115db51710fa2d7d271250797b0bfba9f1e755af/ujson-5.11.0-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b"}}, + {name = "ujson-5.11.0-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/80/47/226e540aa38878ce1194454385701d82df538ccb5ff8db2cf1641dde849a/ujson-5.11.0-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc"}}, + {name = "ujson-5.11.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/7e/81/546042f0b23c9040d61d46ea5ca76f0cc5e0d399180ddfb2ae976ebff5b5/ujson-5.11.0-cp312-cp312-win32.whl",hashes = {sha256 = "be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88"}}, + {name = "ujson-5.11.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/44/1b/27c05dc8c9728f44875d74b5bfa948ce91f6c33349232619279f35c6e817/ujson-5.11.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f"}}, + {name = "ujson-5.11.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/22/2d/37b6557c97c3409c202c838aa9c960ca3896843b4295c4b7bb2bbd260664/ujson-5.11.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6"}}, +] +marker = "sys_platform != \"win32\" and implementation_name == \"cpython\" and \"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "wcwidth" version = "0.2.13" @@ -3071,6 +2942,41 @@ dependencies = [ "backports-functools-lru-cache>=1.2.1; python_version < \"3.2\"", ] +[[packages]] +name = "websockets" +version = "15.0.1" +requires-python = ">=3.9" +sdist = {name = "websockets-15.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hashes = {sha256 = "82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"}} +wheels = [ + {name = "websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931"}}, + {name = "websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675"}}, + {name = "websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151"}}, + {name = "websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22"}}, + {name = "websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f"}}, + {name = "websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8"}}, + {name = "websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375"}}, + {name = "websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl",hashes = {sha256 = "756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d"}}, + {name = "websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4"}}, + {name = "websockets-15.0.1-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl",hashes = {sha256 = "ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa"}}, + {name = "websockets-15.0.1-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl",hashes = {sha256 = "e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561"}}, + {name = "websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3"}}, + {name = "websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665"}}, + {name = "websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2"}}, + {name = "websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215"}}, + {name = "websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5"}}, + {name = "websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65"}}, + {name = "websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe"}}, + {name = "websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl",hashes = {sha256 = "5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4"}}, + {name = "websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597"}}, + {name = "websockets-15.0.1-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl",hashes = {sha256 = "c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9"}}, + {name = "websockets-15.0.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"}}, + {name = "websockets-15.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl",hashes = {sha256 = "f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f"}}, +] +marker = "\"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "win32-setctime" version = "1.2.0" @@ -3085,14 +2991,54 @@ marker = "sys_platform == \"win32\" and \"default\" in dependency_groups" dependencies = [] [[packages]] -name = "zipp" -version = "3.23.0" -requires-python = ">=3.9" -sdist = {name = "zipp-3.23.0.tar.gz", url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hashes = {sha256 = "a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}} -wheels = [ - {name = "zipp-3.23.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl",hashes = {sha256 = "071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}}, +name = "wrapt" +version = "1.17.3" +requires-python = ">=3.8" +sdist = {name = "wrapt-1.17.3.tar.gz", url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hashes = {sha256 = "f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}} +wheels = [ + {name = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl",hashes = {sha256 = "cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"}}, + {name = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl",hashes = {sha256 = "e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"}}, + {name = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl",hashes = {sha256 = "5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"}}, + {name = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"}}, + {name = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"}}, + {name = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl",hashes = {sha256 = "373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"}}, + {name = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl",hashes = {sha256 = "d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"}}, + {name = "wrapt-1.17.3-cp314-cp314-win32.whl",url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl",hashes = {sha256 = "fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"}}, + {name = "wrapt-1.17.3-cp314-cp314-win_amd64.whl",url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl",hashes = {sha256 = "e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"}}, + {name = "wrapt-1.17.3-cp314-cp314-win_arm64.whl",url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl",hashes = {sha256 = "507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"}}, + {name = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl",hashes = {sha256 = "ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"}}, + {name = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"}}, + {name = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"}}, + {name = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"}}, + {name = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"}}, + {name = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"}}, + {name = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"}}, + {name = "wrapt-1.17.3-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl",hashes = {sha256 = "41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"}}, + {name = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"}}, + {name = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"}}, + {name = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl",hashes = {sha256 = "a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"}}, + {name = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl",hashes = {sha256 = "54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"}}, + {name = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl",hashes = {sha256 = "16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"}}, + {name = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"}}, + {name = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"}}, + {name = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl",hashes = {sha256 = "423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"}}, + {name = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl",hashes = {sha256 = "e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"}}, + {name = "wrapt-1.17.3-cp313-cp313-win32.whl",url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl",hashes = {sha256 = "53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"}}, + {name = "wrapt-1.17.3-cp313-cp313-win_amd64.whl",url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl",hashes = {sha256 = "1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"}}, + {name = "wrapt-1.17.3-cp313-cp313-win_arm64.whl",url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl",hashes = {sha256 = "7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"}}, + {name = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl",hashes = {sha256 = "ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"}}, + {name = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl",hashes = {sha256 = "9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"}}, + {name = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl",hashes = {sha256 = "6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"}}, + {name = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"}}, + {name = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"}}, + {name = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"}}, + {name = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"}}, + {name = "wrapt-1.17.3-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl",hashes = {sha256 = "4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"}}, + {name = "wrapt-1.17.3-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl",hashes = {sha256 = "e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"}}, + {name = "wrapt-1.17.3-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl",hashes = {sha256 = "604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"}}, + {name = "wrapt-1.17.3-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl",hashes = {sha256 = "7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}}, ] -marker = "python_full_version < \"3.10.2\" and python_version >= \"3.9\" and \"dev\" in extras" +marker = "\"default\" in dependency_groups" [packages.tool.pdm] dependencies = [] @@ -3156,6 +3102,19 @@ dependencies = [ "uc-micro-py", ] +[[packages]] +name = "networkx" +version = "3.5" +requires-python = ">=3.11" +sdist = {name = "networkx-3.5.tar.gz", url = "https://files.pythonhosted.org/packages/6c/4f/ccdb8ad3a38e583f214547fd2f7ff1fc160c43a75af88e6aec213404b96a/networkx-3.5.tar.gz", hashes = {sha256 = "d4c6f9cf81f52d69230866796b82afbccdec3db7ae4fbd1b65ea750feed50037"}} +wheels = [ + {name = "networkx-3.5-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl",hashes = {sha256 = "0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec"}}, +] +marker = "python_version ~= \"3.12\"" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "pandas" version = "2.3.1" @@ -3182,27 +3141,6 @@ wheels = [ {name = "pandas-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/5b/14/cec7760d7c9507f11c97d64f29022e12a6cc4fc03ac694535e89f88ad2ec/pandas-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8"}}, {name = "pandas-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/50/b9/6e2d2c6728ed29fb3d4d4d302504fb66f1a543e37eb2e43f352a86365cdf/pandas-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl",hashes = {sha256 = "ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679"}}, {name = "pandas-2.3.1-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/80/a5/3a92893e7399a691bad7664d977cb5e7c81cf666c81f89ea76ba2bff483d/pandas-2.3.1-cp312-cp312-win_amd64.whl",hashes = {sha256 = "ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8"}}, - {name = "pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/76/1c/ccf70029e927e473a4476c00e0d5b32e623bff27f0402d0a92b7fc29bb9f/pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b"}}, - {name = "pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ec/d3/3c37cb724d76a841f14b8f5fe57e5e3645207cc67370e4f84717e8bb7657/pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f"}}, - {name = "pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/8a/4c/367c98854a1251940edf54a4df0826dcacfb987f9068abf3e3064081a382/pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85"}}, - {name = "pandas-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/07/5f/63760ff107bcf5146eee41b38b3985f9055e710a72fdd637b791dea3495c/pandas-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d"}}, - {name = "pandas-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/15/53/f31a9b4dfe73fe4711c3a609bd8e60238022f48eacedc257cd13ae9327a7/pandas-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678"}}, - {name = "pandas-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/e0/94/6fce6bf85b5056d065e0a7933cba2616dcb48596f7ba3c6341ec4bcc529d/pandas-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299"}}, - {name = "pandas-2.3.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/c8/7b/bdcb1ed8fccb63d04bdb7635161d0ec26596d92c9d7a6cce964e7876b6c1/pandas-2.3.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab"}}, - {name = "pandas-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/c4/ca/aa97b47287221fa37a49634532e520300088e290b20d690b21ce3e448143/pandas-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "22c2e866f7209ebc3a8f08d75766566aae02bcc91d196935a1d9e59c7b990ac9"}}, - {name = "pandas-2.3.1-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/80/bf/7938dddc5f01e18e573dcfb0f1b8c9357d9b5fa6ffdee6e605b92efbdff2/pandas-2.3.1-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "3583d348546201aff730c8c47e49bc159833f971c2899d6097bce68b9112a4f1"}}, - {name = "pandas-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/ee/2f/9af748366763b2a494fed477f88051dbf06f56053d5c00eba652697e3f94/pandas-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "0f951fbb702dacd390561e0ea45cdd8ecfa7fb56935eb3dd78e306c19104b9b0"}}, - {name = "pandas-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/2c/95/79ab37aa4c25d1e7df953dde407bb9c3e4ae47d154bc0dd1692f3a6dcf8c/pandas-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "cd05b72ec02ebfb993569b4931b2e16fbb4d6ad6ce80224a3ee838387d83a191"}}, - {name = "pandas-2.3.1-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/75/a7/d65e5d8665c12c3c6ff5edd9709d5836ec9b6f80071b7f4a718c6106e86e/pandas-2.3.1-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1b916a627919a247d865aed068eb65eb91a344b13f5b57ab9f610b7716c92de1"}}, - {name = "pandas-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/65/f3/4c1dbd754dbaa79dbf8b537800cb2fa1a6e534764fef50ab1f7533226c5c/pandas-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "fe67dc676818c186d5a3d5425250e40f179c2a89145df477dd82945eaea89e97"}}, - {name = "pandas-2.3.1-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3f/d6/d7f5777162aa9b48ec3910bca5a58c9b5927cfd9cfde3aa64322f5ba4b9f/pandas-2.3.1-cp310-cp310-win_amd64.whl",hashes = {sha256 = "2eb789ae0274672acbd3c575b0598d213345660120a257b47b5dafdc618aec83"}}, - {name = "pandas-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/6e/21/ecf2df680982616459409b09962a8c2065330c7151dc6538069f3b634acf/pandas-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "4645f770f98d656f11c69e81aeb21c6fca076a44bed3dcbb9396a4311bc7f6d8"}}, - {name = "pandas-2.3.1-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/1e/1a/dcb50e44b75419e96b276c9fb023b0f147b3c411be1cd517492aa2a184d4/pandas-2.3.1-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "342e59589cc454aaff7484d75b816a433350b3d7964d7847327edda4d532a2e3"}}, - {name = "pandas-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/2d/55/66cd2b679f6a27398380eac7574bc24746128f74626a3c02b978ea00e5ce/pandas-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "1d12f618d80379fde6af007f65f0c25bd3e40251dbd1636480dfffce2cf1e6da"}}, - {name = "pandas-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/ae/1c/5b9b263c80fd5e231b77df6f78cd7426d1d4ad3a4e858e85b7b3d93d0e9c/pandas-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "dd71c47a911da120d72ef173aeac0bf5241423f9bfea57320110a978457e069e"}}, - {name = "pandas-2.3.1-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/f7/74/7e817b31413fbb96366ea327d43d1926a9c48c58074e27e094e2839a0e36/pandas-2.3.1-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "09e3b1587f0f3b0913e21e8b32c3119174551deb4a4eba4a89bc7377947977e7"}}, - {name = "pandas-2.3.1-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/1f/0f/bc0a44b47eba2f22ae4235719a573d552ef7ad76ed3ea39ae62d554e040b/pandas-2.3.1-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "2323294c73ed50f612f67e2bf3ae45aea04dce5690778e08a09391897f35ff88"}}, - {name = "pandas-2.3.1-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fa/cb/6c32f8fadefa4314b740fbe8f74f6a02423bd1549e7c930826df35ac3c1b/pandas-2.3.1-cp39-cp39-win_amd64.whl",hashes = {sha256 = "b4b0de34dc8499c2db34000ef8baad684cfa4cbd836ecee05f323ebfba348c7d"}}, ] marker = "\"default\" in dependency_groups" @@ -3269,6 +3207,19 @@ marker = "\"default\" in dependency_groups" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "pycparser" +version = "2.23" +requires-python = ">=3.8" +sdist = {name = "pycparser-2.23.tar.gz", url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hashes = {sha256 = "78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}} +wheels = [ + {name = "pycparser-2.23-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl",hashes = {sha256 = "e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}}, +] +marker = "implementation_name != \"PyPy\" and \"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + [[packages]] name = "pyproject-hooks" version = "1.2.0" @@ -3321,33 +3272,6 @@ wheels = [ {name = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl",hashes = {sha256 = "b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d"}}, {name = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl",hashes = {sha256 = "e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}}, {name = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl",hashes = {sha256 = "0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl",url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl",hashes = {sha256 = "4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl",hashes = {sha256 = "d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl",url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl",hashes = {sha256 = "cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl",hashes = {sha256 = "bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}}, - {name = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl",hashes = {sha256 = "a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl",url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl",hashes = {sha256 = "11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl",hashes = {sha256 = "a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl",url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl",hashes = {sha256 = "22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl",hashes = {sha256 = "932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl",hashes = {sha256 = "3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}}, - {name = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl",hashes = {sha256 = "ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/e5/46/ccdef7a84ad745c37cb3d9a81790f28fbc9adf9c237dba682017b123294e/ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl",hashes = {sha256 = "fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/29/09/932360f30ad1b7b79f08757e0a6fb8c5392a52cdcc182779158fe66d25ac/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl",hashes = {sha256 = "bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a2/2a/5b27602e7a4344c1334e26bf4739746206b7a60a8acdba33a61473468b73/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/da/1c/23497017c554fc06ff5701b29355522cff850f626337fff35d9ab352cb18/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl",url = "https://files.pythonhosted.org/packages/68/e6/f3d4ff3223f9ea49c3b7169ec0268e42bd49f87c70c0e3e853895e4a7ae2/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl",hashes = {sha256 = "d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/84/62/ead07043527642491e5011b143f44b81ef80f1025a96069b7210e0f2f0f3/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl",hashes = {sha256 = "e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/52/b3/fe4d84446f7e4887e3bea7ceff0a7df23790b5ed625f830e79ace88ebefb/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/6e/b3/7feb99a00bfaa5c6868617bb7651308afde85e5a0b23cd187fe5de65feeb/ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl",hashes = {sha256 = "beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}}, - {name = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/93/07/de635108684b7a5bb06e432b0930c5a04b6c59efe73bd966d8db3cc208f2/ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl",hashes = {sha256 = "040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}}, ] marker = "platform_python_implementation == \"CPython\" and python_version < \"3.14\" and python_version >= \"3.9\" and \"dev\" in extras" @@ -3406,6 +3330,107 @@ marker = "\"dev\" in extras" [packages.tool.pdm] dependencies = [] +[[packages]] +name = "standard-aifc" +version = "3.13.0" +sdist = {name = "standard_aifc-3.13.0.tar.gz", url = "https://files.pythonhosted.org/packages/c4/53/6050dc3dde1671eb3db592c13b55a8005e5040131f7509cef0215212cb84/standard_aifc-3.13.0.tar.gz", hashes = {sha256 = "64e249c7cb4b3daf2fdba4e95721f811bde8bdfc43ad9f936589b7bb2fae2e43"}} +wheels = [ + {name = "standard_aifc-3.13.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/c3/52/5fbb203394cc852334d1575cc020f6bcec768d2265355984dfd361968f36/standard_aifc-3.13.0-py3-none-any.whl",hashes = {sha256 = "f7ae09cc57de1224a0dd8e3eb8f73830be7c3d0bc485de4c1f82b4a7f645ac66"}}, +] +marker = "python_version ~= \"3.13\"" + +[packages.tool.pdm] +dependencies = [ + "standard-chunk; python_version >= \"3.13\"", + "audioop-lts; python_version >= \"3.13\"", +] + +[[packages]] +name = "audioop-lts" +version = "0.2.2" +requires-python = ">=3.13" +sdist = {name = "audioop_lts-0.2.2.tar.gz", url = "https://files.pythonhosted.org/packages/38/53/946db57842a50b2da2e0c1e34bd37f36f5aadba1a929a3971c5d7841dbca/audioop_lts-0.2.2.tar.gz", hashes = {sha256 = "64d0c62d88e67b98a1a5e71987b7aa7b5bcffc7dcee65b635823dbdd0a8dbbd0"}} +wheels = [ + {name = "audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/5c/73/413b5a2804091e2c7d5def1d618e4837f1cb82464e230f827226278556b7/audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_universal2.whl",hashes = {sha256 = "f9ee9b52f5f857fbaf9d605a360884f034c92c1c23021fb90b2e39b8e64bede6"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/ae/8c/daa3308dc6593944410c2c68306a5e217f5c05b70a12e70228e7dd42dc5c/audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_x86_64.whl",hashes = {sha256 = "49ee1a41738a23e98d98b937a0638357a2477bc99e61b0f768a8f654f45d9b7a"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4e/86/c2e0f627168fcf61781a8f72cab06b228fe1da4b9fa4ab39cfb791b5836b/audioop_lts-0.2.2-cp314-cp314t-macosx_11_0_arm64.whl",hashes = {sha256 = "5b00be98ccd0fc123dcfad31d50030d25fcf31488cde9e61692029cd7394733b"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/c7/bd/35dce665255434f54e5307de39e31912a6f902d4572da7c37582809de14f/audioop_lts-0.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "a6d2e0f9f7a69403e388894d4ca5ada5c47230716a03f2847cfc7bd1ecb589d6"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/2d/d2/deeb9f51def1437b3afa35aeb729d577c04bcd89394cb56f9239a9f50b6f/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "f9b0b8a03ef474f56d1a842af1a2e01398b8f7654009823c6d9e0ecff4d5cfbf"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/76/3b/09f8b35b227cee28cc8231e296a82759ed80c1a08e349811d69773c48426/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "2b267b70747d82125f1a021506565bdc5609a2b24bcb4773c16d79d2bb260bbd"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/0b/15/05b48a935cf3b130c248bfdbdea71ce6437f5394ee8533e0edd7cfd93d5e/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "0337d658f9b81f4cd0fdb1f47635070cc084871a3d4646d9de74fdf4e7c3d24a"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/83/80/186b7fce6d35b68d3d739f228dc31d60b3412105854edb975aa155a58339/audioop_lts-0.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "167d3b62586faef8b6b2275c3218796b12621a60e43f7e9d5845d627b9c9b80e"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/49/89/c78cc5ac6cb5828f17514fb12966e299c850bc885e80f8ad94e38d450886/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "0d9385e96f9f6da847f4d571ce3cb15b5091140edf3db97276872647ce37efd7"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/4c/4b/6401888d0c010e586c2ca50fce4c903d70a6bb55928b16cfbdfd957a13da/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "48159d96962674eccdca9a3df280e864e8ac75e40a577cc97c5c42667ffabfc5"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/de/f8/c874ca9bb447dae0e2ef2e231f6c4c2b0c39e31ae684d2420b0f9e97ee68/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "8fefe5868cd082db1186f2837d64cfbfa78b548ea0d0543e9b28935ccce81ce9"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/3e/c0/0323e66f3daebc13fd46b36b30c3be47e3fc4257eae44f1e77eb828c703f/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_s390x.whl",hashes = {sha256 = "58cf54380c3884fb49fdd37dfb7a772632b6701d28edd3e2904743c5e1773602"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/98/6b/acc7734ac02d95ab791c10c3f17ffa3584ccb9ac5c18fd771c638ed6d1f5/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "088327f00488cdeed296edd9215ca159f3a5a5034741465789cad403fcf4bec0"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-win32.whl",url = "https://files.pythonhosted.org/packages/13/c3/c3dc3f564ce6877ecd2a05f8d751b9b27a8c320c2533a98b0c86349778d0/audioop_lts-0.2.2-cp314-cp314t-win32.whl",hashes = {sha256 = "068aa17a38b4e0e7de771c62c60bbca2455924b67a8814f3b0dee92b5820c0b3"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/72/bb/b4608537e9ffcb86449091939d52d24a055216a36a8bf66b936af8c3e7ac/audioop_lts-0.2.2-cp314-cp314t-win_amd64.whl",hashes = {sha256 = "a5bf613e96f49712073de86f20dbdd4014ca18efd4d34ed18c75bd808337851b"}}, + {name = "audioop_lts-0.2.2-cp314-cp314t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/f6/22/91616fe707a5c5510de2cac9b046a30defe7007ba8a0c04f9c08f27df312/audioop_lts-0.2.2-cp314-cp314t-win_arm64.whl",hashes = {sha256 = "b492c3b040153e68b9fdaff5913305aaaba5bb433d8a7f73d5cf6a64ed3cc1dd"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/58/a7/0a764f77b5c4ac58dc13c01a580f5d32ae8c74c92020b961556a43e26d02/audioop_lts-0.2.2-cp313-cp313t-macosx_10_13_universal2.whl",hashes = {sha256 = "73f80bf4cd5d2ca7814da30a120de1f9408ee0619cc75da87d0641273d202a09"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/aa/ed/ebebedde1a18848b085ad0fa54b66ceb95f1f94a3fc04f1cd1b5ccb0ed42/audioop_lts-0.2.2-cp313-cp313t-macosx_10_13_x86_64.whl",hashes = {sha256 = "106753a83a25ee4d6f473f2be6b0966fc1c9af7e0017192f5531a3e7463dce58"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/cb/6e/11ca8c21af79f15dbb1c7f8017952ee8c810c438ce4e2b25638dfef2b02c/audioop_lts-0.2.2-cp313-cp313t-macosx_11_0_arm64.whl",hashes = {sha256 = "fbdd522624141e40948ab3e8cdae6e04c748d78710e9f0f8d4dae2750831de19"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/84/52/0022f93d56d85eec5da6b9da6a958a1ef09e80c39f2cc0a590c6af81dcbb/audioop_lts-0.2.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "143fad0311e8209ece30a8dbddab3b65ab419cbe8c0dde6e8828da25999be911"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/87/1d/48a889855e67be8718adbc7a01f3c01d5743c325453a5e81cf3717664aad/audioop_lts-0.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "dfbbc74ec68a0fd08cfec1f4b5e8cca3d3cd7de5501b01c4b5d209995033cde9"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/98/a6/94b7213190e8077547ffae75e13ed05edc488653c85aa5c41472c297d295/audioop_lts-0.2.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "cfcac6aa6f42397471e4943e0feb2244549db5c5d01efcd02725b96af417f3fe"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/e9/e9/78450d7cb921ede0cfc33426d3a8023a3bda755883c95c868ee36db8d48d/audioop_lts-0.2.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "752d76472d9804ac60f0078c79cdae8b956f293177acd2316cd1e15149aee132"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/4f/e2/cd5439aad4f3e34ae1ee852025dc6aa8f67a82b97641e390bf7bd9891d3e/audioop_lts-0.2.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "83c381767e2cc10e93e40281a04852facc4cd9334550e0f392f72d1c0a9c5753"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/68/4b/9d853e9076c43ebba0d411e8d2aa19061083349ac695a7d082540bad64d0/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c0022283e9556e0f3643b7c3c03f05063ca72b3063291834cca43234f20c60bb"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/58/26/4bae7f9d2f116ed5593989d0e521d679b0d583973d203384679323d8fa85/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "a2d4f1513d63c795e82948e1305f31a6d530626e5f9f2605408b300ae6095093"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/b2/67/a9f4fb3e250dda9e9046f8866e9fa7d52664f8985e445c6b4ad6dfb55641/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_riscv64.whl",hashes = {sha256 = "c9c8e68d8b4a56fda8c025e538e639f8c5953f5073886b596c93ec9b620055e7"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/70/f7/3de86562db0121956148bcb0fe5b506615e3bcf6e63c4357a612b910765a/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_s390x.whl",hashes = {sha256 = "96f19de485a2925314f5020e85911fb447ff5fbef56e8c7c6927851b95533a1c"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/f1/32/fd772bf9078ae1001207d2df1eef3da05bea611a87dd0e8217989b2848fa/audioop_lts-0.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl",hashes = {sha256 = "e541c3ef484852ef36545f66209444c48b28661e864ccadb29daddb6a4b8e5f5"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-win32.whl",url = "https://files.pythonhosted.org/packages/4f/41/affea7181592ab0ab560044632571a38edaf9130b84928177823fbf3176a/audioop_lts-0.2.2-cp313-cp313t-win32.whl",hashes = {sha256 = "d5e73fa573e273e4f2e5ff96f9043858a5e9311e94ffefd88a3186a910c70917"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-win_amd64.whl",url = "https://files.pythonhosted.org/packages/28/2b/0372842877016641db8fc54d5c88596b542eec2f8f6c20a36fb6612bf9ee/audioop_lts-0.2.2-cp313-cp313t-win_amd64.whl",hashes = {sha256 = "9191d68659eda01e448188f60364c7763a7ca6653ed3f87ebb165822153a8547"}}, + {name = "audioop_lts-0.2.2-cp313-cp313t-win_arm64.whl",url = "https://files.pythonhosted.org/packages/ee/ca/baf2b9cc7e96c179bb4a54f30fcd83e6ecb340031bde68f486403f943768/audioop_lts-0.2.2-cp313-cp313t-win_arm64.whl",hashes = {sha256 = "c174e322bb5783c099aaf87faeb240c8d210686b04bd61dfd05a8e5a83d88969"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-macosx_10_13_universal2.whl",url = "https://files.pythonhosted.org/packages/de/d4/94d277ca941de5a507b07f0b592f199c22454eeaec8f008a286b3fbbacd6/audioop_lts-0.2.2-cp313-abi3-macosx_10_13_universal2.whl",hashes = {sha256 = "fd3d4602dc64914d462924a08c1a9816435a2155d74f325853c1f1ac3b2d9800"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-macosx_10_13_x86_64.whl",url = "https://files.pythonhosted.org/packages/f8/5a/656d1c2da4b555920ce4177167bfeb8623d98765594af59702c8873f60ec/audioop_lts-0.2.2-cp313-abi3-macosx_10_13_x86_64.whl",hashes = {sha256 = "550c114a8df0aafe9a05442a1162dfc8fec37e9af1d625ae6060fed6e756f303"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/1b/83/ea581e364ce7b0d41456fb79d6ee0ad482beda61faf0cab20cbd4c63a541/audioop_lts-0.2.2-cp313-abi3-macosx_11_0_arm64.whl",hashes = {sha256 = "9a13dc409f2564de15dd68be65b462ba0dde01b19663720c68c1140c782d1d75"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",url = "https://files.pythonhosted.org/packages/b8/3b/e8964210b5e216e5041593b7d33e97ee65967f17c282e8510d19c666dab4/audioop_lts-0.2.2-cp313-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl",hashes = {sha256 = "51c916108c56aa6e426ce611946f901badac950ee2ddaf302b7ed35d9958970d"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",url = "https://files.pythonhosted.org/packages/c7/2e/0a1c52faf10d51def20531a59ce4c706cb7952323b11709e10de324d6493/audioop_lts-0.2.2-cp313-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",hashes = {sha256 = "47eba38322370347b1c47024defbd36374a211e8dd5b0dcbce7b34fdb6f8847b"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",url = "https://files.pythonhosted.org/packages/75/e8/cd95eef479656cb75ab05dfece8c1f8c395d17a7c651d88f8e6e291a63ab/audioop_lts-0.2.2-cp313-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl",hashes = {sha256 = "ba7c3a7e5f23e215cb271516197030c32aef2e754252c4c70a50aaff7031a2c8"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",url = "https://files.pythonhosted.org/packages/5c/1e/a0c42570b74f83efa5cca34905b3eef03f7ab09fe5637015df538a7f3345/audioop_lts-0.2.2-cp313-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl",hashes = {sha256 = "def246fe9e180626731b26e89816e79aae2276f825420a07b4a647abaa84becc"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",url = "https://files.pythonhosted.org/packages/50/d5/8a0ae607ca07dbb34027bac8db805498ee7bfecc05fd2c148cc1ed7646e7/audioop_lts-0.2.2-cp313-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl",hashes = {sha256 = "e160bf9df356d841bb6c180eeeea1834085464626dc1b68fa4e1d59070affdc3"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/12/17/0d28c46179e7910bfb0bb62760ccb33edb5de973052cb2230b662c14ca2e/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_aarch64.whl",hashes = {sha256 = "4b4cd51a57b698b2d06cb9993b7ac8dfe89a3b2878e96bc7948e9f19ff51dba6"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/84/ba/bd5d3806641564f2024e97ca98ea8f8811d4e01d9b9f9831474bc9e14f9e/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "4a53aa7c16a60a6857e6b0b165261436396ef7293f8b5c9c828a3a203147ed4a"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_riscv64.whl",url = "https://files.pythonhosted.org/packages/f9/5e/435ce8d5642f1f7679540d1e73c1c42d933331c0976eb397d1717d7f01a3/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_riscv64.whl",hashes = {sha256 = "3fc38008969796f0f689f1453722a0f463da1b8a6fbee11987830bfbb664f623"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/ae/3b/b909e76b606cbfd53875693ec8c156e93e15a1366a012f0b7e4fb52d3c34/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_s390x.whl",hashes = {sha256 = "15ab25dd3e620790f40e9ead897f91e79c0d3ce65fe193c8ed6c26cffdd24be7"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/30/e7/8f1603b4572d79b775f2140d7952f200f5e6c62904585d08a01f0a70393a/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_x86_64.whl",hashes = {sha256 = "03f061a1915538fd96272bac9551841859dbb2e3bf73ebe4a23ef043766f5449"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-win32.whl",url = "https://files.pythonhosted.org/packages/b5/96/c37846df657ccdda62ba1ae2b6534fa90e2e1b1742ca8dcf8ebd38c53801/audioop_lts-0.2.2-cp313-abi3-win32.whl",hashes = {sha256 = "3bcddaaf6cc5935a300a8387c99f7a7fbbe212a11568ec6cf6e4bc458c048636"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-win_amd64.whl",url = "https://files.pythonhosted.org/packages/34/a5/9d78fdb5b844a83da8a71226c7bdae7cc638861085fff7a1d707cb4823fa/audioop_lts-0.2.2-cp313-abi3-win_amd64.whl",hashes = {sha256 = "a2c2a947fae7d1062ef08c4e369e0ba2086049a5e598fda41122535557012e9e"}}, + {name = "audioop_lts-0.2.2-cp313-abi3-win_arm64.whl",url = "https://files.pythonhosted.org/packages/34/25/20d8fde083123e90c61b51afb547bb0ea7e77bab50d98c0ab243d02a0e43/audioop_lts-0.2.2-cp313-abi3-win_arm64.whl",hashes = {sha256 = "5f93a5db13927a37d2d09637ccca4b2b6b48c19cd9eda7b17a2e9f77edee6a6f"}}, +] +marker = "python_version ~= \"3.13\"" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "standard-chunk" +version = "3.13.0" +sdist = {name = "standard_chunk-3.13.0.tar.gz", url = "https://files.pythonhosted.org/packages/43/06/ce1bb165c1f111c7d23a1ad17204d67224baa69725bb6857a264db61beaf/standard_chunk-3.13.0.tar.gz", hashes = {sha256 = "4ac345d37d7e686d2755e01836b8d98eda0d1a3ee90375e597ae43aaf064d654"}} +wheels = [ + {name = "standard_chunk-3.13.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/7a/90/a5c1084d87767d787a6caba615aa50dc587229646308d9420c960cb5e4c0/standard_chunk-3.13.0-py3-none-any.whl",hashes = {sha256 = "17880a26c285189c644bd5bd8f8ed2bdb795d216e3293e6dbe55bbd848e2982c"}}, +] +marker = "python_version ~= \"3.13\"" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "standard-sunau" +version = "3.13.0" +sdist = {name = "standard_sunau-3.13.0.tar.gz", url = "https://files.pythonhosted.org/packages/66/e3/ce8d38cb2d70e05ffeddc28bb09bad77cfef979eb0a299c9117f7ed4e6a9/standard_sunau-3.13.0.tar.gz", hashes = {sha256 = "b319a1ac95a09a2378a8442f403c66f4fd4b36616d6df6ae82b8e536ee790908"}} +wheels = [ + {name = "standard_sunau-3.13.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/34/ae/e3707f6c1bc6f7aa0df600ba8075bfb8a19252140cd595335be60e25f9ee/standard_sunau-3.13.0-py3-none-any.whl",hashes = {sha256 = "53af624a9529c41062f4c2fd33837f297f3baa196b0cfceffea6555654602622"}}, +] +marker = "python_version ~= \"3.13\"" + +[packages.tool.pdm] +dependencies = [ + "audioop-lts; python_version >= \"3.13\"", +] + [[packages]] name = "uc-micro-py" version = "1.0.3" @@ -3455,61 +3480,6 @@ wheels = [ {name = "xxhash-3.5.0-cp312-cp312-win32.whl",url = "https://files.pythonhosted.org/packages/78/e3/dd76659b2811b3fd06892a8beb850e1996b63e9235af5a86ea348f053e9e/xxhash-3.5.0-cp312-cp312-win32.whl",hashes = {sha256 = "f7b58d1fd3551b8c80a971199543379be1cee3d0d409e1f6d8b01c1a2eebf1f8"}}, {name = "xxhash-3.5.0-cp312-cp312-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d9/6b/1c443fe6cfeb4ad1dcf231cdec96eb94fb43d6498b4469ed8b51f8b59a37/xxhash-3.5.0-cp312-cp312-win_amd64.whl",hashes = {sha256 = "fa0cafd3a2af231b4e113fba24a65d7922af91aeb23774a8b78228e6cd785e3e"}}, {name = "xxhash-3.5.0-cp312-cp312-win_arm64.whl",url = "https://files.pythonhosted.org/packages/0f/eb/04405305f290173acc0350eba6d2f1a794b57925df0398861a20fbafa415/xxhash-3.5.0-cp312-cp312-win_arm64.whl",hashes = {sha256 = "586886c7e89cb9828bcd8a5686b12e161368e0064d040e225e72607b43858ba2"}}, - {name = "xxhash-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/b8/c7/afed0f131fbda960ff15eee7f304fa0eeb2d58770fade99897984852ef23/xxhash-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1"}}, - {name = "xxhash-3.5.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/8c/0c/7c3bc6d87e5235672fcc2fb42fd5ad79fe1033925f71bf549ee068c7d1ca/xxhash-3.5.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8"}}, - {name = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/04/9e/01067981d98069eec1c20201f8c145367698e9056f8bc295346e4ea32dd1/xxhash-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166"}}, - {name = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/d4/09/d4996de4059c3ce5342b6e1e6a77c9d6c91acce31f6ed979891872dd162b/xxhash-3.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7"}}, - {name = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/62/f5/6d2dc9f8d55a7ce0f5e7bfef916e67536f01b85d32a9fbf137d4cadbee38/xxhash-3.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623"}}, - {name = "xxhash-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/72/9256303f10e41ab004799a4aa74b80b3c5977d6383ae4550548b24bd1971/xxhash-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a"}}, - {name = "xxhash-3.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",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",hashes = {sha256 = "685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88"}}, - {name = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/53/ad/7fa1a109663366de42f724a1cdb8e796a260dbac45047bce153bc1e18abf/xxhash-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c"}}, - {name = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/35/02/137300e24203bf2b2a49b48ce898ecce6fd01789c0fcd9c686c0a002d129/xxhash-3.5.0-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2"}}, - {name = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/23/03/aeceb273933d7eee248c4322b98b8e971f06cc3880e5f7602c94e5578af5/xxhash-3.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084"}}, - {name = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/e3/64/ed82ec09489474cbb35c716b189ddc1521d8b3de12b1b5ab41ce7f70253c/xxhash-3.5.0-cp311-cp311-musllinux_1_2_s390x.whl",hashes = {sha256 = "a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d"}}, - {name = "xxhash-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/71/43/6db4c02dcb488ad4e03bc86d70506c3d40a384ee73c9b5c93338eb1f3c23/xxhash-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839"}}, - {name = "xxhash-3.5.0-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/22/6d/db4abec29e7a567455344433d095fdb39c97db6955bb4a2c432e486b4d28/xxhash-3.5.0-cp311-cp311-win32.whl",hashes = {sha256 = "109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da"}}, - {name = "xxhash-3.5.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/52/1c/fa3b61c0cf03e1da4767213672efe186b1dfa4fc901a4a694fb184a513d1/xxhash-3.5.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58"}}, - {name = "xxhash-3.5.0-cp311-cp311-win_arm64.whl",url = "https://files.pythonhosted.org/packages/6b/8e/9e6fc572acf6e1cc7ccb01973c213f895cb8668a9d4c2b58a99350da14b7/xxhash-3.5.0-cp311-cp311-win_arm64.whl",hashes = {sha256 = "c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3"}}, - {name = "xxhash-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/bb/8a/0e9feca390d512d293afd844d31670e25608c4a901e10202aa98785eab09/xxhash-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "ece616532c499ee9afbb83078b1b952beffef121d989841f7f4b3dc5ac0fd212"}}, - {name = "xxhash-3.5.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/16/e6/be5aa49580cd064a18200ab78e29b88b1127e1a8c7955eb8ecf81f2626eb/xxhash-3.5.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "3171f693dbc2cef6477054a665dc255d996646b4023fe56cb4db80e26f4cc520"}}, - {name = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/20/ee/b8a99ebbc6d1113b3a3f09e747fa318c3cde5b04bd9c197688fadf0eeae8/xxhash-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "7c5d3e570ef46adaf93fc81b44aca6002b5a4d8ca11bd0580c07eac537f36680"}}, - {name = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/58/62/15d10582ef159283a5c2b47f6d799fc3303fe3911d5bb0bcc820e1ef7ff4/xxhash-3.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "7cb29a034301e2982df8b1fe6328a84f4b676106a13e9135a0d7e0c3e9f806da"}}, - {name = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/23/41/61202663ea9b1bd8e53673b8ec9e2619989353dba8cfb68e59a9cbd9ffe3/xxhash-3.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "5d0d307d27099bb0cbeea7260eb39ed4fdb99c5542e21e94bb6fd29e49c57a23"}}, - {name = "xxhash-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/f2/07/d9a3059f702dec5b3b703737afb6dda32f304f6e9da181a229dafd052c29/xxhash-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "c0342aafd421795d740e514bc9858ebddfc705a75a8c5046ac56d85fe97bf196"}}, - {name = "xxhash-3.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",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",hashes = {sha256 = "3dbbd9892c5ebffeca1ed620cf0ade13eb55a0d8c84e0751a6653adc6ac40d0c"}}, - {name = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/b1/08/32d558ce23e1e068453c39aed7b3c1cdc690c177873ec0ca3a90d5808765/xxhash-3.5.0-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "4cc2d67fdb4d057730c75a64c5923abfa17775ae234a71b0200346bfb0a7f482"}}, - {name = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/3f/d4/2b971e2d2b0a61045f842b622ef11e94096cf1f12cd448b6fd426e80e0e2/xxhash-3.5.0-cp310-cp310-musllinux_1_2_i686.whl",hashes = {sha256 = "ec28adb204b759306a3d64358a5e5c07d7b1dd0ccbce04aa76cb9377b7b70296"}}, - {name = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/19/ae/6a6438864a8c4c39915d7b65effd85392ebe22710412902487e51769146d/xxhash-3.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "1328f6d8cca2b86acb14104e381225a3d7b42c92c4b86ceae814e5c400dbb415"}}, - {name = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/48/7d/b3c27c27d1fc868094d02fe4498ccce8cec9fcc591825c01d6bcb0b4fc49/xxhash-3.5.0-cp310-cp310-musllinux_1_2_s390x.whl",hashes = {sha256 = "8d47ebd9f5d9607fd039c1fbf4994e3b071ea23eff42f4ecef246ab2b7334198"}}, - {name = "xxhash-3.5.0-cp310-cp310-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/a1/05/918f9e7d2fbbd334b829997045d341d6239b563c44e683b9a7ef8fe50f5d/xxhash-3.5.0-cp310-cp310-musllinux_1_2_x86_64.whl",hashes = {sha256 = "b96d559e0fcddd3343c510a0fe2b127fbff16bf346dd76280b82292567523442"}}, - {name = "xxhash-3.5.0-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/08/29/dfe393805b2f86bfc47c290b275f0b7c189dc2f4e136fd4754f32eb18a8d/xxhash-3.5.0-cp310-cp310-win32.whl",hashes = {sha256 = "61c722ed8d49ac9bc26c7071eeaa1f6ff24053d553146d5df031802deffd03da"}}, - {name = "xxhash-3.5.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/7b/d7/aa0b22c4ebb7c3ccb993d4c565132abc641cd11164f8952d89eb6a501909/xxhash-3.5.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "9bed5144c6923cc902cd14bb8963f2d5e034def4486ab0bbe1f58f03f042f9a9"}}, - {name = "xxhash-3.5.0-cp310-cp310-win_arm64.whl",url = "https://files.pythonhosted.org/packages/69/12/f969b81541ee91b55f1ce469d7ab55079593c80d04fd01691b550e535000/xxhash-3.5.0-cp310-cp310-win_arm64.whl",hashes = {sha256 = "893074d651cf25c1cc14e3bea4fceefd67f2921b1bb8e40fcfeba56820de80c6"}}, - {name = "xxhash-3.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/ab/9a/233606bada5bd6f50b2b72c45de3d9868ad551e83893d2ac86dc7bb8553a/xxhash-3.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "2014c5b3ff15e64feecb6b713af12093f75b7926049e26a580e94dcad3c73d8c"}}, - {name = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/0c/67/f75276ca39e2c6604e3bee6c84e9db8a56a4973fde9bf35989787cf6e8aa/xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "fab81ef75003eda96239a23eda4e4543cedc22e34c373edcaf744e721a163986"}}, - {name = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",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",hashes = {sha256 = "4e2febf914ace002132aa09169cc572e0d8959d0f305f93d5828c4836f9bc5a6"}}, - {name = "xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",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",hashes = {sha256 = "5d3a10609c51da2a1c0ea0293fc3968ca0a18bd73838455b5bca3069d7f8e32b"}}, - {name = "xxhash-3.5.0-pp310-pypy310_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/62/e3/bef7b82c1997579c94de9ac5ea7626d01ae5858aa22bf4fcb38bf220cb3e/xxhash-3.5.0-pp310-pypy310_pp73-win_amd64.whl",hashes = {sha256 = "5a74f23335b9689b66eb6dbe2a931a88fcd7a4c2cc4b1cb0edba8ce381c7a1da"}}, - {name = "xxhash-3.5.0-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/d4/f6/531dd6858adf8877675270b9d6989b6dacfd1c2d7135b17584fc29866df3/xxhash-3.5.0-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "bfc8cdd7f33d57f0468b0614ae634cc38ab9202c6957a60e31d285a71ebe0301"}}, - {name = "xxhash-3.5.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/7c/a8/b2a42b6c9ae46e233f474f3d307c2e7bca8d9817650babeca048d2ad01d6/xxhash-3.5.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "e0c48b6300cd0b0106bf49169c3e0536408dfbeb1ccb53180068a18b03c662ab"}}, - {name = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/b4/92/9ac297e3487818f429bcf369c1c6a097edf5b56ed6fc1feff4c1882e87ef/xxhash-3.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "fe1a92cfbaa0a1253e339ccec42dbe6db262615e52df591b68726ab10338003f"}}, - {name = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",url = "https://files.pythonhosted.org/packages/86/48/c1426dd3c86fc4a52f983301867463472f6a9013fb32d15991e60c9919b6/xxhash-3.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",hashes = {sha256 = "33513d6cc3ed3b559134fb307aae9bdd94d7e7c02907b37896a6c45ff9ce51bd"}}, - {name = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",url = "https://files.pythonhosted.org/packages/f3/de/0ab8c79993765c94fc0d0c1a22b454483c58a0161e1b562f58b654f47660/xxhash-3.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl",hashes = {sha256 = "eefc37f6138f522e771ac6db71a6d4838ec7933939676f3753eafd7d3f4c40bc"}}, - {name = "xxhash-3.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b4/b4/332647451ed7d2c021294b7c1e9c144dbb5586b1fb214ad4f5a404642835/xxhash-3.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "a606c8070ada8aa2a88e181773fa1ef17ba65ce5dd168b9d08038e2a61b33754"}}, - {name = "xxhash-3.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/f4/1c/a42c0a6cac752f84f7b44a90d1a9fa9047cf70bdba5198a304fde7cc471f/xxhash-3.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "42eca420c8fa072cc1dd62597635d140e78e384a79bb4944f825fbef8bfeeef6"}}, - {name = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/c4/d7/04e1b0daae9dc9b02c73c1664cc8aa527498c3f66ccbc586eeb25bbe9f14/xxhash-3.5.0-cp39-cp39-musllinux_1_2_aarch64.whl",hashes = {sha256 = "604253b2143e13218ff1ef0b59ce67f18b8bd1c4205d2ffda22b09b426386898"}}, - {name = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/c4/f4/05e15e67505228fc19ee98a79e427b3a0b9695f5567cd66ced5d66389883/xxhash-3.5.0-cp39-cp39-musllinux_1_2_i686.whl",hashes = {sha256 = "6e93a5ad22f434d7876665444a97e713a8f60b5b1a3521e8df11b98309bff833"}}, - {name = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl",url = "https://files.pythonhosted.org/packages/94/fb/e9028d3645bba5412a09de13ee36df276a567e60bdb31d499dafa46d76ae/xxhash-3.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl",hashes = {sha256 = "7a46e1d6d2817ba8024de44c4fd79913a90e5f7265434cef97026215b7d30df6"}}, - {name = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_s390x.whl",url = "https://files.pythonhosted.org/packages/02/2c/18c6a622429368274739372d2f86c8125413ec169025c7d8ffb051784bba/xxhash-3.5.0-cp39-cp39-musllinux_1_2_s390x.whl",hashes = {sha256 = "30eb2efe6503c379b7ab99c81ba4a779748e3830241f032ab46bd182bf5873af"}}, - {name = "xxhash-3.5.0-cp39-cp39-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/72/bb/5b55c391084a0321c3809632a018b9b657e59d5966289664f85a645942ac/xxhash-3.5.0-cp39-cp39-musllinux_1_2_x86_64.whl",hashes = {sha256 = "c8aa771ff2c13dd9cda8166d685d7333d389fae30a4d2bb39d63ab5775de8606"}}, - {name = "xxhash-3.5.0-cp39-cp39-win32.whl",url = "https://files.pythonhosted.org/packages/86/2b/915049db13401792fec159f57e4f4a5ca7a9768e83ef71d6645b9d0cd749/xxhash-3.5.0-cp39-cp39-win32.whl",hashes = {sha256 = "5ed9ebc46f24cf91034544b26b131241b699edbfc99ec5e7f8f3d02d6eb7fba4"}}, - {name = "xxhash-3.5.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/d5/87/382ef7b24917d7cf4c540ee30f29b283bc87ac5893d2f89b23ea3cdf7d77/xxhash-3.5.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "220f3f896c6b8d0316f63f16c077d52c412619e475f9372333474ee15133a558"}}, - {name = "xxhash-3.5.0-cp39-cp39-win_arm64.whl",url = "https://files.pythonhosted.org/packages/e2/47/d06b24e2d9c3dcabccfd734d11b5bbebfdf59ceac2c61509d8205dd20ac6/xxhash-3.5.0-cp39-cp39-win_arm64.whl",hashes = {sha256 = "a7b1d8315d9b5e9f89eb2933b73afae6ec9597a258d52190944437158b49d38e"}}, - {name = "xxhash-3.5.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl",url = "https://files.pythonhosted.org/packages/c2/56/30d3df421814947f9d782b20c9b7e5e957f3791cbd89874578011daafcbd/xxhash-3.5.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl",hashes = {sha256 = "531af8845aaadcadf951b7e0c1345c6b9c68a990eeb74ff9acd8501a0ad6a1c9"}}, - {name = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/82/dd/3c42a1f022ad0d82c852d3cb65493ebac03dcfa8c994465a5fb052b00e3c/xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "7ce379bcaa9fcc00f19affa7773084dd09f5b59947b3fb47a1ceb0179f91aaa1"}}, - {name = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b2/40/8f902ab3bebda228a9b4de69eba988280285a7f7f167b942bc20bb562df9/xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "fd1b2281d01723f076df3c8188f43f2472248a6b63118b036e641243656b1b0f"}}, - {name = "xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/db/87/bd06beb8ccaa0e9e577c9b909a49cfa5c5cd2ca46034342d72dd9ce5bc56/xxhash-3.5.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "9c770750cc80e8694492244bca7251385188bc5597b6a39d98a9f30e8da984e0"}}, - {name = "xxhash-3.5.0-pp39-pypy39_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/bb/f8/505385e2fbd753ddcaafd5550eabe86f6232cbebabad3b2508d411b19153/xxhash-3.5.0-pp39-pypy39_pp73-win_amd64.whl",hashes = {sha256 = "b150b8467852e1bd844387459aa6fbe11d7f38b56e901f9f3b3e6aba0d660240"}}, ] marker = "\"default\" in dependency_groups" @@ -3522,6 +3492,18 @@ version = "1.13.1" requires-python = ">=3.9" sdist = {name = "scipy-1.13.1.tar.gz", url = "https://files.pythonhosted.org/packages/ae/00/48c2f661e2816ccf2ecd77982f6605b2950afe60f60a52b4cbbc2504aa8f/scipy-1.13.1.tar.gz", hashes = {sha256 = "095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c"}} wheels = [ + {name = "scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/b4/15/4a4bb1b15bbd2cd2786c4f46e76b871b28799b67891f23f455323a0cdcfb/scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9"}}, + {name = "scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ba/92/42476de1af309c27710004f5cdebc27bec62c204db42e05b23a302cb0c9a/scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl",hashes = {sha256 = "54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326"}}, + {name = "scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/80/ba/8be64fe225360a4beb6840f3cbee494c107c0887f33350d0a47d55400b01/scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299"}}, + {name = "scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/36/07/035d22ff9795129c5a847c64cb43c1fa9188826b59344fee28a3ab02e283/scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa"}}, + {name = "scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/d9/10/f9b43de37e5ed91facc0cfff31d45ed0104f359e4f9a68416cbf4e790241/scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59"}}, + {name = "scipy-1.13.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/4a/48/4513a1a5623a23e95f94abd675ed91cfb19989c58e9f6f7d03990f6caf3d/scipy-1.13.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b"}}, + {name = "scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/33/59/41b2529908c002ade869623b87eecff3e11e3ce62e996d0bdcb536984187/scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca"}}, + {name = "scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/d5/33/f1307601f492f764062ce7dd471a14750f3360e33cd0f8c614dae208492c/scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl",hashes = {sha256 = "d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f"}}, + {name = "scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/c0/66/9cd4f501dd5ea03e4a4572ecd874936d0da296bd04d1c45ae1a4a75d9c3a/scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989"}}, + {name = "scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a3/ba/7255e5dc82a65adbe83771c72f384d99c43063648456796436c9a5585ec3/scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f"}}, + {name = "scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/49/a5/bb9ded8326e9f0cdfdc412eeda1054b914dfea952bda2097d174f8832cc0/scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl",hashes = {sha256 = "eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94"}}, + {name = "scipy-1.13.1-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/12/30/df7a8fcc08f9b4a83f5f27cfaaa7d43f9a2d2ad0b6562cced433e5b04e31/scipy-1.13.1-cp310-cp310-win_amd64.whl",hashes = {sha256 = "2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54"}}, {name = "scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/7f/29/c2ea58c9731b9ecb30b6738113a95d147e83922986b34c685b8f6eefde21/scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5"}}, {name = "scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/5c/c0/e71b94b20ccf9effb38d7147c0064c08c622309fd487b1b677771a97d18c/scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl",hashes = {sha256 = "8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24"}}, {name = "scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/6d/0f/aaa55b06d474817cea311e7b10aab2ea1fd5d43bc6a2861ccc9caec9f418/scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004"}}, @@ -3529,7 +3511,7 @@ wheels = [ {name = "scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/8d/02/1165905f14962174e6569076bcc3315809ae1291ed14de6448cc151eedfd/scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl",hashes = {sha256 = "a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c"}}, {name = "scipy-1.13.1-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/3e/77/dab54fe647a08ee4253963bcd8f9cf17509c8ca64d6335141422fe2e2114/scipy-1.13.1-cp39-cp39-win_amd64.whl",hashes = {sha256 = "392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2"}}, ] -marker = "python_version < \"3.10\" and python_version >= \"3.9\" and \"dev\" in extras" +marker = "python_version < \"3.12\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.12\" and python_version >= \"3.9\" and \"dev\" in extras" [packages.tool.pdm] dependencies = [ @@ -3542,6 +3524,26 @@ version = "2.0.2" requires-python = ">=3.9" sdist = {name = "numpy-2.0.2.tar.gz", url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hashes = {sha256 = "883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78"}} wheels = [ + {name = "numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448"}}, + {name = "numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/4a/d9/32de45561811a4b87fbdee23b5797394e3d1504b4a7cf40c10199848893e/numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195"}}, + {name = "numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c1/ca/2f384720020c7b244d22508cb7ab23d95f179fcfff33c31a6eeba8d6c512/numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl",hashes = {sha256 = "807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57"}}, + {name = "numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl",hashes = {sha256 = "8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a"}}, + {name = "numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/a0/72/cfc3a1beb2caf4efc9d0b38a15fe34025230da27e1c08cc2eb9bfb1c7231/numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669"}}, + {name = "numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951"}}, + {name = "numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl",hashes = {sha256 = "9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9"}}, + {name = "numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/df/87/f76450e6e1c14e5bb1eae6836478b1028e096fd02e85c1c37674606ab752/numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15"}}, + {name = "numpy-2.0.2-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/5c/ca/0f0f328e1e59f73754f06e1adfb909de43726d4f24c6a3f8805f34f2b0fa/numpy-2.0.2-cp311-cp311-win32.whl",hashes = {sha256 = "a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4"}}, + {name = "numpy-2.0.2-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl",hashes = {sha256 = "286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc"}}, + {name = "numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/21/91/3495b3237510f79f5d81f2508f9f13fea78ebfdf07538fc7444badda173d/numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece"}}, + {name = "numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/05/33/26178c7d437a87082d11019292dce6d3fe6f0e9026b7b2309cbf3e489b1d/numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04"}}, + {name = "numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ec/31/cc46e13bf07644efc7a4bf68df2df5fb2a1a88d0cd0da9ddc84dc0033e51/numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl",hashes = {sha256 = "8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66"}}, + {name = "numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl",url = "https://files.pythonhosted.org/packages/6e/16/7bfcebf27bb4f9d7ec67332ffebee4d1bf085c84246552d52dbb548600e7/numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl",hashes = {sha256 = "becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b"}}, + {name = "numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f9/a3/561c531c0e8bf082c5bef509d00d56f82e0ea7e1e3e3a7fc8fa78742a6e5/numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd"}}, + {name = "numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/fa/66/f7177ab331876200ac7563a580140643d1179c8b4b6a6b0fc9838de2a9b8/numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318"}}, + {name = "numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl",url = "https://files.pythonhosted.org/packages/25/7f/0b209498009ad6453e4efc2c65bcdf0ae08a182b2b7877d7ab38a92dc542/numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl",hashes = {sha256 = "a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8"}}, + {name = "numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/3e/df/2619393b1e1b565cd2d4c4403bdd979621e2c4dea1f8532754b2598ed63b/numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl",hashes = {sha256 = "d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326"}}, + {name = "numpy-2.0.2-cp310-cp310-win32.whl",url = "https://files.pythonhosted.org/packages/22/ad/77e921b9f256d5da36424ffb711ae79ca3f451ff8489eeca544d0701d74a/numpy-2.0.2-cp310-cp310-win32.whl",hashes = {sha256 = "984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97"}}, + {name = "numpy-2.0.2-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/10/05/3442317535028bc29cf0c0dd4c191a4481e8376e9f0db6bcf29703cadae6/numpy-2.0.2-cp310-cp310-win_amd64.whl",hashes = {sha256 = "c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131"}}, {name = "numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/43/c1/41c8f6df3162b0c6ffd4437d729115704bd43363de0090c7f913cfbc2d89/numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c"}}, {name = "numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/39/bc/fd298f308dcd232b56a4031fd6ddf11c43f9917fbc937e53762f7b5a3bb1/numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd"}}, {name = "numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl",url = "https://files.pythonhosted.org/packages/96/ff/06d1aa3eeb1c614eda245c1ba4fb88c483bee6520d361641331872ac4b82/numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl",hashes = {sha256 = "2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b"}}, @@ -3557,17 +3559,212 @@ wheels = [ {name = "numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/12/46/de1fbd0c1b5ccaa7f9a005b66761533e2f6a3e560096682683a223631fe9/numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c"}}, {name = "numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl",url = "https://files.pythonhosted.org/packages/cc/dc/d330a6faefd92b446ec0f0dfea4c3207bb1fef3c4771d19cf4543efd2c78/numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl",hashes = {sha256 = "a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385"}}, ] -marker = "python_version < \"3.10\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.10\" and python_version >= \"3.9\" and \"dev\" in extras" +marker = "python_version < \"3.12\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.12\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "tomli" +version = "2.2.1" +requires-python = ">=3.8" +sdist = {name = "tomli-2.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hashes = {sha256 = "cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}} +wheels = [ + {name = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}}, + {name = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}}, + {name = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}}, + {name = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}}, + {name = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl",hashes = {sha256 = "c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}}, + {name = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl",url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl",hashes = {sha256 = "8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}}, + {name = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl",url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl",hashes = {sha256 = "e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}}, + {name = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl",url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl",hashes = {sha256 = "33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}}, + {name = "tomli-2.2.1-cp311-cp311-win32.whl",url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl",hashes = {sha256 = "465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}}, + {name = "tomli-2.2.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}}, + {name = "tomli-2.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl",hashes = {sha256 = "cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}}, +] +marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "importlib-metadata" +version = "8.7.0" +requires-python = ">=3.9" +sdist = {name = "importlib_metadata-8.7.0.tar.gz", url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hashes = {sha256 = "d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"}} +wheels = [ + {name = "importlib_metadata-8.7.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl",hashes = {sha256 = "e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"}}, +] +marker = "python_full_version < \"3.10.2\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [ + "zipp>=3.20", + "typing-extensions>=3.6.4; python_version < \"3.8\"", +] + +[[packages]] +name = "backports-asyncio-runner" +version = "1.2.0" +requires-python = "<3.11,>=3.8" +sdist = {name = "backports_asyncio_runner-1.2.0.tar.gz", url = "https://files.pythonhosted.org/packages/8e/ff/70dca7d7cb1cbc0edb2c6cc0c38b65cba36cccc491eca64cabd5fe7f8670/backports_asyncio_runner-1.2.0.tar.gz", hashes = {sha256 = "a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"}} +wheels = [ + {name = "backports_asyncio_runner-1.2.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/a0/59/76ab57e3fe74484f48a53f8e337171b4a2349e506eabe136d7e01d059086/backports_asyncio_runner-1.2.0-py3-none-any.whl",hashes = {sha256 = "0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"}}, +] +marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "async-timeout" +version = "5.0.1" +requires-python = ">=3.8" +sdist = {name = "async_timeout-5.0.1.tar.gz", url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hashes = {sha256 = "d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}} +wheels = [ + {name = "async_timeout-5.0.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl",hashes = {sha256 = "39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}}, +] +marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "exceptiongroup" +version = "1.3.0" +requires-python = ">=3.7" +sdist = {name = "exceptiongroup-1.3.0.tar.gz", url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hashes = {sha256 = "b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}} +wheels = [ + {name = "exceptiongroup-1.3.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl",hashes = {sha256 = "4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}}, +] +marker = "python_version < \"3.11\" and python_version >= \"3.9\" and \"default\" in dependency_groups or python_version < \"3.11\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [ + "typing-extensions>=4.6.0; python_version < \"3.13\"", +] + +[[packages]] +name = "numba" +version = "0.60.0" +requires-python = ">=3.9" +sdist = {name = "numba-0.60.0.tar.gz", url = "https://files.pythonhosted.org/packages/3c/93/2849300a9184775ba274aba6f82f303343669b0592b7bb0849ea713dabb0/numba-0.60.0.tar.gz", hashes = {sha256 = "5df6158e5584eece5fc83294b949fd30b9f1125df7708862205217e068aabf16"}} +wheels = [ + {name = "numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8"}}, + {name = "numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/9a/51/a4dc2c01ce7a850b8e56ff6d5381d047a5daea83d12bad08aa071d34b2ee/numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b"}}, + {name = "numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703"}}, + {name = "numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8"}}, + {name = "numba-0.60.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2"}}, + {name = "numba-0.60.0-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/f7/cf/baa13a7e3556d73d9e38021e6d6aa4aeb30d8b94545aa8b70d0f24a1ccc4/numba-0.60.0-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "5d761de835cd38fb400d2c26bb103a2726f548dc30368853121d66201672e651"}}, + {name = "numba-0.60.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ac/ba/4b57fa498564457c3cc9fc9e570a6b08e6086c74220f24baaf04e54b995f/numba-0.60.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "159e618ef213fba758837f9837fb402bbe65326e60ba0633dbe6c7f274d42c1b"}}, + {name = "numba-0.60.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/28/98/7ea97ee75870a54f938a8c70f7e0be4495ba5349c5f9db09d467c4a5d5b7/numba-0.60.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "1527dc578b95c7c4ff248792ec33d097ba6bef9eda466c948b68dfc995c25781"}}, + {name = "numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/79/58/cb4ac5b8f7ec64200460aef1fed88258fb872ceef504ab1f989d2ff0f684/numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "fe0b28abb8d70f8160798f4de9d486143200f34458d34c4a214114e445d7124e"}}, + {name = "numba-0.60.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/1c/b0/c61a93ca947d12233ff45de506ddbf52af3f752066a0b8be4d27426e16da/numba-0.60.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "19407ced081d7e2e4b8d8c36aa57b7452e0283871c296e12d798852bc7d7f198"}}, + {name = "numba-0.60.0-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/68/1a/87c53f836cdf557083248c3f47212271f220280ff766538795e77c8c6bbf/numba-0.60.0-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "01ef4cd7d83abe087d644eaa3d95831b777aa21d441a23703d649e06b8e06b74"}}, + {name = "numba-0.60.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/28/14/a5baa1f2edea7b49afa4dc1bb1b126645198cf1075186853b5b497be826e/numba-0.60.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "819a3dfd4630d95fd574036f99e47212a1af41cbcb019bf8afac63ff56834449"}}, + {name = "numba-0.60.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",url = "https://files.pythonhosted.org/packages/3b/bd/f1985719ff34e37e07bb18f9d3acd17e5a21da255f550c8eae031e2ddf5f/numba-0.60.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl",hashes = {sha256 = "0b983bd6ad82fe868493012487f34eae8bf7dd94654951404114f23c3466d34b"}}, + {name = "numba-0.60.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",url = "https://files.pythonhosted.org/packages/54/9b/cd73d3f6617ddc8398a63ef97d8dc9139a9879b9ca8a7ca4b8789056ea46/numba-0.60.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",hashes = {sha256 = "c151748cd269ddeab66334bd754817ffc0cabd9433acb0f551697e5151917d25"}}, + {name = "numba-0.60.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/01/01/8b7b670c77c5ea0e47e283d82332969bf672ab6410d0b2610cac5b7a3ded/numba-0.60.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "3031547a015710140e8c87226b4cfe927cac199835e5bf7d4fe5cb64e814e3ab"}}, +] +marker = "python_version < \"3.12\" and python_version >= \"3.9\" and \"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "llvmlite<0.44,>=0.43.0dev0", + "numpy<2.1,>=1.22", +] + +[[packages]] +name = "llvmlite" +version = "0.43.0" +requires-python = ">=3.9" +sdist = {name = "llvmlite-0.43.0.tar.gz", url = "https://files.pythonhosted.org/packages/9f/3d/f513755f285db51ab363a53e898b85562e950f79a2e6767a364530c2f645/llvmlite-0.43.0.tar.gz", hashes = {sha256 = "ae2b5b5c3ef67354824fb75517c8db5fbe93bc02cd9671f3c62271626bc041d5"}} +wheels = [ + {name = "llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/95/8c/de3276d773ab6ce3ad676df5fab5aac19696b2956319d65d7dd88fb10f19/llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98"}}, + {name = "llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ee/e1/38deed89ced4cf378c61e232265cfe933ccde56ae83c901aa68b477d14b1/llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl",hashes = {sha256 = "e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57"}}, + {name = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2"}}, + {name = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/6b/99/5d00a7d671b1ba1751fc9f19d3b36f3300774c6eebe2bcdb5f6191763eb4/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749"}}, + {name = "llvmlite-0.43.0-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/20/ab/ed5ed3688c6ba4f0b8d789da19fd8e30a9cf7fc5852effe311bc5aefe73e/llvmlite-0.43.0-cp311-cp311-win_amd64.whl",hashes = {sha256 = "d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91"}}, + {name = "llvmlite-0.43.0-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/23/ff/6ca7e98998b573b4bd6566f15c35e5c8bea829663a6df0c7aa55ab559da9/llvmlite-0.43.0-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "a289af9a1687c6cf463478f0fa8e8aa3b6fb813317b0d70bf1ed0759eab6f761"}}, + {name = "llvmlite-0.43.0-cp310-cp310-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/ca/5c/a27f9257f86f0cda3f764ff21d9f4217b9f6a0d45e7a39ecfa7905f524ce/llvmlite-0.43.0-cp310-cp310-macosx_11_0_arm64.whl",hashes = {sha256 = "6d4fd101f571a31acb1559ae1af30f30b1dc4b3186669f92ad780e17c81e91bc"}}, + {name = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/7e/3c/4410f670ad0a911227ea2ecfcba9f672a77cf1924df5280c4562032ec32d/llvmlite-0.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "7d434ec7e2ce3cc8f452d1cd9a28591745de022f931d67be688a737320dfcead"}}, + {name = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/c6/21/2ffbab5714e72f2483207b4a1de79b2eecd9debbf666ff4e7067bcc5c134/llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "6912a87782acdff6eb8bf01675ed01d60ca1f2551f8176a300a886f09e836a6a"}}, + {name = "llvmlite-0.43.0-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/f2/26/b5478037c453554a61625ef1125f7e12bb1429ae11c6376f47beba9b0179/llvmlite-0.43.0-cp310-cp310-win_amd64.whl",hashes = {sha256 = "14f0e4bf2fd2d9a75a3534111e8ebeb08eda2f33e9bdd6dfa13282afacdde0ed"}}, + {name = "llvmlite-0.43.0-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/2a/73/12925b1bbb3c2beb6d96f892ef5b4d742c34f00ddb9f4a125e9e87b22f52/llvmlite-0.43.0-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "9cd2a7376f7b3367019b664c21f0c61766219faa3b03731113ead75107f3b66c"}}, + {name = "llvmlite-0.43.0-cp39-cp39-macosx_11_0_arm64.whl",url = "https://files.pythonhosted.org/packages/cc/61/58c70aa0808a8cba825a7d98cc65bef4801b99328fba80837bfcb5fc767f/llvmlite-0.43.0-cp39-cp39-macosx_11_0_arm64.whl",hashes = {sha256 = "18e9953c748b105668487b7c81a3e97b046d8abf95c4ddc0cd3c94f4e4651ae8"}}, + {name = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/c8/c6/9324eb5de2ba9d99cbed853d85ba7a318652a48e077797bec27cf40f911d/llvmlite-0.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "74937acd22dc11b33946b67dca7680e6d103d6e90eeaaaf932603bec6fe7b03a"}}, + {name = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/e0/d0/889e9705107db7b1ec0767b03f15d7b95b4c4f9fdf91928ab1c7e9ffacf6/llvmlite-0.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "bc9efc739cc6ed760f795806f67889923f7274276f0eb45092a1473e40d9b867"}}, + {name = "llvmlite-0.43.0-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/df/41/73cc26a2634b538cfe813f618c91e7e9960b8c163f8f0c94a2b0f008b9da/llvmlite-0.43.0-cp39-cp39-win_amd64.whl",hashes = {sha256 = "47e147cdda9037f94b399bf03bfd8a6b6b1f2f90be94a454e3386f006455a9b4"}}, +] +marker = "python_version < \"3.12\" and python_version >= \"3.9\" and \"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "scikit-learn" +version = "1.6.1" +requires-python = ">=3.9" +sdist = {name = "scikit_learn-1.6.1.tar.gz", url = "https://files.pythonhosted.org/packages/9e/a5/4ae3b3a0755f7b35a280ac90b28817d1f380318973cff14075ab41ef50d9/scikit_learn-1.6.1.tar.gz", hashes = {sha256 = "b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e"}} +wheels = [ + {name = "scikit_learn-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/6c/2a/e291c29670795406a824567d1dfc91db7b699799a002fdaa452bceea8f6e/scikit_learn-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl",hashes = {sha256 = "72abc587c75234935e97d09aa4913a82f7b03ee0b74111dcc2881cba3c5a7b33"}}, + {name = "scikit_learn-1.6.1-cp311-cp311-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/25/92/ee1d7a00bb6b8c55755d4984fd82608603a3cc59959245068ce32e7fb808/scikit_learn-1.6.1-cp311-cp311-macosx_12_0_arm64.whl",hashes = {sha256 = "b3b00cdc8f1317b5f33191df1386c0befd16625f49d979fe77a8d44cae82410d"}}, + {name = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/30/cd/ed4399485ef364bb25f388ab438e3724e60dc218c547a407b6e90ccccaef/scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "dc4765af3386811c3ca21638f63b9cf5ecf66261cc4815c1db3f1e7dc7b79db2"}}, + {name = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/a8/f3/62fc9a5a659bb58a03cdd7e258956a5824bdc9b4bb3c5d932f55880be569/scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "25fc636bdaf1cc2f4a124a116312d837148b5e10872147bdaf4887926b8c03d8"}}, + {name = "scikit_learn-1.6.1-cp311-cp311-win_amd64.whl",url = "https://files.pythonhosted.org/packages/a1/a6/c5b78606743a1f28eae8f11973de6613a5ee87366796583fb74c67d54939/scikit_learn-1.6.1-cp311-cp311-win_amd64.whl",hashes = {sha256 = "fa909b1a36e000a03c382aade0bd2063fd5680ff8b8e501660c0f59f021a6415"}}, + {name = "scikit_learn-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/2e/3a/f4597eb41049110b21ebcbb0bcb43e4035017545daa5eedcfeb45c08b9c5/scikit_learn-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl",hashes = {sha256 = "d056391530ccd1e501056160e3c9673b4da4805eb67eb2bdf4e983e1f9c9204e"}}, + {name = "scikit_learn-1.6.1-cp310-cp310-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/37/19/0423e5e1fd1c6ec5be2352ba05a537a473c1677f8188b9306097d684b327/scikit_learn-1.6.1-cp310-cp310-macosx_12_0_arm64.whl",hashes = {sha256 = "0c8d036eb937dbb568c6242fa598d551d88fb4399c0344d95c001980ec1c7d36"}}, + {name = "scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/70/95/d5cb2297a835b0f5fc9a77042b0a2d029866379091ab8b3f52cc62277808/scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "8634c4bd21a2a813e0a7e3900464e6d593162a29dd35d25bdf0103b3fce60ed5"}}, + {name = "scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/b7/91/ab3c697188f224d658969f678be86b0968ccc52774c8ab4a86a07be13c25/scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "775da975a471c4f6f467725dff0ced5c7ac7bda5e9316b260225b48475279a1b"}}, + {name = "scikit_learn-1.6.1-cp310-cp310-win_amd64.whl",url = "https://files.pythonhosted.org/packages/17/04/d5d556b6c88886c092cc989433b2bab62488e0f0dafe616a1d5c9cb0efb1/scikit_learn-1.6.1-cp310-cp310-win_amd64.whl",hashes = {sha256 = "8a600c31592bd7dab31e1c61b9bbd6dea1b3433e67d264d17ce1017dbdce8002"}}, + {name = "scikit_learn-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl",url = "https://files.pythonhosted.org/packages/d2/37/b305b759cc65829fe1b8853ff3e308b12cdd9d8884aa27840835560f2b42/scikit_learn-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl",hashes = {sha256 = "6849dd3234e87f55dce1db34c89a810b489ead832aaf4d4550b7ea85628be6c1"}}, + {name = "scikit_learn-1.6.1-cp39-cp39-macosx_12_0_arm64.whl",url = "https://files.pythonhosted.org/packages/83/74/f64379a4ed5879d9db744fe37cfe1978c07c66684d2439c3060d19a536d8/scikit_learn-1.6.1-cp39-cp39-macosx_12_0_arm64.whl",hashes = {sha256 = "e7be3fa5d2eb9be7d77c3734ff1d599151bb523674be9b834e8da6abe132f44e"}}, + {name = "scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",url = "https://files.pythonhosted.org/packages/fd/dc/d5457e03dc9c971ce2b0d750e33148dd060fefb8b7dc71acd6054e4bb51b/scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",hashes = {sha256 = "44a17798172df1d3c1065e8fcf9019183f06c87609b49a124ebdf57ae6cb0107"}}, + {name = "scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",url = "https://files.pythonhosted.org/packages/79/35/b1d2188967c3204c78fa79c9263668cf1b98060e8e58d1a730fe5b2317bb/scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",hashes = {sha256 = "b8b7a3b86e411e4bce21186e1c180d792f3d99223dcfa3b4f597ecc92fa1a422"}}, + {name = "scikit_learn-1.6.1-cp39-cp39-win_amd64.whl",url = "https://files.pythonhosted.org/packages/fb/d8/8d603bdd26601f4b07e2363032b8565ab82eb857f93d86d0f7956fcf4523/scikit_learn-1.6.1-cp39-cp39-win_amd64.whl",hashes = {sha256 = "7a73d457070e3318e32bdb3aa79a8d990474f19035464dfd8bede2883ab5dc3b"}}, +] +marker = "python_version < \"3.12\" and python_version >= \"3.9\" and \"default\" in dependency_groups" + +[packages.tool.pdm] +dependencies = [ + "numpy>=1.19.5", + "scipy>=1.6.0", + "joblib>=1.2.0", + "threadpoolctl>=3.1.0", +] + +[[packages]] +name = "zipp" +version = "3.23.0" +requires-python = ">=3.9" +sdist = {name = "zipp-3.23.0.tar.gz", url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hashes = {sha256 = "a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}} +wheels = [ + {name = "zipp-3.23.0-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl",hashes = {sha256 = "071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}}, +] +marker = "python_full_version < \"3.10.2\" and python_version >= \"3.9\" and \"dev\" in extras" + +[packages.tool.pdm] +dependencies = [] + +[[packages]] +name = "networkx" +version = "3.2.1" +requires-python = ">=3.9" +sdist = {name = "networkx-3.2.1.tar.gz", url = "https://files.pythonhosted.org/packages/c4/80/a84676339aaae2f1cfdf9f418701dd634aef9cc76f708ef55c36ff39c3ca/networkx-3.2.1.tar.gz", hashes = {sha256 = "9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}} +wheels = [ + {name = "networkx-3.2.1-py3-none-any.whl",url = "https://files.pythonhosted.org/packages/d5/f0/8fbc882ca80cf077f1b246c0e3c3465f7f415439bdea6b899f6b19f61f70/networkx-3.2.1-py3-none-any.whl",hashes = {sha256 = "f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}}, +] +marker = "python_version < \"3.12\" and python_version >= \"3.9\" and \"default\" in dependency_groups" [packages.tool.pdm] dependencies = [] [tool.pdm] -hashes = {sha256 = "4909a619da3f004dcd3f4ece16e07e96f81709904464fc614e66b456c5f8c73e"} +hashes = {sha256 = "555b4bbcb733817760de0902c1c4437a46a7d37708dba2168675e50f454e6361"} strategy = ["inherit_metadata", "static_urls"] [[tool.pdm.targets]] -requires_python = "~=3.10" +requires_python = "~=3.12" [[tool.pdm.targets]] -requires_python = ">=3.9,<3.10" +requires_python = ">=3.9,<3.12" diff --git a/pyproject.toml b/pyproject.toml index fbe054ad..7237e66d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,13 @@ include = ["*"] [tool.pdm] distribution = true +[[tool.pdm.source]] +name = "torch" +type = "find_links" +#url = "https://download.pytorch.org/whl/cpu/torch_stable.html" +url = "https://download.pytorch.org/whl/cpu/torch/" +include_packages = ["torch"] + # ************************************************ # ********** Project Metadata ********** @@ -64,6 +71,8 @@ dependencies = [ "sanic", "transformers", "uvloop>=0.18", + "librosa>=0.11.0", + "torch>=2.8.0", ] [project.optional-dependencies] diff --git a/src/guidellm/data/deserializers/__init__.py b/src/guidellm/data/deserializers/__init__.py index fdee12ce..1062f2b7 100644 --- a/src/guidellm/data/deserializers/__init__.py +++ b/src/guidellm/data/deserializers/__init__.py @@ -25,6 +25,7 @@ SyntheticTextDatasetConfig, SyntheticTextDatasetDeserializer, SyntheticTextGenerator, + SyntheticTextPrefixBucketConfig, ) __all__ = [ @@ -46,6 +47,7 @@ "SyntheticTextDatasetConfig", "SyntheticTextDatasetDeserializer", "SyntheticTextGenerator", + "SyntheticTextPrefixBucketConfig", "TarFileDatasetDeserializer", "TextFileDatasetDeserializer", ] diff --git a/src/guidellm/data/deserializers/synthetic.py b/src/guidellm/data/deserializers/synthetic.py index 2335596d..a071eeea 100644 --- a/src/guidellm/data/deserializers/synthetic.py +++ b/src/guidellm/data/deserializers/synthetic.py @@ -1,13 +1,15 @@ from __future__ import annotations +import math from collections.abc import Iterator from pathlib import Path -from typing import Any, Callable +from random import Random +from typing import Any, Callable, Self import yaml from datasets import Features, IterableDataset, Value from faker import Faker -from pydantic import Field +from pydantic import ConfigDict, Field, model_validator from transformers import PreTrainedTokenizerBase from guidellm.data.deserializers.deserializer import ( @@ -21,10 +23,37 @@ "SyntheticTextDatasetConfig", "SyntheticTextDatasetDeserializer", "SyntheticTextGenerator", + "SyntheticTextPrefixBucketConfig", ] +class SyntheticTextPrefixBucketConfig(StandardBaseModel): + bucket_weight: int = Field( + description="Weight of this bucket in the overall distribution.", + gt=0, + default=100, + ) + prefix_count: int = Field( + description="The number of unique prefixes to generate for this bucket.", + ge=1, + default=1, + ) + prefix_tokens: int = Field( + description="The number of prefix tokens per-prompt for this bucket.", + ge=0, + default=0, + ) + + class SyntheticTextDatasetConfig(StandardBaseModel): + model_config = ConfigDict( + extra="allow", + ) + + prefix_buckets: list[SyntheticTextPrefixBucketConfig] | None = Field( + description="Buckets for the prefix tokens distribution.", + default=None, + ) prompt_tokens: int = Field( description="The average number of text tokens generated for prompts.", gt=0, @@ -68,6 +97,26 @@ class SyntheticTextDatasetConfig(StandardBaseModel): default="data:prideandprejudice.txt.gz", ) + @model_validator(mode="after") + def check_prefix_options(self) -> Self: + prefix_count = self.__pydantic_extra__.get("prefix_count", None) # type: ignore[attr-defined] + prefix_tokens = self.__pydantic_extra__.get("prefix_count", None) # type: ignore[attr-defined] + if prefix_count is not None or prefix_tokens is not None: + if self.prefix_buckets: + raise ValueError( + "prefix_buckets is mutually exclusive" + " with prefix_count and prefix_tokens" + ) + + self.prefix_buckets = [ + SyntheticTextPrefixBucketConfig( + prefix_count=prefix_count or 1, + prefix_tokens=prefix_tokens or 0, + ) + ] + + return self + class SyntheticTextGenerator: def __init__( @@ -104,20 +153,27 @@ def __iter__(self) -> Iterator[dict[str, Any]]: ) ) + # Create a shared prefix if specified + rand = Random(self.random_seed + 3) + prefix_iter = self._create_prefix_iter(faker, rand) + while True: prompt_tokens_count = next(prompt_tokens_sampler) output_tokens_count = next(output_tokens_sampler) yield { + "prefix": next(prefix_iter), "prompt": self._create_prompt( - prompt_tokens_count, samples_generated, faker + prompt_tokens_count, faker, f"{samples_generated} " ), "prompt_tokens_count": prompt_tokens_count, "output_tokens_count": output_tokens_count, } samples_generated += 1 - def _create_prompt(self, prompt_tokens_count: int, index: int, faker: Faker) -> str: + def _create_prompt( + self, prompt_tokens_count: int, faker: Faker, unique: str = "" + ) -> str: prompt_token_ids = [] avg_chars_per_token = 5 margin_of_safety = 1.5 @@ -128,13 +184,42 @@ def _create_prompt(self, prompt_tokens_count: int, index: int, faker: Faker) -> num_chars = ( prompt_tokens_count * avg_chars_per_token * margin_of_safety * attempts ) - text = f"{index} " + faker.text(max_nb_chars=num_chars) + text = unique + faker.text(max_nb_chars=num_chars) prompt_token_ids = self.processor.encode(text) return self.processor.decode( prompt_token_ids[:prompt_tokens_count], skip_special_tokens=True ) + def _create_prefix_iter(self, faker: Faker, rand: Random) -> Iterator[str]: + if not self.config.prefix_buckets: + while True: + yield "" + + # Increase weights to ensure an integer number of samples per per-prefix + least_common_prefix_count = math.lcm( + *(bucket.prefix_count for bucket in self.config.prefix_buckets) + ) + unnorm_weights = [ + least_common_prefix_count * bucket.bucket_weight // bucket.prefix_count + for bucket in self.config.prefix_buckets + ] + # Use GCD to reduce the weights to smallest integer ratio + common_divisor = math.gcd(*unnorm_weights) + + # Create prefix list maintaining the correct distribution + prefixes = [] + for bucket, weight in zip(self.config.prefix_buckets, unnorm_weights): + bucket_prefixes = [ + self._create_prompt(bucket.prefix_tokens, faker) + for _ in range(bucket.prefix_count) + ] + sample_count = weight // common_divisor + prefixes.extend(bucket_prefixes * sample_count) + + while True: + yield rand.choice(prefixes) + @DatasetDeserializerFactory.register("synthetic_text") class SyntheticTextDatasetDeserializer(DatasetDeserializer): @@ -166,6 +251,7 @@ def __call__( ), features=Features( { + "prefix": Value("string"), "prompt": Value("string"), "prompt_tokens_count": Value("int32"), "output_tokens_count": Value("int32"), diff --git a/src/guidellm/data/formatters/templates.py b/src/guidellm/data/formatters/templates.py index 2cf6e2f3..52db73b1 100644 --- a/src/guidellm/data/formatters/templates.py +++ b/src/guidellm/data/formatters/templates.py @@ -22,11 +22,7 @@ class JinjaTemplatesRegistry(RegistryMixin[Union[Template, str]]): textwrap.dedent(""" {% set obj = { "json_body": { - "prompt": ( - text_column[0] - if text_column and text_column|length == 1 - else text_column - ) + "prompt": prefix_column[0]|default("") + text_column[0] } } %} @@ -52,6 +48,10 @@ class JinjaTemplatesRegistry(RegistryMixin[Union[Template, str]]): {% set obj = { "json_body": { "messages": [ + { + "role": "system", + "content": prefix_column[0]|default("") + }, { "role": "user", "content": [] @@ -61,11 +61,11 @@ class JinjaTemplatesRegistry(RegistryMixin[Union[Template, str]]): } %} {%- for item in text_column or [] %} - {% do obj["json_body"].messages[0].content.append({"type": "text", "text": item}) %} + {% do obj["json_body"].messages[1].content.append({"type": "text", "text": item}) %} {%- endfor %} {%- for item in image_column or [] %} - {% do obj["json_body"].messages[0].content.append({ + {% do obj["json_body"].messages[1].content.append({ "type": "image_url", "image_url": encode_image( item, @@ -78,7 +78,7 @@ class JinjaTemplatesRegistry(RegistryMixin[Union[Template, str]]): {%- endfor %} {%- for item in video_column or [] %} - {% do obj["json_body"].messages[0].content.append({ + {% do obj["json_body"].messages[1].content.append({ "type": "video_url", "video_url": encode_video( item, diff --git a/src/guidellm/data/objects.py b/src/guidellm/data/objects.py index 04c5407d..b4a38719 100644 --- a/src/guidellm/data/objects.py +++ b/src/guidellm/data/objects.py @@ -31,6 +31,7 @@ GenerativeDatasetColumnType = Literal[ "prompt_tokens_count_column", "output_tokens_count_column", + "prefix_column", "text_column", "image_column", "video_column", @@ -195,6 +196,7 @@ class GenerativeDatasetArgs(StandardBaseDict): split: str | None = None prompt_tokens_count_column: str | None = None output_tokens_count_column: str | None = None + prefix_column: str | None = None text_column: str | list[str] | None = None image_column: str | list[str] | None = None video_column: str | list[str] | None = None diff --git a/src/guidellm/data/utils.py b/src/guidellm/data/utils.py index 7d53a054..d2fa1f9c 100644 --- a/src/guidellm/data/utils.py +++ b/src/guidellm/data/utils.py @@ -80,6 +80,11 @@ DEFAULT_COLUMN_NAMES: dict[str, list[str]] = { "prompt_tokens_count": ["prompt_tokens_count", "input_tokens_count"], "output_tokens_count": ["output_tokens_count", "completion_tokens_count"], + "prefix_column": [ + "system_prompt", + "system", + "prefix", + ], "text_column": [ "prompt", "instruction", diff --git a/tests/unit/dataset/__init__.py b/tests/unit/data/__init__.py similarity index 100% rename from tests/unit/dataset/__init__.py rename to tests/unit/data/__init__.py diff --git a/tests/unit/data/deserializers/__init__.py b/tests/unit/data/deserializers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/data/deserializers/test_synthetic.py b/tests/unit/data/deserializers/test_synthetic.py new file mode 100644 index 00000000..58b76aee --- /dev/null +++ b/tests/unit/data/deserializers/test_synthetic.py @@ -0,0 +1,587 @@ +""" +Unit tests for guidellm.data.deserializers.synthetic module. +""" + +import json +import tempfile +from pathlib import Path +from unittest.mock import Mock + +import pytest +import yaml +from datasets import IterableDataset + +from guidellm.data.deserializers.deserializer import DataNotSupportedError +from guidellm.data.deserializers.synthetic import ( + SyntheticTextDatasetConfig, + SyntheticTextDatasetDeserializer, + SyntheticTextGenerator, + SyntheticTextPrefixBucketConfig, +) + + +class TestPrefixBucketConfig: + """Test cases for PrefixBucketConfig class. + + ### WRITTEN BY AI ### + """ + + @pytest.mark.smoke + def test_creation_with_valid_params(self): + """Test creating PrefixBucketConfig with valid parameters. + + ### WRITTEN BY AI ### + """ + config = SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=1, prefix_tokens=5 + ) + + assert config.bucket_weight == 100 + assert config.prefix_count == 1 + assert config.prefix_tokens == 5 + + @pytest.mark.sanity + def test_creation_with_negative_values(self): + """Test creating PrefixBucketConfig with negative values raises ValueError. + + ### WRITTEN BY AI ### + """ + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=-10, prefix_count=1, prefix_tokens=5 + ) + + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=-1, prefix_tokens=5 + ) + + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=1, prefix_tokens=-5 + ) + + @pytest.mark.regression + def test_prefix_bucket_zero_weight_error(self): + """Test that zero total weight raises an error. + + ### WRITTEN BY AI ### + """ + # Test validation error for creating PrefixBucketConfig with weight=0 + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=0, prefix_count=1, prefix_tokens=2 + ) + + @pytest.mark.sanity + def test_prefix_bucket_config_validation(self): + """Test PrefixBucketConfig validation. + + ### WRITTEN BY AI ### + """ + # Test valid config + valid_config = SyntheticTextPrefixBucketConfig( + bucket_weight=50, prefix_count=2, prefix_tokens=3 + ) + assert valid_config.bucket_weight == 50 + assert valid_config.prefix_count == 2 + assert valid_config.prefix_tokens == 3 + + # Test invalid bucket_weight + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=0, prefix_count=1, prefix_tokens=2 + ) + + # Test invalid prefix_count + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=0, prefix_tokens=2 + ) + + # Test invalid prefix_tokens + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=1, prefix_tokens=-1 + ) + + +class TestSyntheticDatasetConfig: + """Test cases for SyntheticDatasetConfig class. + + ### WRITTEN BY AI ### + """ + + @pytest.mark.smoke + def test_config_creation_with_all_params(self): + """Test creating config with all parameters specified. + + ### WRITTEN BY AI ### + """ + prefix_bucket = SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=1, prefix_tokens=5 + ) + + config = SyntheticTextDatasetConfig( + prefix_buckets=[prefix_bucket], + prompt_tokens=100, + prompt_tokens_stdev=10, + prompt_tokens_min=50, + prompt_tokens_max=150, + output_tokens=30, + output_tokens_stdev=5, + output_tokens_min=20, + output_tokens_max=40, + source="custom_text.txt", + ) + + assert config.prefix_buckets[0].prefix_tokens == 5 # type: ignore [index] + assert config.prompt_tokens == 100 + assert config.prompt_tokens_stdev == 10 + assert config.prompt_tokens_min == 50 + assert config.prompt_tokens_max == 150 + assert config.output_tokens == 30 + assert config.output_tokens_stdev == 5 + assert config.output_tokens_min == 20 + assert config.output_tokens_max == 40 + assert config.source == "custom_text.txt" + + @pytest.mark.regression + def test_parse_json_string(self): + """Test parsing JSON string configuration. + + ### WRITTEN BY AI ### + """ + json_str = json.dumps( + { + "prompt_tokens": 75, + "output_tokens": 25, + "source": "test.txt", + "prefix_buckets": [ + {"bucket_weight": 100, "prefix_count": 1, "prefix_tokens": 10} + ], + } + ) + + config = SyntheticTextDatasetConfig.model_validate_json(json_str) + + assert config.prompt_tokens == 75 + assert config.output_tokens == 25 + assert config.source == "test.txt" + assert config.prefix_buckets[0].prefix_tokens == 10 # type: ignore [index] + + @pytest.mark.sanity + def test_validation_positive_values(self): + """Test that negative or zero values are rejected. + + ### WRITTEN BY AI ### + """ + with pytest.raises(ValueError): + SyntheticTextDatasetConfig(prompt_tokens=0, output_tokens=20) + + with pytest.raises(ValueError): + SyntheticTextDatasetConfig(prompt_tokens=20, output_tokens=0) + + # Test negative prefix tokens via PrefixBucketConfig validation + with pytest.raises(ValueError): + SyntheticTextPrefixBucketConfig(prefix_tokens=-1) + + @pytest.mark.regression + def test_validation_optional_positive_values(self): + """Test that optional parameters reject negative values. + + ### WRITTEN BY AI ### + """ + with pytest.raises(ValueError): + SyntheticTextDatasetConfig( + prompt_tokens=20, output_tokens=10, prompt_tokens_stdev=-1 + ) + + with pytest.raises(ValueError): + SyntheticTextDatasetConfig( + prompt_tokens=20, output_tokens=10, prompt_tokens_min=-1 + ) + + with pytest.raises(ValueError): + SyntheticTextDatasetConfig( + prompt_tokens=20, output_tokens=10, output_tokens_max=0 + ) + + +class TestSyntheticTextGenerator: + """Test cases for SyntheticTextGenerator class. + + ### WRITTEN BY AI ### + """ + + @pytest.fixture + def mock_tokenizer(self): + """Fixture to provide a mocked tokenizer. + + ### WRITTEN BY AI ### + """ + tokenizer = Mock() + tokenizer.encode.side_effect = lambda text: list(range(len(text.split()))) + tokenizer.decode.side_effect = ( + lambda tokens, skip_special_tokens=False: " ".join( + f"token_{t}" for t in tokens[:5] + ) + ) + return tokenizer + + @pytest.fixture + def simple_config(self): + """Fixture for simple configuration. + + ### WRITTEN BY AI ### + """ + return SyntheticTextDatasetConfig( + prompt_tokens=15, + output_tokens=10, + source="The quick brown fox jumps over the lazy dog.", + ) + + @pytest.fixture + def config_with_prefix(self): + """Fixture for configuration with prefix tokens. + + ### WRITTEN BY AI ### + """ + prefix_bucket = SyntheticTextPrefixBucketConfig( + bucket_weight=100, prefix_count=1, prefix_tokens=3 + ) + + return SyntheticTextDatasetConfig( + prefix_buckets=[prefix_bucket], + prompt_tokens=15, + output_tokens=10, + source="The quick brown fox jumps over the lazy dog.", + ) + + @pytest.mark.smoke + def test_generator_initialization(self, simple_config, mock_tokenizer): + """Test generator initialization. + + ### WRITTEN BY AI ### + """ + generator = SyntheticTextGenerator( + simple_config, mock_tokenizer, random_seed=42 + ) + + assert generator.config == simple_config + assert generator.processor == mock_tokenizer + assert generator.random_seed == 42 + + @pytest.mark.smoke + def test_basic_iteration(self, simple_config, mock_tokenizer): + """Test basic iteration functionality. + + ### WRITTEN BY AI ### + """ + generator = SyntheticTextGenerator( + simple_config, mock_tokenizer, random_seed=42 + ) + + items = [] + for i, item in enumerate(generator): + items.append(item) + if i >= 4: # Only get 5 items + break + + # Verify we get the expected number of items + assert len(items) == 5 + + # Verify each item has the required keys + for item in items: + assert "prefix" in item + assert "prompt" in item + assert "prompt_tokens_count" in item + assert "output_tokens_count" in item + assert isinstance(item["prefix"], str) + assert isinstance(item["prompt"], str) + assert isinstance(item["prompt_tokens_count"], int) + assert isinstance(item["output_tokens_count"], int) + + @pytest.mark.sanity + def test_create_prompt_method(self, simple_config, mock_tokenizer): + """Test _create_prompt method. + + ### WRITTEN BY AI ### + """ + from faker import Faker + + generator = SyntheticTextGenerator( + simple_config, mock_tokenizer, random_seed=42 + ) + faker = Faker() + faker.seed_instance(42) + + # Test normal case + result = generator._create_prompt(5, faker, "unique_prefix ") + assert isinstance(result, str) + # The result should be the decoded tokens (token_0 token_1 etc.) due to our mock + assert "token_" in result + + # Test zero tokens + result = generator._create_prompt(0, faker) + assert result == "" + + @pytest.mark.regression + def test_prefix_tokens_integration(self, config_with_prefix, mock_tokenizer): + """Test integration with prefix tokens. + + ### WRITTEN BY AI ### + """ + generator = SyntheticTextGenerator( + config_with_prefix, mock_tokenizer, random_seed=42 + ) + + items = [] + for i, item in enumerate(generator): + items.append(item) + if i >= 2: # Only get 3 items + break + + # Verify prefix is present in items + for item in items: + assert isinstance(item["prefix"], str) + + @pytest.mark.regression + def test_random_seeding_consistency(self, simple_config, mock_tokenizer): + """Test that same seed produces consistent results. + + ### WRITTEN BY AI ### + """ + # Create two generators with same seed + generator1 = SyntheticTextGenerator( + simple_config, mock_tokenizer, random_seed=42 + ) + generator2 = SyntheticTextGenerator( + simple_config, mock_tokenizer, random_seed=42 + ) + + items1 = [] + items2 = [] + for i, (item1, item2) in enumerate(zip(generator1, generator2)): + items1.append(item1) + items2.append(item2) + if i >= 2: # Only get 3 items + break + + # With same seed and deterministic mocks, results should be identical + assert len(items1) == len(items2) + for item1, item2 in zip(items1, items2): + assert item1["prompt_tokens_count"] == item2["prompt_tokens_count"] + assert item1["output_tokens_count"] == item2["output_tokens_count"] + + +class TestSyntheticDatasetDeserializer: + """Test cases for SyntheticDatasetDeserializer class. + + ### WRITTEN BY AI ### + """ + + @pytest.fixture + def mock_tokenizer(self): + """Fixture to provide a mocked tokenizer. + + ### WRITTEN BY AI ### + """ + tokenizer = Mock() + tokenizer.encode.side_effect = lambda text: list(range(len(text.split()))) + tokenizer.decode.side_effect = ( + lambda tokens, skip_special_tokens=False: " ".join( + f"token_{t}" for t in tokens[:5] + ) + ) + return tokenizer + + @pytest.mark.sanity + def test_load_config_file_yaml(self): + """Test loading YAML config file. + + ### WRITTEN BY AI ### + """ + config_data = { + "prompt_tokens": 60, + "output_tokens": 15, + "source": "yaml_test.txt", + "prefix_buckets": [ + {"bucket_weight": 100, "prefix_count": 1, "prefix_tokens": 3} + ], + } + + with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: + yaml.dump(config_data, f) + yaml_path = f.name + + try: + deserializer = SyntheticTextDatasetDeserializer() + config = deserializer._load_config_file(yaml_path) + + assert config.prompt_tokens == 60 + assert config.output_tokens == 15 + assert config.source == "yaml_test.txt" + assert config.prefix_buckets[0].prefix_tokens == 3 # type: ignore [index] + finally: + Path(yaml_path).unlink() + + @pytest.mark.sanity + def test_load_config_file_config_extension(self): + """Test loading .config file. + + ### WRITTEN BY AI ### + """ + config_data = { + "prompt_tokens": 90, + "output_tokens": 35, + "prefix_buckets": [ + {"bucket_weight": 100, "prefix_count": 1, "prefix_tokens": 2} + ], + } + + with tempfile.NamedTemporaryFile(mode="w", suffix=".config", delete=False) as f: + yaml.dump(config_data, f) + config_path = f.name + + try: + deserializer = SyntheticTextDatasetDeserializer() + config = deserializer._load_config_file(config_path) + + assert config.prompt_tokens == 90 + assert config.output_tokens == 35 + assert config.prefix_buckets[0].prefix_tokens == 2 # type: ignore [index] + finally: + Path(config_path).unlink() + + @pytest.mark.smoke + def test_load_config_str_json(self): + """Test loading JSON string config. + + ### WRITTEN BY AI ### + """ + json_str = '{"prompt_tokens": 50, "output_tokens": 25}' + deserializer = SyntheticTextDatasetDeserializer() + config = deserializer._load_config_str(json_str) + + assert config.prompt_tokens == 50 + assert config.output_tokens == 25 + + @pytest.mark.smoke + def test_load_config_str_key_value(self): + """Test loading key-value string config. + + ### WRITTEN BY AI ### + """ + kv_str = "prompt_tokens=50,output_tokens=25" + deserializer = SyntheticTextDatasetDeserializer() + config = deserializer._load_config_str(kv_str) + + assert config.prompt_tokens == 50 + assert config.output_tokens == 25 + + @pytest.mark.sanity + def test_load_config_str_invalid_format(self): + """Test loading invalid format raises DataNotSupportedError. + + ### WRITTEN BY AI ### + """ + deserializer = SyntheticTextDatasetDeserializer() + with pytest.raises(DataNotSupportedError, match="Unsupported string data"): + deserializer._load_config_str("invalid_format_string") + + @pytest.mark.regression + def test_load_config_file_non_existent(self): + """Test loading non-existent file returns None. + + ### WRITTEN BY AI ### + """ + deserializer = SyntheticTextDatasetDeserializer() + config = deserializer._load_config_file("/non/existent/path.config") + assert config is None + + @pytest.mark.regression + def test_load_config_str_non_string(self): + """Test loading non-string returns None. + + ### WRITTEN BY AI ### + """ + deserializer = SyntheticTextDatasetDeserializer() + config = deserializer._load_config_str(123) + assert config is None + + @pytest.mark.smoke + def test_call_with_config_object(self, mock_tokenizer): + """Test calling deserializer with SyntheticTextDatasetConfig. + + ### WRITTEN BY AI ### + """ + config = SyntheticTextDatasetConfig(prompt_tokens=50, output_tokens=25) + deserializer = SyntheticTextDatasetDeserializer() + + result = deserializer( + data=config, + data_kwargs={}, + processor_factory=lambda: mock_tokenizer, + random_seed=42, + ) + + assert isinstance(result, IterableDataset) + + @pytest.mark.regression + def test_call_with_unsupported_data(self, mock_tokenizer): + """Test calling deserializer with unsupported data raises error. + + ### WRITTEN BY AI ### + """ + deserializer = SyntheticTextDatasetDeserializer() + + with pytest.raises(DataNotSupportedError, match="Unsupported data"): + deserializer( + data=123, + data_kwargs={}, + processor_factory=lambda: mock_tokenizer, + random_seed=42, + ) + + @pytest.mark.regression + def test_call_with_json_string(self, mock_tokenizer): + """Test calling deserializer with JSON string. + + ### WRITTEN BY AI ### + """ + json_str = '{"prompt_tokens": 50, "output_tokens": 25}' + deserializer = SyntheticTextDatasetDeserializer() + + result = deserializer( + data=json_str, + data_kwargs={}, + processor_factory=lambda: mock_tokenizer, + random_seed=42, + ) + + assert isinstance(result, IterableDataset) + + @pytest.mark.regression + def test_call_with_config_file(self, mock_tokenizer): + """Test calling deserializer with config file. + + ### WRITTEN BY AI ### + """ + config_data = {"prompt_tokens": 65, "output_tokens": 45} + + with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: + yaml.dump(config_data, f) + config_path = f.name + + try: + deserializer = SyntheticTextDatasetDeserializer() + result = deserializer( + data=config_path, + data_kwargs={}, + processor_factory=lambda: mock_tokenizer, + random_seed=42, + ) + assert isinstance(result, IterableDataset) + finally: + Path(config_path).unlink() diff --git a/tests/unit/dataset/test_synthetic.py b/tests/unit/dataset/test_synthetic.py deleted file mode 100644 index e3110fa3..00000000 --- a/tests/unit/dataset/test_synthetic.py +++ /dev/null @@ -1,873 +0,0 @@ -""" -Unit tests for guidellm.dataset.synthetic module. -""" - -import json -import tempfile -from pathlib import Path -from unittest.mock import Mock, patch - -import pytest -import yaml - -from guidellm.dataset.synthetic import ( - SyntheticDatasetConfig, - SyntheticDatasetCreator, - SyntheticTextItemsGenerator, -) - - -class TestSyntheticDatasetConfig: - """Test cases for SyntheticDatasetConfig class. - - ### WRITTEN BY AI ### - """ - - @pytest.mark.smoke - def test_config_creation_with_all_params(self): - """Test creating config with all parameters specified. - - ### WRITTEN BY AI ### - """ - config = SyntheticDatasetConfig( - prefix_tokens=5, - prompt_tokens=100, - prompt_tokens_stdev=10, - prompt_tokens_min=50, - prompt_tokens_max=150, - output_tokens=30, - output_tokens_stdev=5, - output_tokens_min=20, - output_tokens_max=40, - samples=500, - source="custom_text.txt", - ) - - assert config.prefix_tokens == 5 - assert config.prompt_tokens == 100 - assert config.prompt_tokens_stdev == 10 - assert config.prompt_tokens_min == 50 - assert config.prompt_tokens_max == 150 - assert config.output_tokens == 30 - assert config.output_tokens_stdev == 5 - assert config.output_tokens_min == 20 - assert config.output_tokens_max == 40 - assert config.samples == 500 - assert config.source == "custom_text.txt" - - @pytest.mark.regression - def test_parse_json_string(self): - """Test parsing JSON string configuration. - - ### WRITTEN BY AI ### - """ - json_str = json.dumps( - { - "prompt_tokens": 75, - "output_tokens": 25, - "samples": 200, - "source": "test.txt", - "prefix_tokens": 10, - } - ) - - config = SyntheticDatasetConfig.parse_str(json_str) - - assert config.prompt_tokens == 75 - assert config.output_tokens == 25 - assert config.samples == 200 - assert config.source == "test.txt" - assert config.prefix_tokens == 10 - - @pytest.mark.regression - def test_parse_key_value_pairs(self): - """Test parsing key-value pairs configuration. - - ### WRITTEN BY AI ### - """ - kv_str = "prompt_tokens=80,output_tokens=30,samples=300,source=data.txt,prefix_tokens=5" # noqa: E501 - - config = SyntheticDatasetConfig.parse_str(kv_str) - - assert config.prompt_tokens == 80 - assert config.output_tokens == 30 - assert config.samples == 300 - assert config.source == "data.txt" - assert config.prefix_tokens == 5 - - @pytest.mark.sanity - def test_parse_yaml_file(self): - """Test parsing YAML file configuration. - - ### WRITTEN BY AI ### - """ - config_data = { - "prompt_tokens": 60, - "output_tokens": 15, - "samples": 100, - "source": "yaml_test.txt", - "prefix_tokens": 3, - } - - with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: - yaml.dump(config_data, f) - yaml_path = f.name - - try: - config = SyntheticDatasetConfig.parse_str(yaml_path) - - assert config.prompt_tokens == 60 - assert config.output_tokens == 15 - assert config.samples == 100 - assert config.source == "yaml_test.txt" - assert config.prefix_tokens == 3 - finally: - Path(yaml_path).unlink() - - @pytest.mark.sanity - def test_parse_config_file(self): - """Test parsing .config file. - - ### WRITTEN BY AI ### - """ - config_data = { - "prompt_tokens": 90, - "output_tokens": 35, - "samples": 150, - "prefix_tokens": 2, - } - - with tempfile.NamedTemporaryFile(mode="w", suffix=".config", delete=False) as f: - yaml.dump(config_data, f) - config_path = f.name - - try: - config = SyntheticDatasetConfig.parse_str(config_path) - - assert config.prompt_tokens == 90 - assert config.output_tokens == 35 - assert config.samples == 150 - assert config.prefix_tokens == 2 - finally: - Path(config_path).unlink() - - @pytest.mark.regression - def test_parse_path_object(self): - """Test parsing with Path object. - - ### WRITTEN BY AI ### - """ - config_data = {"prompt_tokens": 45, "output_tokens": 25} - - with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: - yaml.dump(config_data, f) - yaml_path = Path(f.name) - - try: - config = SyntheticDatasetConfig.parse_str(yaml_path) - assert config.prompt_tokens == 45 - assert config.output_tokens == 25 - finally: - yaml_path.unlink() - - @pytest.mark.sanity - def test_parse_invalid_format(self): - """Test parsing invalid format raises ValueError. - - ### WRITTEN BY AI ### - """ - with pytest.raises(ValueError, match="Unsupported data format"): - SyntheticDatasetConfig.parse_str("invalid_format_string") - - @pytest.mark.sanity - def test_validation_positive_values(self): - """Test that negative or zero values are rejected. - - ### WRITTEN BY AI ### - """ - with pytest.raises(ValueError): - SyntheticDatasetConfig(prompt_tokens=0, output_tokens=20) - - with pytest.raises(ValueError): - SyntheticDatasetConfig(prompt_tokens=20, output_tokens=0) - - with pytest.raises(ValueError): - SyntheticDatasetConfig(prompt_tokens=20, output_tokens=10, samples=0) - - with pytest.raises(ValueError): - SyntheticDatasetConfig(prompt_tokens=20, output_tokens=10, prefix_tokens=-1) - - @pytest.mark.regression - def test_validation_optional_positive_values(self): - """Test that optional parameters reject negative values. - - ### WRITTEN BY AI ### - """ - with pytest.raises(ValueError): - SyntheticDatasetConfig( - prompt_tokens=20, output_tokens=10, prompt_tokens_stdev=-1 - ) - - with pytest.raises(ValueError): - SyntheticDatasetConfig( - prompt_tokens=20, output_tokens=10, prompt_tokens_min=-1 - ) - - with pytest.raises(ValueError): - SyntheticDatasetConfig( - prompt_tokens=20, output_tokens=10, output_tokens_max=0 - ) - - @pytest.mark.regression - def test_parse_json_method_directly(self): - """Test parse_json static method directly. - - ### WRITTEN BY AI ### - """ - json_data = {"prompt_tokens": 100, "output_tokens": 50} - json_str = json.dumps(json_data) - - config = SyntheticDatasetConfig.parse_json(json_str) - - assert config.prompt_tokens == 100 - assert config.output_tokens == 50 - - @pytest.mark.regression - def test_parse_key_value_pairs_method_directly(self): - """Test parse_key_value_pairs static method directly. - - ### WRITTEN BY AI ### - """ - kv_str = "prompt_tokens=75,output_tokens=35" - - config = SyntheticDatasetConfig.parse_key_value_pairs(kv_str) - - assert config.prompt_tokens == 75 - assert config.output_tokens == 35 - - @pytest.mark.regression - def test_parse_config_file_method_directly(self): - """Test parse_config_file static method directly. - - ### WRITTEN BY AI ### - """ - config_data = {"prompt_tokens": 65, "output_tokens": 45} - - with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f: - yaml.dump(config_data, f) - config_path = f.name - - try: - config = SyntheticDatasetConfig.parse_config_file(config_path) - assert config.prompt_tokens == 65 - assert config.output_tokens == 45 - finally: - Path(config_path).unlink() - - -class TestSyntheticTextItemsGenerator: - """Test cases for SyntheticTextItemsGenerator class. - - ### WRITTEN BY AI ### - """ - - @pytest.fixture - def mock_tokenizer(self): - """Fixture to provide a mocked tokenizer. - - ### WRITTEN BY AI ### - """ - tokenizer = Mock() - tokenizer.get_vocab.return_value = {f"token_{i}": i for i in range(1000)} - tokenizer.encode.side_effect = lambda text: [1, 2, 3] * (len(text) // 10 + 1) - tokenizer.decode.side_effect = ( - lambda tokens, skip_special_tokens=False: " ".join( - f"token_{t}" for t in tokens[:5] - ) - ) - return tokenizer - - @pytest.fixture - def simple_config(self): - """Fixture for simple configuration. - - ### WRITTEN BY AI ### - """ - return SyntheticDatasetConfig( - prompt_tokens=15, - output_tokens=10, - samples=5, - source="The quick brown fox jumps over the lazy dog.", - ) - - @pytest.fixture - def config_with_prefix(self): - """Fixture for configuration with prefix tokens. - - ### WRITTEN BY AI ### - """ - return SyntheticDatasetConfig( - prefix_tokens=3, - prompt_tokens=15, - output_tokens=10, - samples=5, - source="The quick brown fox jumps over the lazy dog.", - ) - - @pytest.fixture - def complex_config(self): - """Fixture for complex configuration with variance. - - ### WRITTEN BY AI ### - """ - return SyntheticDatasetConfig( - prompt_tokens=20, - prompt_tokens_stdev=5, - prompt_tokens_min=10, - prompt_tokens_max=30, - output_tokens=15, - output_tokens_stdev=3, - output_tokens_min=10, - output_tokens_max=20, - samples=10, - source="The quick brown fox jumps over the lazy dog.", - ) - - @pytest.mark.smoke - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - def test_generator_initialization( - self, mock_text_creator, simple_config, mock_tokenizer - ): - """Test generator initialization. - - ### WRITTEN BY AI ### - """ - generator = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - - assert generator.config == simple_config - assert generator.processor == mock_tokenizer - assert generator.random_seed == 42 - mock_text_creator.assert_called_once_with(data=simple_config.source) - - @pytest.mark.smoke - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - @patch("guidellm.dataset.synthetic.IntegerRangeSampler") - def test_basic_iteration( - self, mock_sampler, mock_text_creator, simple_config, mock_tokenizer - ): - """Test basic iteration functionality. - - ### WRITTEN BY AI ### - """ - # Setup mocks - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word1", "word2", "word3"] * 100 - mock_text_creator_instance.create_text.return_value = "sample text" - mock_text_creator.return_value = mock_text_creator_instance - - # Mock IntegerRangeSampler to return iterators - def mock_sampler_side_effect(*args, **kwargs): - mock_instance = Mock() - mock_instance.__iter__ = Mock(return_value=iter([15, 15, 15, 15, 15])) - return mock_instance - - mock_sampler.side_effect = mock_sampler_side_effect - - generator = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - - items = list(generator) - - # Verify we get the expected number of items - assert len(items) == simple_config.samples - - # Verify each item has the required keys - for item in items: - assert "prompt" in item - assert "prompt_tokens_count" in item - assert "output_tokens_count" in item - assert isinstance(item["prompt"], str) - assert isinstance(item["prompt_tokens_count"], int) - assert isinstance(item["output_tokens_count"], int) - - @pytest.mark.sanity - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - def test_create_prompt_method( - self, mock_text_creator, simple_config, mock_tokenizer - ): - """Test _create_prompt method. - - ### WRITTEN BY AI ### - """ - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word"] * 100 - mock_text_creator_instance.create_text.return_value = "test text" - mock_text_creator.return_value = mock_text_creator_instance - - mock_tokenizer.encode.return_value = [1, 2, 3] - - generator = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - - # Test normal case - result = generator._create_prompt(5, 0, 42) - assert result == [42, 1, 2, 3] - - # Test zero tokens - result = generator._create_prompt(0, 0, 42) - assert result == [] - - # Test without unique prefix - result = generator._create_prompt(3, 0) - assert result == [1, 2, 3] - - @pytest.mark.regression - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - def test_create_prompt_binary_search( - self, mock_text_creator, simple_config, mock_tokenizer - ): - """Test binary search logic in _create_prompt. - - ### WRITTEN BY AI ### - """ - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word"] * 1000 - mock_text_creator_instance.create_text.side_effect = lambda start, length: ( - "text " * max(1, length // 4) - ).strip() - mock_text_creator.return_value = mock_text_creator_instance - - # Mock tokenizer to return different lengths based on input - def mock_encode(text): - return [1] * len(text.split()) - - mock_tokenizer.encode.side_effect = mock_encode - - generator = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - - # Test that binary search finds appropriate length - result = generator._create_prompt(5, 0, 42) - assert len(result) >= 4 # Should include prefix + some tokens - - @pytest.mark.sanity - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - @patch("guidellm.dataset.synthetic.IntegerRangeSampler") - def test_prefix_tokens_integration( - self, mock_sampler, mock_text_creator, config_with_prefix, mock_tokenizer - ): - """Test integration with prefix tokens. - - ### WRITTEN BY AI ### - """ - # Setup mocks - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word"] * 100 - mock_text_creator_instance.create_text.return_value = "sample text" - mock_text_creator.return_value = mock_text_creator_instance - - mock_sampler_instance = Mock() - mock_sampler_instance.__iter__ = Mock(return_value=iter([15, 15, 15, 15, 15])) - mock_sampler.return_value = mock_sampler_instance - - generator = SyntheticTextItemsGenerator( - config_with_prefix, mock_tokenizer, random_seed=42 - ) - - items = list(generator) - - # Verify prompt_tokens_count includes prefix - for item in items: - assert item["prompt_tokens_count"] == config_with_prefix.prefix_tokens + 15 - - @pytest.mark.regression - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - @patch("guidellm.dataset.synthetic.IntegerRangeSampler") - def test_random_seeding_consistency( - self, mock_sampler, mock_text_creator, simple_config, mock_tokenizer - ): - """Test that same seed produces consistent results. - - ### WRITTEN BY AI ### - """ - # Setup mocks - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word"] * 100 - mock_text_creator_instance.create_text.return_value = "sample text" - mock_text_creator.return_value = mock_text_creator_instance - - # Create consistent mock sampler behavior - call_count = 0 - - def mock_sampler_side_effect(*args, **kwargs): - nonlocal call_count - mock_instance = Mock() - # Return same sequence for both prompt and output tokens - if call_count % 2 == 0: # prompt tokens - mock_instance.__iter__ = Mock(return_value=iter([15, 16, 17, 18, 19])) - else: # output tokens - mock_instance.__iter__ = Mock(return_value=iter([10, 11, 12, 13, 14])) - call_count += 1 - return mock_instance - - mock_sampler.side_effect = mock_sampler_side_effect - - # Create two generators with same seed - generator1 = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - generator2 = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - - items1 = list(generator1) - items2 = list(generator2) - - # Results should be identical with same seed - assert len(items1) == len(items2) - for item1, item2 in zip(items1, items2): - assert item1["prompt"] == item2["prompt"] - assert item1["prompt_tokens_count"] == item2["prompt_tokens_count"] - assert item1["output_tokens_count"] == item2["output_tokens_count"] - - @pytest.mark.regression - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - @patch("guidellm.dataset.synthetic.IntegerRangeSampler") - def test_variance_configuration( - self, mock_sampler, mock_text_creator, complex_config, mock_tokenizer - ): - """Test that variance configuration is properly used. - - ### WRITTEN BY AI ### - """ - # Setup mocks - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word"] * 100 - mock_text_creator_instance.create_text.return_value = "sample text" - mock_text_creator.return_value = mock_text_creator_instance - - # Fix tokenizer mock to handle the create_text return properly - mock_tokenizer.encode.side_effect = ( - lambda text: [1, 2, 3] if isinstance(text, str) else [1, 2, 3] - ) - - # Setup mock sampler to track calls - def mock_sampler_side_effect(*args, **kwargs): - mock_instance = Mock() - mock_instance.__iter__ = Mock(return_value=iter([20, 18, 22, 19, 21] * 2)) - return mock_instance - - mock_sampler.side_effect = mock_sampler_side_effect - - generator = SyntheticTextItemsGenerator( - complex_config, mock_tokenizer, random_seed=42 - ) - - # Initialize the generator to trigger sampler creation - generator_iter = iter(generator) - next(generator_iter) - - # Verify that IntegerRangeSampler is called with correct parameters - assert mock_sampler.call_count == 2 - - # Check prompt tokens sampler call - prompt_call = mock_sampler.call_args_list[0] - assert prompt_call[1]["average"] == complex_config.prompt_tokens - assert prompt_call[1]["variance"] == complex_config.prompt_tokens_stdev - assert prompt_call[1]["min_value"] == complex_config.prompt_tokens_min - assert prompt_call[1]["max_value"] == complex_config.prompt_tokens_max - assert prompt_call[1]["random_seed"] == 42 - - # Check output tokens sampler call - output_call = mock_sampler.call_args_list[1] - assert output_call[1]["average"] == complex_config.output_tokens - assert output_call[1]["variance"] == complex_config.output_tokens_stdev - assert output_call[1]["min_value"] == complex_config.output_tokens_min - assert output_call[1]["max_value"] == complex_config.output_tokens_max - assert output_call[1]["random_seed"] == 43 # 42 + 1 - - @pytest.mark.regression - @patch("guidellm.dataset.synthetic.EndlessTextCreator") - def test_unique_prefix_generation( - self, mock_text_creator, simple_config, mock_tokenizer - ): - """Test that unique prefixes are generated for each request. - - ### WRITTEN BY AI ### - """ - mock_text_creator_instance = Mock() - mock_text_creator_instance.words = ["word"] * 100 - mock_text_creator_instance.create_text.return_value = "sample text" - mock_text_creator.return_value = mock_text_creator_instance - - # Mock the cycle to return predictable values - with patch("guidellm.dataset.synthetic.cycle") as mock_cycle: - mock_cycle.return_value = iter([100, 101, 102, 103, 104]) - - generator = SyntheticTextItemsGenerator( - simple_config, mock_tokenizer, random_seed=42 - ) - - # Access the iterator to trigger the cycle creation - generator_iter = iter(generator) - next(generator_iter) - - # Verify cycle was called with vocab values - mock_cycle.assert_called_once() - - -class TestSyntheticDatasetCreator: - """Test cases for SyntheticDatasetCreator class. - - ### WRITTEN BY AI ### - """ - - @pytest.mark.sanity - def test_is_supported_path_config_file(self): - """Test is_supported with config file paths. - - ### WRITTEN BY AI ### - """ - with tempfile.NamedTemporaryFile(suffix=".config", delete=False) as f: - config_path = Path(f.name) - - try: - assert SyntheticDatasetCreator.is_supported(config_path, None) - finally: - config_path.unlink() - - @pytest.mark.sanity - def test_is_supported_path_yaml_file(self): - """Test is_supported with YAML file paths. - - ### WRITTEN BY AI ### - """ - with tempfile.NamedTemporaryFile(suffix=".yaml", delete=False) as f: - yaml_path = Path(f.name) - - try: - assert SyntheticDatasetCreator.is_supported(yaml_path, None) - finally: - yaml_path.unlink() - - @pytest.mark.smoke - def test_is_supported_json_string(self): - """Test is_supported with JSON string. - - ### WRITTEN BY AI ### - """ - json_str = '{"prompt_tokens": 50, "output_tokens": 25}' - assert SyntheticDatasetCreator.is_supported(json_str, None) - - @pytest.mark.smoke - def test_is_supported_key_value_string(self): - """Test is_supported with key-value string. - - ### WRITTEN BY AI ### - """ - kv_str = "prompt_tokens=50,output_tokens=25" - assert SyntheticDatasetCreator.is_supported(kv_str, None) - - @pytest.mark.sanity - def test_is_supported_config_filename_string(self): - """Test is_supported with config filename string. - - ### WRITTEN BY AI ### - """ - assert SyntheticDatasetCreator.is_supported("config.yaml", None) - assert SyntheticDatasetCreator.is_supported("settings.config", None) - - @pytest.mark.sanity - def test_is_not_supported_regular_string(self): - """Test is_supported returns False for regular strings. - - ### WRITTEN BY AI ### - """ - assert not SyntheticDatasetCreator.is_supported("regular string", None) - assert not SyntheticDatasetCreator.is_supported("single=pair", None) - - @pytest.mark.regression - def test_is_not_supported_non_existent_path(self): - """Test is_supported returns False for non-existent paths. - - ### WRITTEN BY AI ### - """ - non_existent_path = Path("/non/existent/path.config") - assert not SyntheticDatasetCreator.is_supported(non_existent_path, None) - - @pytest.mark.regression - def test_is_not_supported_other_types(self): - """Test is_supported returns False for other data types. - - ### WRITTEN BY AI ### - """ - assert not SyntheticDatasetCreator.is_supported(123, None) - assert not SyntheticDatasetCreator.is_supported(["list"], None) - assert not SyntheticDatasetCreator.is_supported({"dict": "value"}, None) - - @pytest.mark.smoke - @patch("guidellm.dataset.synthetic.check_load_processor") - @patch("guidellm.dataset.synthetic.SyntheticTextItemsGenerator") - @patch("guidellm.dataset.synthetic.Dataset") - def test_handle_create_basic( - self, mock_dataset, mock_generator, mock_check_processor - ): - """Test handle_create basic functionality. - - ### WRITTEN BY AI ### - """ - # Setup mocks - mock_processor = Mock() - mock_check_processor.return_value = mock_processor - - mock_generator_instance = Mock() - mock_generator_instance.__iter__ = Mock( - return_value=iter( - [ - { - "prompt": "test", - "prompt_tokens_count": 10, - "output_tokens_count": 5, - } - ] - ) - ) - mock_generator.return_value = mock_generator_instance - - mock_dataset_instance = Mock() - mock_dataset.from_list.return_value = mock_dataset_instance - - # Test - data = '{"prompt_tokens": 50, "output_tokens": 25}' - result = SyntheticDatasetCreator.handle_create( - data=data, - data_args=None, - processor="gpt2", - processor_args=None, - random_seed=42, - ) - - # Verify - mock_check_processor.assert_called_once_with( - "gpt2", - None, - error_msg="Processor/tokenizer required for synthetic dataset generation.", - ) - mock_generator.assert_called_once() - mock_dataset.from_list.assert_called_once() - assert result == mock_dataset_instance - - @pytest.mark.sanity - @patch("guidellm.dataset.synthetic.check_load_processor") - def test_handle_create_processor_required(self, mock_check_processor): - """Test handle_create requires processor. - - ### WRITTEN BY AI ### - """ - mock_check_processor.side_effect = ValueError("Processor required") - - data = '{"prompt_tokens": 50, "output_tokens": 25}' - - with pytest.raises(ValueError, match="Processor required"): - SyntheticDatasetCreator.handle_create( - data=data, - data_args=None, - processor=None, - processor_args=None, - random_seed=42, - ) - - @pytest.mark.regression - @patch("guidellm.dataset.synthetic.check_load_processor") - @patch("guidellm.dataset.synthetic.SyntheticTextItemsGenerator") - @patch("guidellm.dataset.synthetic.Dataset") - def test_handle_create_with_data_args( - self, mock_dataset, mock_generator, mock_check_processor - ): - """Test handle_create with data_args. - - ### WRITTEN BY AI ### - """ - # Setup mocks - mock_processor = Mock() - mock_check_processor.return_value = mock_processor - - mock_generator_instance = Mock() - mock_generator_instance.__iter__ = Mock(return_value=iter([])) - mock_generator.return_value = mock_generator_instance - - mock_dataset_instance = Mock() - mock_dataset.from_list.return_value = mock_dataset_instance - - # Test with data_args - data = '{"prompt_tokens": 50, "output_tokens": 25}' - data_args = {"features": "custom_features"} - - SyntheticDatasetCreator.handle_create( - data=data, - data_args=data_args, - processor="gpt2", - processor_args=None, - random_seed=42, - ) - - # Verify data_args are passed to Dataset.from_list - mock_dataset.from_list.assert_called_once_with([], **data_args) - - @pytest.mark.sanity - def test_extract_args_column_mappings_empty(self): - """Test extract_args_column_mappings with empty data_args. - - ### WRITTEN BY AI ### - """ - result = SyntheticDatasetCreator.extract_args_column_mappings(None) - - expected = { - "prompt_column": "prompt", - "prompt_tokens_count_column": "prompt_tokens_count", - "output_tokens_count_column": "output_tokens_count", - } - assert result == expected - - @pytest.mark.regression - def test_extract_args_column_mappings_with_parent_mappings(self): - """Test extract_args_column_mappings rejects column mappings. - - ### WRITTEN BY AI ### - """ - with ( - patch.object( - SyntheticDatasetCreator.__bases__[0], - "extract_args_column_mappings", - return_value={"prompt_column": "custom_prompt"}, - ), - pytest.raises(ValueError, match="Column mappings are not supported"), - ): - SyntheticDatasetCreator.extract_args_column_mappings({"some": "args"}) - - @pytest.mark.regression - def test_extract_args_column_mappings_no_parent_mappings(self): - """Test extract_args_column_mappings with no parent mappings. - - ### WRITTEN BY AI ### - """ - with patch.object( - SyntheticDatasetCreator.__bases__[0], - "extract_args_column_mappings", - return_value={}, - ): - result = SyntheticDatasetCreator.extract_args_column_mappings( - {"some": "args"} - ) - - expected = { - "prompt_column": "prompt", - "prompt_tokens_count_column": "prompt_tokens_count", - "output_tokens_count_column": "output_tokens_count", - } - assert result == expected From bbca65a81c60d0b7336d219d9546793103c4369b Mon Sep 17 00:00:00 2001 From: Mark Kurtz Date: Tue, 7 Oct 2025 10:21:42 -0400 Subject: [PATCH 3/3] Simplifications for new data pathways and reenablement of completions and chat completions pathways --- pyproject.toml | 16 +- src/guidellm/__main__.py | 124 ++++--- src/guidellm/benchmark/aggregator.py | 12 +- src/guidellm/benchmark/entrypoints.py | 118 ++++--- src/guidellm/data/__init__.py | 32 +- src/guidellm/data/collators.py | 16 + src/guidellm/data/datasets.py | 88 ----- .../data/deserializers/deserializer.py | 60 ++-- src/guidellm/data/deserializers/file.py | 16 +- .../data/deserializers/huggingface.py | 2 +- src/guidellm/data/deserializers/memory.py | 12 +- src/guidellm/data/deserializers/synthetic.py | 19 +- src/guidellm/data/formatters/__init__.py | 47 --- src/guidellm/data/formatters/environment.py | 63 ---- src/guidellm/data/formatters/globals.py | 9 - src/guidellm/data/formatters/objects.py | 92 ------ src/guidellm/data/formatters/templates.py | 182 ----------- src/guidellm/data/loaders.py | 136 ++++---- src/guidellm/data/objects.py | 121 ++----- src/guidellm/data/preprocessors/__init__.py | 20 +- src/guidellm/data/preprocessors/formatters.py | 303 ++++++++++++++++++ src/guidellm/data/preprocessors/mappers.py | 257 +++++++++------ src/guidellm/data/preprocessors/objects.py | 20 -- .../data/preprocessors/preprocessor.py | 29 ++ src/guidellm/data/processor.py | 30 ++ src/guidellm/data/utils/__init__.py | 34 ++ .../data/{utils.py => utils/dataset.py} | 78 +---- .../filters.py => utils/functions.py} | 156 +++++---- src/guidellm/scheduler/worker.py | 12 +- src/guidellm/scheduler/worker_group.py | 1 + src/guidellm/settings.py | 2 +- src/guidellm/utils/messaging.py | 4 + 32 files changed, 1000 insertions(+), 1111 deletions(-) create mode 100644 src/guidellm/data/collators.py delete mode 100644 src/guidellm/data/datasets.py delete mode 100644 src/guidellm/data/formatters/__init__.py delete mode 100644 src/guidellm/data/formatters/environment.py delete mode 100644 src/guidellm/data/formatters/globals.py delete mode 100644 src/guidellm/data/formatters/objects.py delete mode 100644 src/guidellm/data/formatters/templates.py create mode 100644 src/guidellm/data/preprocessors/formatters.py delete mode 100644 src/guidellm/data/preprocessors/objects.py create mode 100644 src/guidellm/data/preprocessors/preprocessor.py create mode 100644 src/guidellm/data/processor.py create mode 100644 src/guidellm/data/utils/__init__.py rename src/guidellm/data/{utils.py => utils/dataset.py} (54%) rename src/guidellm/data/{formatters/filters.py => utils/functions.py} (73%) diff --git a/pyproject.toml b/pyproject.toml index 7237e66d..3461530d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,25 +66,21 @@ dependencies = [ "protobuf", "pydantic>=2.11.7", "pydantic-settings>=2.0.0", + "pydub", "pyyaml>=6.0.0", "rich", "sanic", "transformers", "uvloop>=0.18", "librosa>=0.11.0", - "torch>=2.8.0", + "torch", ] [project.optional-dependencies] -perf = [ - "orjson", - "msgpack", - "msgspec", - "uvloop", -] +perf = ["orjson", "msgpack", "msgspec", "uvloop"] recommended = [ - "tiktoken>=0.11.0", # For OpenAI tokenizer - "blobfile>=3.1.0", # For OpenAI tokenizer + "tiktoken>=0.11.0", # For OpenAI tokenizer + "blobfile>=3.1.0", # For OpenAI tokenizer ] dev = [ # build @@ -127,7 +123,7 @@ dev = [ ] [dependency-groups] -dev = [ "guidellm[dev]" ] +dev = ["guidellm[dev]"] [project.urls] homepage = "https://github.com/vllm-project/guidellm" diff --git a/src/guidellm/__main__.py b/src/guidellm/__main__.py index 82632bc8..43939fa7 100644 --- a/src/guidellm/__main__.py +++ b/src/guidellm/__main__.py @@ -56,11 +56,7 @@ from guidellm.benchmark.scenario import ( GenerativeTextScenario, ) -from guidellm.data import ( - GenerativeDatasetArgs, - GenerativeRequestFormatter, - GenerativeRequestType, -) +from guidellm.data import GenerativeRequestType from guidellm.mock_server import MockServer, MockServerConfig from guidellm.preprocess.dataset import ShortPromptStrategy, process_dataset from guidellm.scheduler import StrategyType @@ -177,12 +173,6 @@ def benchmark(): "For rate-type=synchronous,throughput, this must not be set." ), ) -@click.option( - "--random-seed", - default=GenerativeTextScenario.get_default("random_seed"), - type=int, - help="The random seed to use for benchmarking to ensure reproducibility.", -) # Backend configuration @click.option( "--backend", @@ -216,6 +206,24 @@ def benchmark(): ), ) # Data configuration +@click.option( + "--request-type", + default="chat_completions", + type=click.Choice(list(get_literal_vals(GenerativeRequestType))), + help=( + "The type of request to create for each data sample and send to the backend. " + f"Supported types: {list(get_literal_vals(GenerativeRequestType))}." + ), +) +@click.option( + "--request-formatter-kwargs", + default=None, + callback=cli_tools.parse_json, + help=( + "A JSON string containing any arguments to pass to the request formatter " + "as a dict with **kwargs." + ), +) @click.option( "--processor", default=None, @@ -238,16 +246,7 @@ def benchmark(): @click.option( "--data-args", default=None, - callback=( - lambda _ctx, _param, value: [ - GenerativeDatasetArgs.model_validate_json(val) - if val - else GenerativeDatasetArgs() - for val in value - ] - if value - else None - ), + callback=cli_tools.parse_json, help=( "A JSON string containing any arguments to pass to the dataset creation " "as a dict with **kwargs." @@ -259,43 +258,30 @@ def benchmark(): type=int, help=( "The number of samples to use from the dataset. If -1 (default), will use all " - "samples in the dataset." + "samples in the dataset and dynamically generate samples. " + "If >1, will precompile that number of items from the dataset configs." ), ) @click.option( - "--data-sampler", - default=None, - type=click.Choice(["shuffle"]), - help="The data sampler type to use.", -) -@click.option( - "--data-request-type", - default="text_completions", - type=str, - help=( - "The type of request to create for each data sample. " - f"For example, {list(get_literal_vals(GenerativeRequestType))}." - ), -) -@click.option( - "--data-request-template", + "--data-column-mappings", default=None, + callback=cli_tools.parse_json, help=( - "A Jinja2 template string or path to a Jinja2 template file to use for " - "creating requests from the data samples. If not provided, will use a " - "default template based on the request type." + "A JSON string of column mappings to apply to the dataset to map into request " + "column types." ), ) @click.option( - "--data-request-extras", + "--data-sampler", default=None, - callback=cli_tools.parse_json, - help=("A JSON string of extra data to include with each data request."), + type=click.Choice(["shuffle"]), + help="The data sampler type to use.", ) @click.option( - "--data-request-nonstreaming", - is_flag=True, - help="Set this flag to disable streaming for the data requests.", + "--data-num-workers", + default=1, + type=int, + help="The number of worker processes to use for data loading.", ) @click.option( "--dataloader_kwargs", @@ -306,6 +292,12 @@ def benchmark(): "as a dict with **kwargs." ), ) +@click.option( + "--random-seed", + default=GenerativeTextScenario.get_default("random_seed"), + type=int, + help="The random seed to use for benchmarking to ensure reproducibility.", +) # Output configuration @click.option( "--output-path", @@ -435,22 +427,22 @@ def run( data, profile, rate, - random_seed, # Backend Configuration backend, backend_kwargs, model, # Data configuration + request_type, + request_formatter_kwargs, processor, processor_args, data_args, data_samples, + data_column_mappings, data_sampler, - data_request_type, - data_request_template, - data_request_extras, - data_request_nonstreaming, + data_num_workers, dataloader_kwargs, + random_seed, # Output configuration output_path, output_formats, @@ -478,6 +470,12 @@ def run( Supports multiple backends, data sources, output formats, and constraint types for flexible benchmark configuration. """ + data_request_formatter = ( + request_type + if not request_formatter_kwargs + else {"request_type": request_type, **request_formatter_kwargs} + ) + if HAS_UVLOOP: asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) asyncio.run( @@ -487,7 +485,6 @@ def run( # Benchmark configuration profile=profile, rate=rate, - random_seed=random_seed, # Backend configuration backend=backend, backend_kwargs=backend_kwargs, @@ -497,21 +494,12 @@ def run( processor_args=processor_args, data_args=data_args, data_samples=data_samples, - data_column_mapper=None, # use default - data_request_formatter=GenerativeRequestFormatter( - request_type=data_request_type, - request_template=data_request_template, - request_extras=data_request_extras, - request_defaults=( - {} # disable defaults if non-streaming - if data_request_nonstreaming - else None - ), - ), - data_preprocessors=None, # no preprocessors through CLI for now - dataloader_sampler=data_sampler, - dataloader_collate_fn=None, # use default + data_column_mapper=data_column_mappings, + data_request_formatter=data_request_formatter, + data_sampler=data_sampler, + data_num_workers=data_num_workers, dataloader_kwargs=dataloader_kwargs, + random_seed=random_seed, # Output configuration output_path=output_path, output_formats=[ @@ -534,7 +522,7 @@ def run( add_aggregators={"extras": InjectExtrasAggregator(extras=output_extras)}, warmup=warmup, cooldown=cooldown, - request_samples=request_samples, + sample_requests=request_samples, # Constraints configuration max_seconds=max_seconds, max_requests=max_requests, diff --git a/src/guidellm/benchmark/aggregator.py b/src/guidellm/benchmark/aggregator.py index 3040ad36..562fc36c 100644 --- a/src/guidellm/benchmark/aggregator.py +++ b/src/guidellm/benchmark/aggregator.py @@ -678,20 +678,20 @@ class GenerativeRequestsAggregator( @classmethod def validated_kwargs( cls, - request_samples: int | None = 20, + sample_requests: int | None = 20, warmup: int | float | None = None, cooldown: int | float | None = None, **_kwargs, ) -> dict[str, Any]: return { - "request_samples": request_samples, + "sample_requests": sample_requests, "warmup": warmup, "cooldown": cooldown, } type_: Literal["generative_requests"] = Field(default="generative_requests") - request_samples: int | None = Field(default=20, description="") + sample_requests: int | None = Field(default=20, description="") warmup: int | float | None = Field( default=None, description="Number of warmup requests to ignore at benchmark start", @@ -828,9 +828,9 @@ def compile( list[GenerativeRequestStats], list[GenerativeRequestStats], ]( - successful=self._sample_request_stats(successful, self.request_samples), - incomplete=self._sample_request_stats(incomplete, self.request_samples), - errored=self._sample_request_stats(errored, self.request_samples), + successful=self._sample_request_stats(successful, self.sample_requests), + incomplete=self._sample_request_stats(incomplete, self.sample_requests), + errored=self._sample_request_stats(errored, self.sample_requests), ), "metrics": GenerativeMetrics( requests_per_second=self._calculate_requests_per_second( diff --git a/src/guidellm/benchmark/entrypoints.py b/src/guidellm/benchmark/entrypoints.py index 23bc985a..e400907a 100644 --- a/src/guidellm/benchmark/entrypoints.py +++ b/src/guidellm/benchmark/entrypoints.py @@ -1,11 +1,10 @@ from __future__ import annotations from pathlib import Path -from typing import Any, Literal +from typing import Any, Callable, Literal from torch.utils.data import Sampler from transformers import ( # type: ignore[import] - AutoTokenizer, PreTrainedTokenizerBase, ) @@ -35,13 +34,13 @@ BenchmarkerProgressGroup, ) from guidellm.data import ( + DataLoader, DatasetPreprocessor, - GenerativeColumnMapper, - GenerativeDataLoader, GenerativeRequestCollator, - GenerativeRequestFormatter, + PreprocessorRegistry, + ProcessorFactory, ) -from guidellm.data.objects import GenerativeDatasetArgs +from guidellm.data.preprocessors import GenerativeColumnMapper from guidellm.scheduler import ( ConstraintInitializer, NonDistributedEnvironment, @@ -59,14 +58,13 @@ # @validate_call(config={"arbitrary_types_allowed": True}) -async def benchmark_generative_text( # noqa: C901, PLR0915 +async def benchmark_generative_text( # noqa: C901, PLR0915, PLR0912 # Required target: str, data: list[Any], # Benchmark configuration profile: StrategyType | ProfileType | Profile = "sweep", rate: float | list[float] | None = None, - random_seed: int = 42, # Backend configuration backend: BackendType | Backend = "openai_http", backend_kwargs: dict[str, Any] | None = None, @@ -74,14 +72,19 @@ async def benchmark_generative_text( # noqa: C901, PLR0915 # Data configuration processor: str | Path | PreTrainedTokenizerBase | None = None, processor_args: dict[str, Any] | None = None, - data_args: list[GenerativeDatasetArgs] | None = None, + data_args: list[dict[str, Any]] | None = None, data_samples: int = -1, - data_column_mapper: GenerativeColumnMapper | None = None, - data_preprocessors: list[DatasetPreprocessor] | None = None, - data_request_formatter: GenerativeRequestFormatter | None = None, - dataloader_sampler: Sampler[int] | Literal["shuffle"] | None = None, - dataloader_collate_fn: GenerativeRequestCollator | None = None, + data_column_mapper: ( + DatasetPreprocessor | dict[str, str] | Literal["generative_column_mapper"] + ) = "generative_column_mapper", + data_request_formatter: ( + DatasetPreprocessor | dict[str, str] | str + ) = "chat_completions", + data_collator: Callable | Literal["generative"] | None = "generative", + data_sampler: Sampler[int] | Literal["shuffle"] | None = None, + data_num_workers: int | None = 1, dataloader_kwargs: dict[str, Any] | None = None, + random_seed: int = 42, # Output configuration output_path: str | Path | None = _CURRENT_WORKING_DIR, output_formats: ( @@ -99,7 +102,7 @@ async def benchmark_generative_text( # noqa: C901, PLR0915 ) = None, warmup: float | None = None, cooldown: float | None = None, - request_samples: int | None = 20, + sample_requests: int | None = 10, # Constraints configuration max_seconds: int | float | None = None, max_requests: int | None = None, @@ -123,8 +126,17 @@ async def benchmark_generative_text( # noqa: C901, PLR0915 console_step.update(f"{backend.__class__.__name__} backend initialized") await backend.process_startup() await backend.validate() + if model is None: + console_step.update( + title="Resolving default model from backend.default_model", + status_level="info", + ) + model = await backend.default_model() + await backend.process_shutdown() console_step.finish( - title=f"{backend.__class__.__name__} backend initialized", + title=( + f"{backend.__class__.__name__} backend validated with model {model}" + ), details=backend.info, status_level="success", ) @@ -136,54 +148,56 @@ async def benchmark_generative_text( # noqa: C901, PLR0915 details=f"Using processor '{processor}'", status_level="success", ) - elif model is not None: - console_step.finish( - title="Processor resolved", - details=f"Using model '{model}' as processor", - status_level="success", - ) - processor = model else: - console_step.update( - title="Resolving processor from backend.default_model", - status_level="info", - ) - processor = await backend.default_model() + processor = model console_step.finish( title="Processor resolved", - details=( - f"Using model '{processor}' from backend " - f"{backend.__class__.__name__} as processor" - ), + details=f"Using model '{processor}' as processor", status_level="success", ) - await backend.process_shutdown() with console.print_update_step( title=f"Initializing request loader from {data}" ) as console_step: + if not isinstance(data_column_mapper, DatasetPreprocessor): + column_mappings = ( + data_column_mapper if isinstance(data_column_mapper, dict) else None + ) + data_column_mapper = GenerativeColumnMapper( + column_mappings=column_mappings, + ) + if not isinstance(data_request_formatter, DatasetPreprocessor): + request_type = ( + data_request_formatter + if isinstance(data_request_formatter, str) + else data_request_formatter.pop("request_type", "chat_completions") + ) + data_request_formatter = PreprocessorRegistry.get_registered_object( + request_type + )( + model=model, + **( + data_request_formatter + if isinstance(data_request_formatter, dict) + else {} + ), + ) - def processor_factory() -> PreTrainedTokenizerBase: - nonlocal processor - if isinstance(processor, PreTrainedTokenizerBase): - return processor - else: - processor = AutoTokenizer.from_pretrained( - processor, - **(processor_args or {}), - ) - return processor - - request_loader = GenerativeDataLoader( + request_loader = DataLoader( data=data, data_args=data_args, data_samples=data_samples, - processor_factory=processor_factory, - column_mapper=data_column_mapper or GenerativeColumnMapper(), - preprocessors=data_preprocessors or [], - request_formatter=data_request_formatter or GenerativeRequestFormatter(), - sampler=dataloader_sampler, - collate_fn=dataloader_collate_fn, + processor_factory=ProcessorFactory( + processor=processor, processor_args=processor_args + ), + preprocessors=[data_column_mapper, data_request_formatter], + collator=( + data_collator + if callable(data_collator) + else GenerativeRequestCollator() + ), + sampler=data_sampler, + num_workers=data_num_workers, random_seed=random_seed, **(dataloader_kwargs or {}), ) @@ -234,7 +248,7 @@ def processor_factory() -> PreTrainedTokenizerBase: "scheduler_stats": SchedulerStatsAggregator(), "requests_progress": GenerativeStatsProgressAggregator(), "requests": GenerativeRequestsAggregator( - request_samples=request_samples, + request_samples=sample_requests, warmup=warmup, cooldown=cooldown, ), diff --git a/src/guidellm/data/__init__.py b/src/guidellm/data/__init__.py index 282c5b59..d25c719a 100644 --- a/src/guidellm/data/__init__.py +++ b/src/guidellm/data/__init__.py @@ -1,31 +1,29 @@ -from .datasets import GenerativeRequestsDataset +from .collators import GenerativeRequestCollator from .deserializers import ( DataNotSupportedError, DatasetDeserializer, DatasetDeserializerFactory, ) -from .formatters import ( - GenerativeRequestFormatter, - JinjaEnvironmentMixin, - JinjaFiltersRegistry, - JinjaGlobalsRegistry, - JinjaTemplatesRegistry, -) -from .loaders import GenerativeDataLoader, GenerativeRequestCollator +from .loaders import DataLoader from .objects import ( GenerationRequest, GenerationRequestArguments, GenerationRequestTimings, - GenerativeDatasetArgs, GenerativeDatasetColumnType, GenerativeRequestType, ) from .preprocessors import ( + DataDependentPreprocessor, DatasetPreprocessor, - GenerativeColumnMapper, + PreprocessorRegistry, ) +from .processor import ProcessorFactory __all__ = [ + "ColumnMapper", + "ColumnMapperRegistry", + "DataDependentPreprocessor", + "DataLoader", "DataNotSupportedError", "DatasetDeserializer", "DatasetDeserializerFactory", @@ -33,16 +31,12 @@ "GenerationRequest", "GenerationRequestArguments", "GenerationRequestTimings", - "GenerativeColumnMapper", - "GenerativeDataLoader", "GenerativeDatasetArgs", "GenerativeDatasetColumnType", "GenerativeRequestCollator", - "GenerativeRequestFormatter", "GenerativeRequestType", - "GenerativeRequestsDataset", - "JinjaEnvironmentMixin", - "JinjaFiltersRegistry", - "JinjaGlobalsRegistry", - "JinjaTemplatesRegistry", + "PreprocessorRegistry", + "ProcessorFactory", + "RequestFormatter", + "RequestFormatterRegistry", ] diff --git a/src/guidellm/data/collators.py b/src/guidellm/data/collators.py new file mode 100644 index 00000000..4d12f0c0 --- /dev/null +++ b/src/guidellm/data/collators.py @@ -0,0 +1,16 @@ +from __future__ import annotations + +from guidellm.data.objects import GenerationRequest + +__all__ = ["GenerativeRequestCollator"] + + +class GenerativeRequestCollator: + def __call__(self, batch: list) -> GenerationRequest: + if len(batch) != 1: + raise NotImplementedError( + f"Batch size greater than 1 is not currently supported. " + f"Got batch size: {len(batch)}" + ) + + return batch[0] diff --git a/src/guidellm/data/datasets.py b/src/guidellm/data/datasets.py deleted file mode 100644 index 8c24683c..00000000 --- a/src/guidellm/data/datasets.py +++ /dev/null @@ -1,88 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable -from typing import Any - -from datasets import Dataset, IterableDataset -from transformers import PreTrainedTokenizerBase - -from guidellm.data.deserializers import DatasetDeserializerFactory -from guidellm.data.formatters import GenerativeRequestFormatter -from guidellm.data.objects import GenerativeDatasetArgs -from guidellm.data.preprocessors import ( - DatasetPreprocessor, - GenerativeColumnMapper, -) -from guidellm.data.utils import datasets_item_iterator, resolve_dataset_split - -__all__ = ["GenerativeRequestsDataset"] - - -class GenerativeRequestsDataset: - @classmethod - def build( - cls, - data: list[Any], - data_args: list[GenerativeDatasetArgs] | None, - data_samples: int, - processor_factory: Callable[[], PreTrainedTokenizerBase], - column_mapper: GenerativeColumnMapper, - preprocessors: list[DatasetPreprocessor], - request_formatter: GenerativeRequestFormatter, - random_seed: int = 42, - ) -> Dataset | IterableDataset: - if not data or not isinstance(data, list): - raise ValueError(f"Data must be a non-empty list, got {data}.") - - if data_args is None: - data_args = [GenerativeDatasetArgs() for _ in data] - - if len(data) != len(data_args): - raise ValueError( - f"Length of data ({len(data)}) must match length of data_args " - f"({len(data_args)})." - ) - - datasets = [] - for datum, args in zip(data, data_args): - datasets.append( - resolve_dataset_split( - dataset=DatasetDeserializerFactory.deserialize( - data=datum, - data_kwargs=args.to_kwargs(), - processor_factory=processor_factory, - random_seed=random_seed, - type_=args.type_, - ), - split=args.split, - ) - ) - - column_mapper.init_data(datasets=datasets, data_args=data_args) - request_formatter.init_data(datasets=datasets, data_args=data_args) - for preprocessor in preprocessors: - preprocessor.init_data(datasets=datasets, data_args=data_args) - - if data_samples > 0: - dataset = Dataset.from_list( - list( - datasets_item_iterator( - datasets=datasets, - data_samples=data_samples, - ) - ) - ) - else: - dataset = IterableDataset.from_generator( - datasets_item_iterator, - gen_kwargs={ - "datasets": datasets, - "data_samples": data_samples, - }, - ) - - dataset = dataset.map(column_mapper) - for preprocessor in preprocessors: - dataset = dataset.map(preprocessor) - - return dataset.map(request_formatter) diff --git a/src/guidellm/data/deserializers/deserializer.py b/src/guidellm/data/deserializers/deserializer.py index ed9050a1..c7e2f1da 100644 --- a/src/guidellm/data/deserializers/deserializer.py +++ b/src/guidellm/data/deserializers/deserializer.py @@ -4,9 +4,10 @@ from collections.abc import Callable from typing import Any, Protocol, Union, runtime_checkable -from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict +from datasets import Dataset, IterableDataset from transformers import PreTrainedTokenizerBase +from guidellm.data.utils import resolve_dataset_split from guidellm.utils import RegistryMixin __all__ = [ @@ -25,9 +26,9 @@ class DatasetDeserializer(Protocol): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: ... @@ -38,44 +39,43 @@ class DatasetDeserializerFactory( def deserialize( cls, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int = 42, type_: str | None = None, - ) -> Dataset | IterableDataset | DatasetDict | IterableDatasetDict: - if type_ is not None: - deserializer = cls.get_registered_object(type_) + resolve_split: bool = True, + **data_kwargs: dict[str, Any], + ) -> Dataset | IterableDataset: + dataset = None - if deserializer is None: - raise DataNotSupportedError( - f"Deserializer type '{type_}' is not registered. " - f"Available types: {cls.registry}" + if type_ is None: + for deserializer in cls.registered_objects(): + deserializer_fn: DatasetDeserializer = ( + deserializer() if isinstance(deserializer, type) else deserializer ) - elif isinstance(deserializer, type): - deserializer_fn = deserializer() - else: - deserializer_fn = deserializer - return deserializer_fn( + with contextlib.suppress(DataNotSupportedError): + dataset = deserializer_fn( + data=data, + processor_factory=processor_factory, + random_seed=random_seed, + **data_kwargs, + ) + elif deserializer := cls.get_registered_object(type_) is not None: + deserializer_fn: DatasetDeserializer = ( + deserializer() if isinstance(deserializer, type) else deserializer + ) + + dataset = deserializer_fn( data=data, - data_kwargs=data_kwargs, processor_factory=processor_factory, random_seed=random_seed, + **data_kwargs, ) - for deserializer in cls.registered_objects(): - deserializer_fn: DatasetDeserializer = ( - deserializer() if isinstance(deserializer, type) else deserializer + if dataset is None: + raise DataNotSupportedError( + f"No suitable deserializer found for data {data} " + f"with kwargs {data_kwargs} and type_ {type_}." ) - with contextlib.suppress(DataNotSupportedError): - return deserializer_fn( - data=data, - data_kwargs=data_kwargs, - processor_factory=processor_factory, - random_seed=random_seed, - ) - - raise DataNotSupportedError( - f"No suitable deserializer found for data {data} with kwargs {data_kwargs}." - ) + return resolve_dataset_split(dataset) if resolve_split else dataset diff --git a/src/guidellm/data/deserializers/file.py b/src/guidellm/data/deserializers/file.py index 53688cf0..54b18edb 100644 --- a/src/guidellm/data/deserializers/file.py +++ b/src/guidellm/data/deserializers/file.py @@ -30,9 +30,9 @@ class TextFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) # Ignore unused args format errors @@ -58,9 +58,9 @@ class CSVFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( @@ -82,9 +82,9 @@ class JSONFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( @@ -106,9 +106,9 @@ class ParquetFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( @@ -130,9 +130,9 @@ class ArrowFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( @@ -154,9 +154,9 @@ class HDF5FileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( @@ -178,9 +178,9 @@ class DBFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( @@ -202,9 +202,9 @@ class TarFileDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) if ( diff --git a/src/guidellm/data/deserializers/huggingface.py b/src/guidellm/data/deserializers/huggingface.py index 275f7180..3e0cf090 100644 --- a/src/guidellm/data/deserializers/huggingface.py +++ b/src/guidellm/data/deserializers/huggingface.py @@ -27,9 +27,9 @@ class HuggingFaceDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) diff --git a/src/guidellm/data/deserializers/memory.py b/src/guidellm/data/deserializers/memory.py index b04ea6bc..ddca64a9 100644 --- a/src/guidellm/data/deserializers/memory.py +++ b/src/guidellm/data/deserializers/memory.py @@ -29,9 +29,9 @@ class InMemoryDictDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) # Ignore unused args format errors @@ -63,9 +63,9 @@ class InMemoryDictListDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) # Ignore unused args format errors @@ -104,9 +104,9 @@ class InMemoryItemListDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: _ = (processor_factory, random_seed) # Ignore unused args format errors @@ -131,9 +131,9 @@ class InMemoryJsonStrDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: if ( isinstance(data, str) @@ -167,9 +167,9 @@ class InMemoryCsvDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> dict[str, list]: if ( isinstance(data, str) @@ -182,7 +182,7 @@ def __call__( rows = list(reader) return InMemoryDictListDatasetDeserializer()( - rows, data_kwargs, processor_factory, random_seed + rows, processor_factory, random_seed, **data_kwargs ) raise DataNotSupportedError( diff --git a/src/guidellm/data/deserializers/synthetic.py b/src/guidellm/data/deserializers/synthetic.py index a071eeea..c2078f1a 100644 --- a/src/guidellm/data/deserializers/synthetic.py +++ b/src/guidellm/data/deserializers/synthetic.py @@ -4,7 +4,7 @@ from collections.abc import Iterator from pathlib import Path from random import Random -from typing import Any, Callable, Self +from typing import Any, Callable import yaml from datasets import Features, IterableDataset, Value @@ -98,7 +98,7 @@ class SyntheticTextDatasetConfig(StandardBaseModel): ) @model_validator(mode="after") - def check_prefix_options(self) -> Self: + def check_prefix_options(self) -> SyntheticTextDatasetConfig: prefix_count = self.__pydantic_extra__.get("prefix_count", None) # type: ignore[attr-defined] prefix_tokens = self.__pydantic_extra__.get("prefix_count", None) # type: ignore[attr-defined] if prefix_count is not None or prefix_tokens is not None: @@ -226,17 +226,17 @@ class SyntheticTextDatasetDeserializer(DatasetDeserializer): def __call__( self, data: Any, - data_kwargs: dict[str, Any], processor_factory: Callable[[], PreTrainedTokenizerBase], random_seed: int, + **data_kwargs: dict[str, Any], ) -> IterableDataset: # Config file pathways, deserialize and call self again if (config := self._load_config_file(data)) is not None: - return self(config, data_kwargs, processor_factory, random_seed) + return self(config, processor_factory, random_seed, **data_kwargs) # Config str pathways, deserialize and call self again if (config := self._load_config_str(data)) is not None: - return self(config, data_kwargs, processor_factory, random_seed) + return self(config, processor_factory, random_seed, **data_kwargs) if not isinstance(data, SyntheticTextDatasetConfig): raise DataNotSupportedError( @@ -246,9 +246,12 @@ def __call__( ) return IterableDataset.from_generator( - lambda: SyntheticTextGenerator( - config=data, processor=processor_factory(), random_seed=random_seed - ), + SyntheticTextGenerator, + gen_kwargs={ + "config": data, + "processor": processor_factory(), + "random_seed": random_seed, + }, features=Features( { "prefix": Value("string"), diff --git a/src/guidellm/data/formatters/__init__.py b/src/guidellm/data/formatters/__init__.py deleted file mode 100644 index 0a5ccbc9..00000000 --- a/src/guidellm/data/formatters/__init__.py +++ /dev/null @@ -1,47 +0,0 @@ -from .environment import JinjaEnvironmentMixin -from .filters import ( - JinjaFiltersRegistry, - download_audio, - download_image, - download_video, - encode_audio, - encode_image, - encode_image_base64, - encode_video, - encode_video_base64, - get_file_format, - is_url, - resize_image, -) -from .globals import JinjaGlobalsRegistry -from .objects import GenerativeRequestFormatter -from .templates import ( - DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE, - DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE, - DEFAULT_CHAT_COMPLETIONS_TEMPLATE, - DEFAULT_TEXT_COMPLETIONS_TEMPLATE, - JinjaTemplatesRegistry, -) - -__all__ = [ - "DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE", - "DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE", - "DEFAULT_CHAT_COMPLETIONS_TEMPLATE", - "DEFAULT_TEXT_COMPLETIONS_TEMPLATE", - "GenerativeRequestFormatter", - "JinjaEnvironmentMixin", - "JinjaFiltersRegistry", - "JinjaGlobalsRegistry", - "JinjaTemplatesRegistry", - "download_audio", - "download_image", - "download_video", - "encode_audio", - "encode_image", - "encode_image_base64", - "encode_video", - "encode_video_base64", - "get_file_format", - "is_url", - "resize_image", -] diff --git a/src/guidellm/data/formatters/environment.py b/src/guidellm/data/formatters/environment.py deleted file mode 100644 index bd37e26b..00000000 --- a/src/guidellm/data/formatters/environment.py +++ /dev/null @@ -1,63 +0,0 @@ -from __future__ import annotations - -from typing import Any, ClassVar - -from jinja2 import Template -from jinja2.nativetypes import NativeEnvironment, NativeTemplate - -from guidellm.data.formatters.filters import JinjaFiltersRegistry -from guidellm.data.formatters.globals import JinjaGlobalsRegistry -from guidellm.data.formatters.templates import JinjaTemplatesRegistry - -__all__ = ["JinjaEnvironmentMixin"] - - -class JinjaEnvironmentMixin: - jinja_environment: ClassVar[NativeEnvironment | None] = None - - @classmethod - def create_environment(cls, **env_kwargs: Any) -> NativeEnvironment: - if "autoescape" not in env_kwargs: - env_kwargs["autoescape"] = False - - extensions = env_kwargs.pop("extensions", []) - extensions = set(extensions) | {"jinja2.ext.do"} - - env = NativeEnvironment(extensions=list(extensions), **env_kwargs) # noqa: S701 - - # Attach registered filters - filters_registry = JinjaFiltersRegistry.registry # type: ignore[misc] - if filters_registry: - for name, func in filters_registry.items(): - env.filters[name] = func - - # Attach registered globals - globals_registry = JinjaGlobalsRegistry.registry # type: ignore[misc] - if globals_registry: - for name, value in globals_registry.items(): - env.globals[name] = value - - cls.jinja_environment = env - return env - - @classmethod - def get_environment(cls) -> NativeEnvironment: - if cls.jinja_environment is None: - raise ValueError( - "Jinja environment is not initialized. Call create_environment first." - ) - return cls.jinja_environment - - @classmethod - def template_from_source(cls, source: str | Template) -> NativeTemplate: - if isinstance(source, Template): - return source - env = cls.get_environment() - return env.from_string(source) - - @classmethod - def template_from_registry(cls, name: str) -> NativeTemplate: - template = JinjaTemplatesRegistry.get_registered_object(name) - if template is None: - raise ValueError(f"Template '{name}' not found in registry.") - return cls.template_from_source(template) diff --git a/src/guidellm/data/formatters/globals.py b/src/guidellm/data/formatters/globals.py deleted file mode 100644 index 6c066191..00000000 --- a/src/guidellm/data/formatters/globals.py +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Any - -from guidellm.utils import RegistryMixin - -__all__ = ["JinjaGlobalsRegistry"] - - -class JinjaGlobalsRegistry(RegistryMixin[Any]): - pass diff --git a/src/guidellm/data/formatters/objects.py b/src/guidellm/data/formatters/objects.py deleted file mode 100644 index 3e032089..00000000 --- a/src/guidellm/data/formatters/objects.py +++ /dev/null @@ -1,92 +0,0 @@ -from __future__ import annotations - -from typing import Any, Literal - -from datasets import Dataset, IterableDataset -from jinja2 import Template - -from guidellm.data.formatters import JinjaEnvironmentMixin -from guidellm.data.objects import ( - GenerationRequest, - GenerationRequestArguments, - GenerativeDatasetArgs, - GenerativeRequestType, -) -from guidellm.data.preprocessors.objects import DatasetPreprocessor - -__all__ = ["GenerativeRequestFormatter"] - - -class GenerativeRequestFormatter(DatasetPreprocessor, JinjaEnvironmentMixin): - def __init__( - self, - request_type: GenerativeRequestType | str = "text_completions", - request_template: str | Template | None = None, - request_extras: dict[str, Any] | GenerationRequestArguments | None = None, - request_defaults: dict[str, Any] | GenerationRequestArguments | None = None, - environment_extras: dict[str, Any] | None = None, - ): - self.datasets: list[Dataset | IterableDataset] | None = None - self.data_args: list[GenerativeDatasetArgs] | None = None - - self.request_type = request_type - self.request_template = request_template - self.request_extras = request_extras or {} - self.request_defaults = request_defaults or { - "stream": True, - "json_body": { - "stream": True, - "stream_options": { - "include_usage": True, - }, - }, - } - self.environment_extras = environment_extras or {} - self.jinja_template: Template | None = None - - def init_data( - self, - datasets: list[Dataset | IterableDataset], - data_args: list[GenerativeDatasetArgs], - ): - self.datasets = datasets - self.data_args = data_args - - self.create_environment(**self.environment_extras) - self.jinja_template = ( - self.template_from_source(self.request_template) - if self.request_template - else self.template_from_registry(self.request_type) - ) - - def __call__( - self, item: dict[str, Any] - ) -> dict[Literal["request"], GenerationRequest]: - if self.jinja_template is None: - raise ValueError("GenerativeRequestCreator not initialized with data.") - - stats = {} - if "prompt_tokens_count" in item: - count = item["prompt_tokens_count"][0] - stats["prompt_tokens"] = count - item["prompt_tokens_count"] = count - if "output_tokens_count" in item: - count = item["output_tokens_count"][0] - stats["output_tokens"] = count - item["output_tokens_count"] = count - - return { - "request": { - "request_type": self.request_type, - "arguments": GenerationRequestArguments.model_combine_dict( - self.request_defaults, - self.request_extras, - self.jinja_template.render( - **item, - request_defaults=self.request_defaults, - request_extras=self.request_extras, - ), - ), - "stats": stats, - } - } diff --git a/src/guidellm/data/formatters/templates.py b/src/guidellm/data/formatters/templates.py deleted file mode 100644 index 52db73b1..00000000 --- a/src/guidellm/data/formatters/templates.py +++ /dev/null @@ -1,182 +0,0 @@ -import textwrap -from typing import Union - -from jinja2 import Template - -from guidellm.utils import RegistryMixin - -__all__ = [ - "DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE", - "DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE", - "DEFAULT_CHAT_COMPLETIONS_TEMPLATE", - "DEFAULT_TEXT_COMPLETIONS_TEMPLATE", - "JinjaTemplatesRegistry", -] - - -class JinjaTemplatesRegistry(RegistryMixin[Union[Template, str]]): - pass - - -DEFAULT_TEXT_COMPLETIONS_TEMPLATE = JinjaTemplatesRegistry.register("text_completions")( - textwrap.dedent(""" - {% set obj = { - "json_body": { - "prompt": prefix_column[0]|default("") + text_column[0] - } - } %} - - {% if output_tokens_count is defined and output_tokens_count is not none %} - {% do obj["json_body"].update({ - "max_tokens": output_tokens_count, - "max_completion_tokens": output_tokens_count, - "stop": None, - "ignore_eos": True - }) %} - {% elif max_tokens is defined and max_tokens is not none %} - {% do obj["json_body"].update({"max_tokens": max_tokens}) %} - {% elif max_completion_tokens is defined and max_completion_tokens is not none %} - {% do obj["json_body"].update({"max_completion_tokens": max_completion_tokens}) %} - {% endif %} - - {{ obj }} - """).strip() # noqa: E501 -) - -DEFAULT_CHAT_COMPLETIONS_TEMPLATE = JinjaTemplatesRegistry.register("chat_completions")( - textwrap.dedent(""" - {% set obj = { - "json_body": { - "messages": [ - { - "role": "system", - "content": prefix_column[0]|default("") - }, - { - "role": "user", - "content": [] - } - ] - } - } %} - - {%- for item in text_column or [] %} - {% do obj["json_body"].messages[1].content.append({"type": "text", "text": item}) %} - {%- endfor %} - - {%- for item in image_column or [] %} - {% do obj["json_body"].messages[1].content.append({ - "type": "image_url", - "image_url": encode_image( - item, - max_size=max_size|default(None), - max_width=max_width|default(None), - max_height=max_height|default(None), - encode_type=image_encode_type|default(encode_type|default(None)) - ) - }) %} - {%- endfor %} - - {%- for item in video_column or [] %} - {% do obj["json_body"].messages[1].content.append({ - "type": "video_url", - "video_url": encode_video( - item, - encode_type=video_encode_type|default(encode_type|default(None)) - ) - }) %} - {%- endfor %} - - {%- for item in audio_column or [] %} - {%- set audio_type, audio_val = encode_audio( - item, - sample_rate=sample_rate|default(None), - max_duration=max_duration|default(None), - encode_type=audio_encode_type|default(encode_type|default(None)) - ) -%} - {% do content_list.append({"type": audio_type, audio_type: audio_val}) %} - {%- endfor %} - - {% if output_tokens_count is defined and output_tokens_count is not none %} - {% do obj["json_body"].update({ - "max_completion_tokens": output_tokens_count, - "stop": None, - "ignore_eos": True - }) %} - {% elif max_tokens is defined and max_tokens is not none %} - {% do obj["json_body"].update({"max_completion_tokens": max_tokens}) %} - {% elif max_completion_tokens is defined and max_completion_tokens is not none %} - {% do obj["json_body"].update({"max_completion_tokens": max_completion_tokens}) %} - {% endif %} - - {{ obj }} - """).strip() # noqa: E501 -) - -DEFAULT_AUDIO_TRANSCRIPTIONS_TEMPLATE = JinjaTemplatesRegistry.register( - "audio_transcriptions" -)( - textwrap.dedent(""" - { - {%- if output_tokens_count_column is defined and output_tokens_count_column is not none -%} - "max_tokens": {{ output_tokens_count_column }}, - "max_completion_tokens": {{ output_tokens_count_column }}, - "stop": None, - "ignore_eos": True, - {%- else -%} - {%- if max_tokens is defined and max_tokens is not none -%} - "max_tokens": {{ max_tokens }}, - {%- endif -%} - {%- if max_completion_tokens is defined and max_completion_tokens is not none -%} - "max_completion_tokens": {{ max_completion_tokens }}, - {%- endif -%} - {%- endif -%} - "files": { - "file": {{ encode_audio_file( - audio_column[0], - encode_type=audio_encode_type|default(encode_type|default(None)) - ) }} - } - {%- if text_column and text_column|length > 0 -%} - , - "json": { - "prompt": {{ text_column[0] }} - } - {%- endif -%} - } - """).strip() # noqa: E501 -) - -DEFAULT_AUDIO_TRANSLATIONS_TEMPLATE = JinjaTemplatesRegistry.register( - "audio_translations" -)( - textwrap.dedent(""" - { - {%- if output_tokens_count_column is defined and output_tokens_count_column is not none -%} - "max_tokens": {{ output_tokens_count_column }}, - "max_completion_tokens": {{ output_tokens_count_column }}, - "stop": None, - "ignore_eos": True, - {%- else -%} - {%- if max_tokens is defined and max_tokens is not none -%} - "max_tokens": {{ max_tokens }}, - {%- endif -%} - {%- if max_completion_tokens is defined and max_completion_tokens is not none -%} - "max_completion_tokens": {{ max_completion_tokens }}, - {%- endif -%} - {%- endif -%} - "files": { - "file": {{ encode_audio_file( - audio_column[0], - encode_type=audio_encode_type|default(encode_type|default(None)) - ) }} - } - {%- if text_column and text_column|length > 0 -%} - , - "json": { - "prompt": {{ text_column[0] }} - } - {%- endif -%} - } - """).strip() # noqa: E501 -) diff --git a/src/guidellm/data/loaders.py b/src/guidellm/data/loaders.py index ebecdb6f..303e5a8d 100644 --- a/src/guidellm/data/loaders.py +++ b/src/guidellm/data/loaders.py @@ -1,93 +1,111 @@ from __future__ import annotations -from collections.abc import Callable +import contextlib +import math +from collections.abc import Callable, Iterator from typing import Any, Literal from datasets import Dataset, IterableDataset -from torch.utils.data import DataLoader, Sampler +from torch.utils.data import Sampler +from torch.utils.data.dataloader import DataLoader as PyTorchDataLoader from transformers import PreTrainedTokenizerBase -from guidellm.data.datasets import GenerativeRequestsDataset -from guidellm.data.formatters import GenerativeRequestFormatter -from guidellm.data.objects import GenerationRequest, GenerativeDatasetArgs -from guidellm.data.preprocessors import ( - DatasetPreprocessor, - GenerativeColumnMapper, -) +from guidellm.data.deserializers import DatasetDeserializerFactory +from guidellm.data.objects import GenerationRequest +from guidellm.data.preprocessors import DataDependentPreprocessor, DatasetPreprocessor -__all__ = ["GenerativeDataLoader", "GenerativeRequestCollator"] +__all__ = ["DataLoader", "datasets_item_iterator"] -class GenerativeRequestCollator: - def __call__( - self, batch: list[dict[Literal["request"], dict[str, Any]]] - ) -> GenerationRequest: - if len(batch) != 1: - raise NotImplementedError( - f"Batch size greater than 1 is not currently supported. " - f"Got batch size: {len(batch)}" - ) +def datasets_item_iterator( + datasets: list[Dataset | IterableDataset], + data_samples: int, + preprocessors: tuple[DatasetPreprocessor | DataDependentPreprocessor], +) -> Iterator[Any]: + gen_count = 0 + dataset_iters = [iter(dataset) for dataset in datasets] + + with contextlib.suppress(StopIteration): + while gen_count < data_samples or data_samples == math.inf: + row = {"items": [next(dataset_iter) for dataset_iter in dataset_iters]} + for preprocessor in preprocessors: + row = preprocessor(row) + yield row + gen_count += 1 - return GenerationRequest.model_validate(batch[0]["request"]) + if data_samples != math.inf and gen_count < data_samples: + raise ValueError( + f"Requested {data_samples} samples, but only {gen_count} " + "available from the provided datasets." + ) -class GenerativeDataLoader(DataLoader[GenerationRequest]): +class DataLoader(PyTorchDataLoader[GenerationRequest]): def __init__( self, data: list[Any], - data_args: list[GenerativeDatasetArgs] | None, + data_args: list[dict[str, Any]] | None, data_samples: int, processor_factory: Callable[[], PreTrainedTokenizerBase], - column_mapper: GenerativeColumnMapper, - preprocessors: list[DatasetPreprocessor], - request_formatter: GenerativeRequestFormatter, + preprocessors: list[DatasetPreprocessor | DataDependentPreprocessor], + collator: Callable, sampler: Sampler[int] | Literal["shuffle"] | None = None, - collate_fn: GenerativeRequestCollator | None = None, - num_workers: int | None = None, + num_workers: int | None = 1, random_seed: int = 42, **kwargs: Any, ): - dataset = GenerativeRequestsDataset.build( - data=data, - data_args=data_args, - data_samples=data_samples, - processor_factory=processor_factory, - column_mapper=column_mapper, - request_formatter=request_formatter, - preprocessors=preprocessors, - random_seed=random_seed, - ) + if not data or not isinstance(data, list): + raise ValueError(f"Data must be a non-empty list, got {data}.") - if collate_fn is None: - collate_fn = GenerativeRequestCollator() + if data_args is None: + data_args = [{} for _ in data] - # Handle sampler/shuffle logic based on dataset type - if sampler == "shuffle": - shuffle = True - sampler = None - elif isinstance(sampler, str) and sampler != "shuffle": + if len(data) != len(data_args): raise ValueError( - f"Invalid string sampler: {sampler}. " - f"Only 'shuffle' is supported as a string value." + f"Length of data ({len(data)}) must match length of data_args " + f"({len(data_args)})." ) - else: - shuffle = False - if isinstance(dataset, IterableDataset) and sampler is not None: - raise ValueError( - "Samplers are not supported with IterableDataset. " - "Use shuffle=True or apply shuffling to the dataset directly." + datasets = [] + for datum, data_kwargs in zip(data, data_args): + type_ = data_kwargs.pop("type_") if "type_" in data_kwargs else None + datasets.append( + DatasetDeserializerFactory.deserialize( + data=datum, + data_kwargs=data_args, + processor_factory=processor_factory, + random_seed=random_seed, + type_=type_, + **data_kwargs, + ) + ) + for preprocessor in preprocessors: + if isinstance(preprocessor, DataDependentPreprocessor): + preprocessor.setup_data( + datasets=datasets, + data_args=data_args, + ) + if data_samples != math.inf and data_samples > 0: + cached_samples = list( + datasets_item_iterator(datasets, data_samples, tuple(preprocessors)) + ) + dataset = IterableDataset.from_generator(lambda: cached_samples) + else: + dataset = IterableDataset.from_generator( + datasets_item_iterator, + gen_kwargs={ + "datasets": datasets, + "data_samples": math.inf, + "preprocessors": tuple(preprocessors), + }, ) - elif isinstance(dataset, Dataset) and shuffle: - dataset = dataset.shuffle(seed=random_seed) - shuffle = False super().__init__( dataset=dataset, batch_size=1, - shuffle=shuffle, - sampler=sampler, - collate_fn=collate_fn, - num_workers=num_workers or 0, + shuffle=sampler == "shuffle", + sampler=sampler if sampler != "shuffle" else None, + collate_fn=collator, + num_workers=num_workers, **kwargs, ) diff --git a/src/guidellm/data/objects.py b/src/guidellm/data/objects.py index b4a38719..2a4b3857 100644 --- a/src/guidellm/data/objects.py +++ b/src/guidellm/data/objects.py @@ -1,7 +1,7 @@ from __future__ import annotations import uuid -from typing import Any, Literal, get_args +from typing import Any, Literal from pydantic import Field @@ -15,7 +15,6 @@ "GenerationRequest", "GenerationRequestArguments", "GenerationRequestTimings", - "GenerativeDatasetArgs", "GenerativeDatasetColumnType", "GenerativeRequestType", ] @@ -47,66 +46,23 @@ def model_combine_dict( # noqa: C901, PLR0912 combined = {} for args in arguments: - if ( - url := args.get("url") if isinstance(args, dict) else args.url - ) is not None: - combined["url"] = url - - if ( - path := args.get("path") if isinstance(args, dict) else args.path - ) is not None: - combined["path"] = path - - if ( - method := args.get("method") if isinstance(args, dict) else args.method - ) is not None: - combined["method"] = method - - if ( - stream := args.get("stream") if isinstance(args, dict) else args.stream - ) is not None: - combined["stream"] = stream - - if ( - content_body := ( - args.get("content_body") - if isinstance(args, dict) - else args.content_body - ) - ) is not None: - combined["content_body"] = content_body - - if ( - json_body := ( - args.get("json_body") if isinstance(args, dict) else args.json_body - ) - ) is not None: - if "json_body" not in combined: - combined["json_body"] = {} - combined["json_body"].update(json_body) - - if ( - files := args.get("files") if isinstance(args, dict) else args.files - ) is not None: - if "files" not in combined: - combined["files"] = {} - combined["files"].update(files) - - if ( - params := args.get("params") if isinstance(args, dict) else args.params - ) is not None: - if "params" not in combined: - combined["params"] = {} - combined["params"].update(params) - - if ( - headers := ( - args.get("headers") if isinstance(args, dict) else args.headers - ) - ) is not None: - if "headers" not in combined: - combined["headers"] = {} - combined["headers"].update(headers) + args_dict = args if isinstance(args, dict) else args.model_dump() + combined["url"] = args_dict.get("url", combined.get("url")) + combined["path"] = args_dict.get("path", combined.get("path")) + combined["method"] = args_dict.get("method", combined.get("method")) + combined["stream"] = args_dict.get("stream", combined.get("stream")) + combined["content_body"] = args_dict.get( + "content_body", combined.get("content_body") + ) + + if (json_body := args_dict.get("json_body")) is not None: + combined["json_body"] = combined.get("json_body", {}) + json_body + if (files := args_dict.get("files")) is not None: + combined["files"] = combined.get("files", {}) + files + if (params := args_dict.get("params")) is not None: + combined["params"] = combined.get("params", {}) + params + if (headers := args_dict.get("headers")) is not None: + combined["headers"] = combined.get("headers", {}) + headers return combined @@ -189,44 +145,3 @@ class GenerationRequestTimings(MeasuredRequestTimings): default=None, description="Unix timestamp when the last generation iteration completed.", ) - - -class GenerativeDatasetArgs(StandardBaseDict): - type_: str | None = None - split: str | None = None - prompt_tokens_count_column: str | None = None - output_tokens_count_column: str | None = None - prefix_column: str | None = None - text_column: str | list[str] | None = None - image_column: str | list[str] | None = None - video_column: str | list[str] | None = None - audio_column: str | list[str] | None = None - - def to_kwargs(self) -> dict[str, Any]: - return { - key: value - for key, value in self.model_extra.items() - if not key.endswith("_column") - } - - def get_mapped_columns( - self, - ) -> dict[GenerativeDatasetColumnType | str, str | list[str]]: - column_mapping: dict[GenerativeDatasetColumnType | str, list[str] | None] = {} - - # Add in any non None columns from the fields - for column in get_args(GenerativeDatasetColumnType): - value = getattr(self, column) - if value is not None: - column_mapping[column] = value - - # Enable flexibility for extra columns to be passed through and referenced later - for extra in self.model_extra: - if ( - extra.endswith("_column") - and extra not in column_mapping - and self.model_extra[extra] is not None - ): - column_mapping[extra] = self.model_extra[extra] - - return column_mapping diff --git a/src/guidellm/data/preprocessors/__init__.py b/src/guidellm/data/preprocessors/__init__.py index 039f74a5..664e196b 100644 --- a/src/guidellm/data/preprocessors/__init__.py +++ b/src/guidellm/data/preprocessors/__init__.py @@ -1,7 +1,25 @@ +from .formatters import ( + GenerativeAudioTranscriptionRequestFormatter, + GenerativeAudioTranslationRequestFormatter, + GenerativeChatCompletionsRequestFormatter, + GenerativeTextCompletionsRequestFormatter, +) from .mappers import GenerativeColumnMapper -from .objects import DatasetPreprocessor +from .preprocessor import ( + DataDependentPreprocessor, + DatasetPreprocessor, + PreprocessorRegistry, +) __all__ = [ + "ColumnMapper", + "ColumnMapperRegistry", + "DataDependentPreprocessor", "DatasetPreprocessor", + "GenerativeAudioTranscriptionRequestFormatter", + "GenerativeAudioTranslationRequestFormatter", + "GenerativeChatCompletionsRequestFormatter", "GenerativeColumnMapper", + "GenerativeTextCompletionsRequestFormatter", + "PreprocessorRegistry", ] diff --git a/src/guidellm/data/preprocessors/formatters.py b/src/guidellm/data/preprocessors/formatters.py new file mode 100644 index 00000000..c41ce936 --- /dev/null +++ b/src/guidellm/data/preprocessors/formatters.py @@ -0,0 +1,303 @@ +from __future__ import annotations + +from typing import Any, Literal + +from guidellm.data.objects import ( + GenerationRequest, + GenerationRequestArguments, + GenerativeDatasetColumnType, +) +from guidellm.data.preprocessors.preprocessor import ( + DatasetPreprocessor, + PreprocessorRegistry, +) +from guidellm.data.utils import ( + encode_audio_as_dict, + encode_audio_as_file, + encode_image, + encode_video, +) + +__all__ = [ + "GenerativeAudioTranscriptionRequestFormatter", + "GenerativeAudioTranslationRequestFormatter", + "GenerativeChatCompletionsRequestFormatter", + "GenerativeTextCompletionsRequestFormatter", +] + + +@PreprocessorRegistry.register("text_completions") +class GenerativeTextCompletionsRequestFormatter(DatasetPreprocessor): + def __init__( + self, + model: str, + extras: dict[str, Any] | GenerationRequestArguments | None = None, + stream: bool = True, + max_tokens: int | None = None, + max_completion_tokens: int | None = None, + ): + self.model: str | None = model + self.extras = ( + GenerationRequestArguments(**extras) + if extras and isinstance(extras, dict) + else extras + ) + self.stream: bool = stream + self.max_tokens: int | None = max_tokens or max_completion_tokens + + def __call__( + self, columns: dict[GenerativeDatasetColumnType, list[Any]] + ) -> GenerationRequest: + arguments = {"json_body": {}} + stats = {} + + # Add model + if self.model is not None: + arguments["json_body"]["model"] = self.model + + # Configure streaming + if self.stream: + arguments["json_body"].update( + {"stream": True, "stream_options": {"include_usage": True}} + ) + arguments["stream"] = True + + # Handle output tokens + if output_tokens := columns.get("output_tokens_count_column", []): + output_count = output_tokens[0] + stats["output_tokens"] = output_count + arguments["json_body"].update( + {"max_tokens": output_count, "stop": None, "ignore_eos": True} + ) + elif self.max_tokens is not None: + arguments["json_body"]["max_tokens"] = self.max_tokens + + # Handle prompt tokens + if prompt_tokens := columns.get("prompt_tokens_count_column", []): + stats["prompt_tokens"] = prompt_tokens[0] + + # Apply extra arguments + if self.extras: + arguments = GenerationRequestArguments.model_combine_dict( + arguments, self.extras + ) + + # Build prompt + arguments["json_body"]["prompt"] = "".join( + columns.get("prefix_column", []) + columns.get("text_column", []) + ) + + return GenerationRequest( + request_type="text_completions", + arguments=GenerationRequestArguments(**arguments), + stats=stats, + ) + + +@PreprocessorRegistry.register("chat_completions") +class GenerativeChatCompletionsRequestFormatter(DatasetPreprocessor): + def __init__( + self, + model: str, + extras: dict[str, Any] | GenerationRequestArguments | None = None, + stream: bool = True, + max_tokens: int | None = None, + max_completion_tokens: int | None = None, + encode_kwargs: dict[str, Any] | None = None, + ): + self.model = model + self.extras = ( + GenerationRequestArguments(**extras) + if extras and isinstance(extras, dict) + else extras + ) + self.stream = stream + self.max_completion_tokens = max_tokens or max_completion_tokens + self.encode_image_kwargs = ( + encode_kwargs.get("image", {}) if encode_kwargs else {} + ) + self.encode_video_kwargs = ( + encode_kwargs.get("video", {}) if encode_kwargs else {} + ) + self.encode_audio_kwargs = ( + encode_kwargs.get("audio", {}) if encode_kwargs else {} + ) + + def __call__( + self, columns: dict[GenerativeDatasetColumnType, list[Any]] + ) -> GenerationRequest: + arguments = {"json_body": {}} + stats = {} + + # Add model + if self.model is not None: + arguments["json_body"]["model"] = self.model + + # Configure streaming + if self.stream: + arguments["json_body"].update( + {"stream": True, "stream_options": {"include_usage": True}} + ) + arguments["stream"] = True + + # Handle output tokens + if output_tokens := columns.pop("output_tokens_count_column", []): + output_count = output_tokens[0] + stats["output_tokens"] = output_count + arguments["json_body"].update( + { + "max_completion_tokens": output_count, + "stop": None, + "ignore_eos": True, + } + ) + elif self.max_completion_tokens is not None: + arguments["json_body"]["max_completion_tokens"] = self.max_completion_tokens + + # Handle prompt tokens + if prompt_tokens := columns.pop("prompt_tokens_count_column", []): + stats["prompt_tokens"] = prompt_tokens[0] + + # Apply extra arguments + if self.extras: + arguments = GenerationRequestArguments.model_combine_dict( + arguments, self.extras + ) + + # Build messages + arguments["json_body"]["messages"] = ( + [ + {"role": "system", "content": prefix} + for prefix in columns.pop("prefix_column", []) + ] + + [ + {"role": "user", "content": [{"type": "text", "text": text}]} + for text in columns.pop("text_column", []) + ] + + [ + { + "role": "user", + "content": [ + { + "type": "image_url", + "image_url": encode_image( + image, **self.encode_image_kwargs + ), + } + ], + } + for image in columns.pop("image_column", []) + ] + + [ + { + "role": "user", + "content": [ + { + "type": "video_url", + "video_url": encode_video( + video, **self.encode_video_kwargs + ), + } + ], + } + for video in columns.pop("video_column", []) + ] + + [ + { + "role": "user", + "content": [ + { + "type": "input_audio", + "input_audio": encode_audio_as_dict( + audio, **self.encode_audio_kwargs + ), + } + ], + } + for audio in columns.pop("audio_column", []) + ] + ) + + return GenerationRequest( + request_type="chat_completions", + arguments=GenerationRequestArguments(**arguments), + stats=stats, + ) + + +@PreprocessorRegistry.register("audio_transcriptions") +class GenerativeAudioTranscriptionRequestFormatter(DatasetPreprocessor): + def __init__( + self, + model: str, + extra_args: dict[str, Any] | GenerationRequestArguments | None = None, + stream: bool = True, + encode_kwargs: dict[str, Any] | None = None, + ): + self.model = model + self.extra_args = extra_args + self.stream = stream + self.encode_audio_kwargs = encode_kwargs or {} + + def __call__( + self, columns: dict[GenerativeDatasetColumnType, list[Any]] + ) -> GenerationRequest: + arguments = {"json_body": {}} + stats = {} + + # Add model + if self.model is not None: + arguments["json_body"]["model"] = self.model + + # Configure streaming + if self.stream: + arguments["json_body"].update( + {"stream": True, "stream_options": {"include_usage": True}} + ) + + # Apply extra arguments + if self.extra_args: + arguments = GenerationRequestArguments.model_combine_dict( + arguments, self.extra_args + ) + + # Handle stats tokens + if output_tokens := columns.get("output_tokens_count_column", []): + output_count = output_tokens[0] + stats["output_tokens"] = output_count + if prompt_tokens := columns.get("prompt_tokens_count_column", []): + stats["prompt_tokens"] = prompt_tokens[0] + + # Build audio input + if audio := columns.get("audio_column", []): + arguments["files"]["file"] = encode_audio_as_file( + audio[0], **self.encode_audio_kwargs + ) + else: + raise ValueError("No audio column found for audio transcription request.") + + # Build prompt + if (prefix := columns.get("prefix_column", [])) or ( + text := columns.get("text_column", []) + ): + arguments["json_body"]["prompt"] = "".join(prefix) + "".join(text) + + return { + "request": { + "request_type": "audio_transcriptions", + "arguments": arguments, + "stats": stats, + } + } + + +@PreprocessorRegistry.register("audio_translations") +class GenerativeAudioTranslationRequestFormatter( + GenerativeAudioTranscriptionRequestFormatter +): + def __call__( + self, columns: dict[GenerativeDatasetColumnType, list[Any]] + ) -> dict[Literal["request"], dict[Literal["request_type"], Any]]: + result = super().__call__(columns) + result["request"]["request_type"] = "audio_translations" + return result diff --git a/src/guidellm/data/preprocessors/mappers.py b/src/guidellm/data/preprocessors/mappers.py index 1792cb7e..56ca0342 100644 --- a/src/guidellm/data/preprocessors/mappers.py +++ b/src/guidellm/data/preprocessors/mappers.py @@ -1,115 +1,182 @@ from __future__ import annotations -from dataclasses import dataclass -from typing import Any, Literal +from collections import defaultdict +from typing import Any, ClassVar from datasets import Dataset, IterableDataset -from guidellm.data.objects import ( - GenerativeDatasetArgs, - GenerativeDatasetColumnType, +from guidellm.data.objects import GenerativeDatasetColumnType +from guidellm.data.preprocessors.preprocessor import ( + DataDependentPreprocessor, + PreprocessorRegistry, ) -from guidellm.data.preprocessors.objects import DatasetPreprocessor -from guidellm.data.utils import DEFAULT_COLUMN_NAMES -__all__ = ["ColumnMapping", "GenerativeColumnMapper"] +__all__ = ["GenerativeColumnMapper"] + + +@PreprocessorRegistry.register("generative_column_mapper") +class GenerativeColumnMapper(DataDependentPreprocessor): + defaults: ClassVar[dict[str, list[str]]] = { + "prompt_tokens_count_column": ["prompt_tokens_count", "input_tokens_count"], + "output_tokens_count_column": [ + "output_tokens_count", + "completion_tokens_count", + ], + "prefix_column": [ + "system_prompt", + "system", + "prefix", + ], + "text_column": [ + "prompt", + "instruction", + "question", + "input", + "context", + "content", + "conversation", + "turn", + "text", + ], + "image_column": [ + "image", + "picture", + "photo", + "img", + ], + "video_column": [ + "video", + "clip", + "movie", + "footage", + "mp4", + "mov", + "avi", + ], + "audio_column": [ + "audio", + "sound", + "voice", + "speech", + "wav", + "mp3", + ], + } + + @classmethod + def datasets_default_mappings( + cls, datasets: list[Dataset | IterableDataset] + ) -> dict[str, list[tuple[int, str]]]: + mappings: dict[GenerativeDatasetColumnType, list[tuple[int, str]]] = ( + defaultdict(list) + ) + + for index, dataset in enumerate(datasets): + dataset_columns = dataset.column_names or list(next(iter(dataset)).keys()) + + for column_type in cls.defaults: + if column_type in mappings: + continue + + type_names = [ + variant + for name in cls.defaults.get(column_type, []) + for plural in [name, f"{name}s", f"{name}es"] + for variant in [ + plural, + plural.lower(), + plural.upper(), + plural.capitalize(), + ] + ] + + for name in type_names: + if name in dataset_columns: + mappings[column_type].append((index, name)) + break + return mappings -@dataclass -class ColumnMapping: - indices: list[int] - names: list[str] + @classmethod + def datasets_mappings( + cls, + datasets: list[Dataset | IterableDataset], + input_mappings: dict[GenerativeDatasetColumnType, str | list[str]], + ) -> dict[GenerativeDatasetColumnType, list[tuple[int, str]]]: + mappings: dict[GenerativeDatasetColumnType, list[tuple[int, str]]] = ( + defaultdict(list) + ) + datasets_named_indices = { + ( + dataset.info.dataset_name + if dataset.info and dataset.info.dataset_name + else index + ): index + for index, dataset in enumerate(datasets) + } + datasets_columns = { + index: dataset.column_names or list(next(iter(dataset)).keys()) + for index, dataset in enumerate(datasets) + } + + for column_type, names in input_mappings.items(): + mappings[column_type] = [] + + for name in names if isinstance(names, list) else [names]: + dataset, column_name = name.split(".", 1) + dataset_index = ( + int(dataset) + if dataset.isdigit() + else datasets_named_indices.get(dataset) + ) + if dataset_index is None or dataset_index >= len(datasets): + raise ValueError( + f"Dataset '{dataset}' not found in datasets: " + f"{datasets_named_indices}." + ) + if column_name not in datasets_columns[dataset_index]: + raise ValueError( + f"Column '{column_name}' not found in dataset '{dataset}' " + f"columns: {datasets_columns[dataset_index]}." + ) + mappings[column_type].append((dataset_index, column_name)) + return mappings -class GenerativeColumnMapper(DatasetPreprocessor): - def __init__(self): - self.datasets: list[Dataset | IterableDataset] | None = None - self.data_args: list[GenerativeDatasetArgs] | None = None - self.column_mappings: ( - dict[GenerativeDatasetColumnType, ColumnMapping | None] | None - ) = None + def __init__( + self, + column_mappings: dict[GenerativeDatasetColumnType, str | list[str]] + | None = None, + ): + self.input_mappings = column_mappings + self.datasets_column_mappings: ( + dict[GenerativeDatasetColumnType, list[tuple[int, str]]] | None + ) - def __call__( - self, row: dict[Literal["items"], tuple[dict[str, Any]]] - ) -> dict[str, Any]: - if ( - self.datasets is None - or self.data_args is None - or self.column_mapping is None - ): - raise ValueError("GenerativeColumnMapper not initialized with data.") + def __call__(self, row: dict[int, list[dict[str, Any]]]) -> dict[str, list[Any]]: + if self.datasets_column_mappings is None: + raise ValueError("DefaultGenerativeColumnMapper not setup with data.") - mapped: dict[GenerativeDatasetColumnType, list[Any]] = {} items = row.pop("items") + mapped: dict[GenerativeDatasetColumnType, list[Any]] = defaultdict(list) - for column_type, column_mapping in self.column_mapping.items(): - mapped[column_type] = [ - items[index].get(name) - for index, name in zip(column_mapping.indices, column_mapping.names) - ] + for column_type, column_mappings in self.datasets_column_mappings.items(): + for ( + dataset_index, + dataset_column, + ) in column_mappings: + mapped[column_type].append(items[dataset_index][dataset_column]) - return mapped + return dict(mapped) - def init_data( + def setup_data( self, datasets: list[Dataset | IterableDataset], - data_args: list[GenerativeDatasetArgs], + data_args: list[dict[str, Any]], ): - self.datasets = datasets - self.data_args = data_args - self.column_mapping = self.generate_column_mapping() - - def generate_column_mapping( - self, - ) -> dict[GenerativeDatasetColumnType, ColumnMapping]: - mappings: dict[GenerativeDatasetColumnType, ColumnMapping] = {} - # Map any columns specified in the GenerativeDatasetArgs first - self._fill_mappings_from_data_args(mappings) - # For standard column types not mapped, fill in first one found from defaults - self._fill_mappings_from_defaults(mappings) - - return mappings - - def _fill_mappings_from_data_args( - self, mappings: dict[GenerativeDatasetColumnType, ColumnMapping] - ): - for index, args in enumerate(self.data_args): - args_column_mappings = args.get_mapped_columns() - for column_type, column_name in args_column_mappings.items(): - if column_type not in mappings: - mappings[column_type] = ColumnMapping(indices=[], names=[]) - column_mapping = mappings[column_type] - - for name in ( - column_name if isinstance(column_name, list) else [column_name] - ): - if name not in self.datasets[index].column_names: - raise ValueError( - f"Column '{name}' not found in dataset columns: " - f"{self.datasets[index].column_names}" - ) - column_mapping.indices.append(index) - column_mapping.names.append(name) - - def _fill_mappings_from_defaults( - self, mappings: dict[GenerativeDatasetColumnType, ColumnMapping] - ): - for column_type, default_names in DEFAULT_COLUMN_NAMES.items(): - if column_type in mappings: - continue - - for index, dataset in enumerate(self.datasets): - for name in default_names: - if name in dataset.column_names: - mappings[column_type] = ColumnMapping( - indices=[index], names=[name] - ) - break - # Check for plural form of the name - if f"{name}s" in dataset.column_names: - mappings[column_type] = ColumnMapping( - indices=[index], names=[f"{name}s"] - ) - break - if column_type in mappings: - break + _ = data_args # Unused for this mapper + self.datasets_column_mappings = ( + self.datasets_default_mappings(datasets) + if self.input_mappings is None + else self.datasets_mappings(datasets, self.input_mappings) + ) diff --git a/src/guidellm/data/preprocessors/objects.py b/src/guidellm/data/preprocessors/objects.py deleted file mode 100644 index 831f944d..00000000 --- a/src/guidellm/data/preprocessors/objects.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import annotations - -from typing import Any, Protocol, runtime_checkable - -from datasets import Dataset, IterableDataset - -from guidellm.data.objects import GenerativeDatasetArgs - -__all__ = ["DatasetPreprocessor"] - - -@runtime_checkable -class DatasetPreprocessor(Protocol): - def init_data( - self, - datasets: list[Dataset | IterableDataset], - data_args: list[GenerativeDatasetArgs], - ): ... - - def __call__(self, item: dict[str, Any]) -> dict[str, Any]: ... diff --git a/src/guidellm/data/preprocessors/preprocessor.py b/src/guidellm/data/preprocessors/preprocessor.py new file mode 100644 index 00000000..eefb53d3 --- /dev/null +++ b/src/guidellm/data/preprocessors/preprocessor.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from typing import Any, Protocol, Union, runtime_checkable + +from datasets import Dataset, IterableDataset + +from guidellm.utils import RegistryMixin + +__all__ = ["DataDependentPreprocessor", "DatasetPreprocessor", "PreprocessorRegistry"] + + +@runtime_checkable +class DatasetPreprocessor(Protocol): + def __call__(self, item: dict[str, Any]) -> dict[str, Any]: ... + + +@runtime_checkable +class DataDependentPreprocessor(DatasetPreprocessor, Protocol): + def setup_data( + self, + datasets: list[Dataset | IterableDataset], + data_args: list[dict[str, Any]], + ): ... + + +class PreprocessorRegistry( + RegistryMixin[Union[DataDependentPreprocessor, type[DataDependentPreprocessor]]] +): + pass diff --git a/src/guidellm/data/processor.py b/src/guidellm/data/processor.py new file mode 100644 index 00000000..645683c4 --- /dev/null +++ b/src/guidellm/data/processor.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from typing import Any + +from transformers import ( # type: ignore[import] + AutoTokenizer, + PreTrainedTokenizerBase, +) + +__all__ = ["ProcessorFactory"] + + +class ProcessorFactory: + def __init__( + self, + processor: str | PreTrainedTokenizerBase, + processor_args: dict[str, Any] | None = None, + ) -> None: + self.processor = processor + self.processor_args = processor_args or {} + + def __call__(self) -> PreTrainedTokenizerBase: + if isinstance(self.processor, PreTrainedTokenizerBase): + return self.processor + else: + self.processor = AutoTokenizer.from_pretrained( + self.processor, + **(self.processor_args or {}), + ) + return self.processor diff --git a/src/guidellm/data/utils/__init__.py b/src/guidellm/data/utils/__init__.py new file mode 100644 index 00000000..aac657f8 --- /dev/null +++ b/src/guidellm/data/utils/__init__.py @@ -0,0 +1,34 @@ +from .dataset import DEFAULT_SPLITS, resolve_dataset_split +from .functions import ( + download_audio, + download_image, + download_video, + encode_audio, + encode_audio_as_dict, + encode_audio_as_file, + encode_image, + encode_image_base64, + encode_video, + encode_video_base64, + get_file_format, + is_url, + resize_image, +) + +__all__ = [ + "DEFAULT_SPLITS", + "download_audio", + "download_image", + "download_video", + "encode_audio", + "encode_audio_as_dict", + "encode_audio_as_file", + "encode_image", + "encode_image_base64", + "encode_video", + "encode_video_base64", + "get_file_format", + "is_url", + "resize_image", + "resolve_dataset_split", +] diff --git a/src/guidellm/data/utils.py b/src/guidellm/data/utils/dataset.py similarity index 54% rename from src/guidellm/data/utils.py rename to src/guidellm/data/utils/dataset.py index d2fa1f9c..9656c1a7 100644 --- a/src/guidellm/data/utils.py +++ b/src/guidellm/data/utils/dataset.py @@ -1,18 +1,10 @@ from __future__ import annotations -import contextlib -import math -from collections.abc import Iterator -from typing import Any, Literal +from typing import Literal from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict -__all__ = [ - "DEFAULT_COLUMN_NAMES", - "DEFAULT_SPLITS", - "datasets_item_iterator", - "resolve_dataset_split", -] +__all__ = ["DEFAULT_SPLITS", "resolve_dataset_split"] DEFAULT_SPLITS: dict[Literal["train", "calib", "val", "test"], list[str]] = { @@ -77,54 +69,9 @@ } -DEFAULT_COLUMN_NAMES: dict[str, list[str]] = { - "prompt_tokens_count": ["prompt_tokens_count", "input_tokens_count"], - "output_tokens_count": ["output_tokens_count", "completion_tokens_count"], - "prefix_column": [ - "system_prompt", - "system", - "prefix", - ], - "text_column": [ - "prompt", - "instruction", - "question", - "input", - "context", - "content", - "conversation", - "turn", - "text", - ], - "image_column": [ - "image", - "picture", - "photo", - "img", - ], - "video_column": [ - "video", - "clip", - "movie", - "footage", - "mp4", - "mov", - "avi", - ], - "audio_column": [ - "audio", - "sound", - "voice", - "speech", - "wav", - "mp3", - ], -} - - def resolve_dataset_split( dataset: Dataset | IterableDataset | DatasetDict | IterableDatasetDict, - split: str | None, + split: str | None = None, ) -> Dataset | IterableDataset: if split is not None and isinstance(dataset, (DatasetDict, IterableDatasetDict)): if split in dataset: @@ -145,22 +92,3 @@ def resolve_dataset_split( return dataset[default_split] return dataset[list(dataset.keys())[0]] - - -def datasets_item_iterator( - datasets: list[Dataset | IterableDataset], - data_samples: int, -) -> Iterator[dict[Literal["items"], tuple[dict[str, Any]]]]: - dataset_iters = [iter(dataset) for dataset in datasets] - gen_count = 0 - - with contextlib.suppress(StopIteration): - while gen_count < data_samples or data_samples <= 0 or data_samples == math.inf: - yield {"items": tuple(next(dataset_iter) for dataset_iter in dataset_iters)} - gen_count += 1 - - if gen_count < data_samples and data_samples > 0 and data_samples != math.inf: - raise ValueError( - f"Requested {data_samples} samples, but only {gen_count} available " - "from the provided datasets." - ) diff --git a/src/guidellm/data/formatters/filters.py b/src/guidellm/data/utils/functions.py similarity index 73% rename from src/guidellm/data/formatters/filters.py rename to src/guidellm/data/utils/functions.py index 8dd4e445..c9ca20ed 100644 --- a/src/guidellm/data/formatters/filters.py +++ b/src/guidellm/data/utils/functions.py @@ -3,7 +3,7 @@ import base64 import io from pathlib import Path -from typing import Any, Callable, Literal +from typing import Any, Literal import datasets import httpx @@ -11,15 +11,15 @@ import numpy as np import soundfile from PIL import Image as PILImage - -from guidellm.utils import RegistryMixin +from pydub import AudioSegment __all__ = [ - "JinjaFiltersRegistry", "download_audio", "download_image", "download_video", "encode_audio", + "encode_audio_as_dict", + "encode_audio_as_file", "encode_image", "encode_image_base64", "encode_video", @@ -30,16 +30,10 @@ ] -class JinjaFiltersRegistry(RegistryMixin[Callable[..., Any]]): - pass - - -@JinjaFiltersRegistry.register("is_url") def is_url(text: Any) -> bool: return isinstance(text, str) and text.startswith(("http://", "https://")) -@JinjaFiltersRegistry.register("encode_image") def encode_image( image: bytes | str | Path | np.ndarray | PILImage.Image | datasets.Image, max_size: int | None = None, @@ -90,7 +84,6 @@ def encode_image( ) -@JinjaFiltersRegistry.register("encode_image_base64") def encode_image_base64( image: bytes | str | Path | np.ndarray | PILImage.Image, width: int | None = None, @@ -137,7 +130,6 @@ def encode_image_base64( return f"data:image/jpeg;base64,{image_base64}" -@JinjaFiltersRegistry.register("resize_image") def resize_image( image: PILImage.Image, width: int | None = None, @@ -183,14 +175,12 @@ def resize_image( return image -@JinjaFiltersRegistry.register("download_image") def download_image(url: str) -> bytes: response = httpx.get(url) response.raise_for_status() return response.content -@JinjaFiltersRegistry.register("encode_video") def encode_video( video: bytes | str | Path | datasets.Video, encode_type: Literal["base64", "url"] | None = None, @@ -221,7 +211,6 @@ def encode_video( return encode_video_base64(video=video) -@JinjaFiltersRegistry.register("encode_video_base64") def encode_video_base64(video: bytes | str | Path) -> str: if ( isinstance(video, str) @@ -246,78 +235,121 @@ def encode_video_base64(video: bytes | str | Path) -> str: return f"data:video/{video_format};base64,{video_base64}" -@JinjaFiltersRegistry.register("download_video") def download_video(url: str) -> tuple[bytes, str]: response = httpx.get(url) response.raise_for_status() return response.content, get_file_format(url) -@JinjaFiltersRegistry.register("encode_audio") -def encode_audio( +def encode_audio_as_dict( audio: bytes | str | Path | dict | np.ndarray, - sample_rate: int | None = None, + sample_rate: int | None = 16000, max_duration: float | None = None, -) -> dict[str, str]: - """ - Input audio types: - - bytes: raw audio bytes - - str: file path on disk or URL - - pathlib.Path: file path on disk - - dict: {"data": base64_string, "format": "wav"} format - - numpy.ndarray: audio array, assumed to be at sample_rate if provided - - sample_rate: sample rate of the input audio if input is np.ndarray - target_sample_rate: resample to this rate if provided - duration: limit audio to this duration in seconds if provided + mono: bool = True, + audio_format: str = "mp3", + bitrate: str = "64k", +) -> dict[Literal["data", "format"], Any]: + content, file_name, file_format = encode_audio( + audio=audio, + sample_rate=sample_rate or 16000, + max_duration=max_duration, + mono=mono, + audio_format=audio_format, + bitrate=bitrate, + ) - Returns dict with format: - { - "data": base64_encoded_audio_bytes, - "format": "wav" + return { + "data": base64.b64encode(content).decode("utf-8"), + "format": file_format, } - """ - if is_url(audio): - audio, _ = download_audio(audio) - if isinstance(audio, dict): - if "data" not in audio: - raise ValueError("Audio dict must contain 'data' key") - audio = base64.b64decode(audio["data"]) - if isinstance(audio, bytes): - audio_data, sample_rate = librosa.load(io.BytesIO(audio), sr=sample_rate) +def encode_audio_as_file( + audio: bytes | str | Path | dict | np.ndarray, + sample_rate: int | None = 16000, + max_duration: float | None = None, + mono: bool = True, + audio_format: str = "mp3", + bitrate: str = "64k", +) -> tuple[str, bytes, str]: + content, file_name, file_format = encode_audio( + audio=audio, + sample_rate=sample_rate or 16000, + max_duration=max_duration, + mono=mono, + audio_format=audio_format, + bitrate=bitrate, + ) + + return file_name, content, f"audio/{file_format}" + + +def encode_audio( + audio: bytes | str | Path | dict, + sample_rate: int = 16000, + max_duration: float | None = None, + mono: bool = True, + audio_format: str = "mp3", + bitrate: str = "64k", +) -> tuple[bytes, str, str]: + file_name = "audio.wav" + + if is_url(audio): + audio, file_name, _ = download_audio(audio) + elif isinstance(audio, dict): + file_name = audio.get("name", "audio") + audio = base64.b64decode(audio["data"]) elif isinstance(audio, (str, Path)): - audio_data, sample_rate = librosa.load(str(audio), sr=sample_rate) - elif isinstance(audio, np.ndarray): - if sample_rate is None: - raise ValueError("sample_rate must be provided for numpy arrays") - audio_data = audio - else: + path = Path(audio) + file_name = get_file_name(path) + audio = path.read_bytes() + elif not isinstance(audio, bytes): raise ValueError(f"Unsupported audio type: {type(audio)}") - if max_duration is not None: - max_samples = int(max_duration * sample_rate) - if len(audio_data) > max_samples: - audio_data = audio_data[:max_samples] + processed_audio, sample_rate = librosa.load( + io.BytesIO(audio), + sr=sample_rate, + mono=mono, + duration=max_duration, + ) + # Encode to target format buffer = io.BytesIO() - soundfile.write(buffer, audio_data, sample_rate, format="WAV", subtype="PCM_16") + if audio_format.lower() == "mp3": + temp_wav = io.BytesIO() + soundfile.write( + temp_wav, + processed_audio, + sample_rate, + format="WAV", + subtype="PCM_16", + ) + temp_wav.seek(0) + AudioSegment.from_wav(temp_wav).export(buffer, format="mp3", bitrate=bitrate) + else: + soundfile.write( + buffer, + processed_audio, + sample_rate, + format=audio_format.upper(), + ) - return {"data": buffer.getvalue(), "format": "wav"} + return buffer.getvalue(), file_name, audio_format.lower() -@JinjaFiltersRegistry.register("download_audio") -def download_audio(url: str) -> tuple[bytes, str]: - """Download audio from URL and return bytes with format.""" +def download_audio(url: str) -> tuple[bytes, str, str]: response = httpx.get(url) response.raise_for_status() content = response.content - audio_format = get_file_format(url) - return content, audio_format + + return content, get_file_name(url), get_file_format(url) + + +def get_file_name(path: Path | str) -> str: + """Get file name from path.""" + return Path(path).name -@JinjaFiltersRegistry.register("get_file_format") def get_file_format(path: Path | str) -> str: """Get file format from path extension.""" suffix = Path(path).suffix.lower() diff --git a/src/guidellm/scheduler/worker.py b/src/guidellm/scheduler/worker.py index 5f2fb74b..1832d25f 100644 --- a/src/guidellm/scheduler/worker.py +++ b/src/guidellm/scheduler/worker.py @@ -233,6 +233,12 @@ async def _processing_startup(self): self.backend_started = True await self.backend.validate() + # Wait for all processes to be ready + await wait_for_sync_barrier( + self.startup_barrier, + poll_interval=self.messaging.poll_interval, + ) + # Get messaging system ready await self.messaging.start( receive_stop_criteria=[self.requests_generated_event], @@ -240,12 +246,6 @@ async def _processing_startup(self): ) self.messaging_started = True - # Wait for all processes to be ready - await wait_for_sync_barrier( - self.startup_barrier, - poll_interval=self.messaging.poll_interval, - ) - self.startup_completed = True async def _processing_shutdown(self): diff --git a/src/guidellm/scheduler/worker_group.py b/src/guidellm/scheduler/worker_group.py index e64d64fc..9baccd1b 100644 --- a/src/guidellm/scheduler/worker_group.py +++ b/src/guidellm/scheduler/worker_group.py @@ -495,6 +495,7 @@ def _iter(): count = 0 request_info: ScheduledRequestInfo = None + for request in _iter(): count += 1 diff --git a/src/guidellm/settings.py b/src/guidellm/settings.py index 20d9ff96..5c360eff 100644 --- a/src/guidellm/settings.py +++ b/src/guidellm/settings.py @@ -145,7 +145,7 @@ class Settings(BaseSettings): mp_max_pending_buffer_percent: float = 0.5 mp_max_worker_buffer_percent: float = 0.2 max_concurrency: int = 512 - max_worker_processes: int = 10 + max_worker_processes: int = 2 scheduler_start_delay_non_distributed: float = 1.0 constraint_error_window_size: float = 30 constraint_error_min_processed: float = 30 diff --git a/src/guidellm/utils/messaging.py b/src/guidellm/utils/messaging.py index c56ec29a..2f631a87 100644 --- a/src/guidellm/utils/messaging.py +++ b/src/guidellm/utils/messaging.py @@ -610,6 +610,8 @@ def _send_messages_task_thread( # noqa: C901, PLR0912 except (culsans.QueueFull, queue.Full): pass + time.sleep(0) # Yield to other threads + def _receive_messages_task_thread( # noqa: C901 self, receive_callback: Callable[[Any], Any] | None, @@ -649,6 +651,8 @@ def _receive_messages_task_thread( # noqa: C901 except (culsans.QueueFull, queue.Full): pass + time.sleep(0) # Yield to other threads + class InterProcessMessagingManagerQueue( InterProcessMessagingQueue[SendMessageT, ReceiveMessageT]