diff --git a/.nvim.lua b/.nvim.lua new file mode 100644 index 000000000..ec0ca6948 --- /dev/null +++ b/.nvim.lua @@ -0,0 +1,3 @@ +vim.lsp.config("pyright", { + root_markers = { ".git" }, +}) diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES index 21c389ba9..9a99c3442 100644 --- a/THIRD-PARTY-NOTICES +++ b/THIRD-PARTY-NOTICES @@ -33,6 +33,7 @@ huggingface-hub Apache-2.0 https://github.com/huggingface/huggingface_h loguru MIT https://github.com/Delgan/loguru numpy BSD-3-Clause https://github.com/numpy/numpy nvidia-ml-py BSD-3-Clause https://pypi.org/project/nvidia-ml-py/ +pydantic MIT https://github.com/pydantic/pydantic safetensors Apache-2.0 https://github.com/huggingface/safetensors torch BSD-3-Clause https://pytorch.org torchvision BSD-3-Clause https://github.com/pytorch/vision diff --git a/configs/omnidreams_demo_replay_benchmarks.json b/configs/omnidreams_demo_replay_benchmarks.json new file mode 100644 index 000000000..3ac6e4019 --- /dev/null +++ b/configs/omnidreams_demo_replay_benchmarks.json @@ -0,0 +1,88 @@ +{ + "schema_version": 1, + "description": "Manual one-minute local benchmark scenarios for comparing the legacy Omnidreams single-view runner against the experimental shared demo replay path. The runner writes the legacy stacked HDMap/RGB canvas while the shared demo writes generated RGB output, so use the report for manual MP4 comparison rather than automatic pixel quality scoring.", + "scenarios": [ + { + "id": "omnidreams-sv-runner-baseline", + "name": "Omnidreams single-view runner baseline", + "description": "Runs the stable legacy Omnidreams single-view runner with the bundled example data for the same one-minute block count used by the shipped Omnidreams baseline.", + "report_group": { + "id": "omnidreams-demo", + "name": "Omnidreams Demo Comparison" + }, + "tags": [ + "manual", + "gpu", + "real-demo", + "omnidreams", + "i2v", + "replay", + "baseline" + ], + "env": { + "CUBLAS_WORKSPACE_CONFIG": ":4096:8", + "PYTORCH_CUDA_ALLOC_CONF": "expandable_segments:True" + }, + "command": [ + "uv", + "run", + "--project", + "integrations/omnidreams", + "flashdreams-run", + "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae", + "--example-data", + "True", + "--example-data-uuid", + "239560dc-33d1-11ef-9720-00044bcbccac", + "--total-blocks", + "226" + ], + "warmup_steps": 1, + "quality_baseline_compare": false, + "timeout_s": 7200 + }, + { + "id": "omnidreams-sv-demo-replay", + "name": "Omnidreams shared demo replay", + "description": "Runs the experimental shared demo API replay path with the same stable non-perf preset, bundled example data, and one-minute block count as the legacy runner.", + "report_group": { + "id": "omnidreams-demo", + "name": "Omnidreams Demo Comparison" + }, + "tags": [ + "manual", + "gpu", + "real-demo", + "omnidreams", + "i2v", + "replay", + "shared-demo" + ], + "env": { + "CUBLAS_WORKSPACE_CONFIG": ":4096:8", + "PYTORCH_CUDA_ALLOC_CONF": "expandable_segments:True" + }, + "command": [ + "uv", + "run", + "--project", + "integrations/omnidreams", + "omnidreams-demo", + "replay", + "--preset-id", + "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae", + "--example-data", + "--example-data-uuid", + "239560dc-33d1-11ef-9720-00044bcbccac", + "--total-blocks", + "226", + "--output", + "{output_dir}/omnidreams-sv-demo-replay.mp4" + ], + "output_dir_arg": null, + "warmup_steps": 1, + "quality_baseline_compare": false, + "timeout_s": 7200 + } + ] +} diff --git a/docs/source/_static/diagrams/flashdreams-runtime-data-flow.png b/docs/source/_static/diagrams/flashdreams-runtime-data-flow.png new file mode 100644 index 000000000..d94ac7357 Binary files /dev/null and b/docs/source/_static/diagrams/flashdreams-runtime-data-flow.png differ diff --git a/docs/source/_static/diagrams/flashdreams-runtime.png b/docs/source/_static/diagrams/flashdreams-runtime.png new file mode 100644 index 000000000..7178cc6af Binary files /dev/null and b/docs/source/_static/diagrams/flashdreams-runtime.png differ diff --git a/docs/source/developer_guides/flashdreams_runtime.rst b/docs/source/developer_guides/flashdreams_runtime.rst new file mode 100644 index 000000000..85159ec20 --- /dev/null +++ b/docs/source/developer_guides/flashdreams_runtime.rst @@ -0,0 +1,307 @@ +.. SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-License-Identifier: Apache-2.0 +.. +.. Licensed under the Apache License, Version 2.0 (the "License"); +.. you may not use this file except in compliance with the License. +.. You may obtain a copy of the License at +.. +.. http://www.apache.org/licenses/LICENSE-2.0 +.. +.. Unless required by applicable law or agreed to in writing, software +.. distributed under the License is distributed on an "AS IS" BASIS, +.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.. See the License for the specific language governing permissions and +.. limitations under the License. + +FlashDreams runtime architecture +================================ + +The FlashDreams runtime connects interactive controls to an autoregressive +inference pipeline and routes the generated frames to an output destination. +This page defines the target architecture and the boundaries between its +components. It is a design contract rather than a reference for an existing +Python API. + +Architecture overview +--------------------- + +.. figure:: /_static/diagrams/flashdreams-runtime.png + :alt: FlashDreams runtime architecture and its input and output data flow. + :align: center + :width: 100% + :class: zoomable + + The application owns the runtime components. Dashed arrows show data flow; + solid lines with diamonds show ownership. Solid boxes are classes and + dashed boxes are data. + +.. image:: /_static/diagrams/flashdreams-runtime-data-flow.png + :alt: FlashDreams user and global conditioning data flow into an inference session. + :align: center + :width: 70% + :class: zoomable + +Application layer +----------------- + +``Application`` is the composition and lifecycle boundary for an interactive +FlashDreams runtime. It owns ``InputSystem``, ``InputMapping``, +``OutputTarget``, and the main ``InferenceSession`` that runs the inference +pipeline. These components are passed to the application through dependency +injection. The application connects them, drives the runtime loop, and shuts +them down in a defined order. + +Keeping orchestration in the application gives each child component a narrow +responsibility. Device handling stays out of model execution, model-specific +input conversion stays out of device handling, and presentation stays out of +the inference session. + +InputSystem +~~~~~~~~~~~ + +``InputSystem`` accepts an ordered list of timestamped raw input events +supplied by the application or an upstream input framework. It converts that +list into an ordered stream of timestamped, canonicalized user-input events. +Raw events can include keyboard key-down and key-up events, digital wheel +readings, controller joystick readings, or Meta Quest hand-tracking readings. + +`Unity's Input System +`_ +provides similar concepts for devices and actions. FlashDreams has a narrower +boundary: it does not poll devices or configure key bindings. Device polling, +event collection, and binding configuration are handled upstream. + +.. admonition:: Preserving events during slow inference + :class: note + + A call to ``InferenceSession.step()`` can take approximately 100--1000 ms + because it runs a latent-diffusion step. The upstream input source must + preserve every raw input change that occurs while inference is running + rather than retain only the most recent device state. On the next runtime + iteration, the application passes the complete ordered raw-event list to + ``InputSystem``, which converts every event without collapsing intermediate + states. + + For example, assume positive *x* means right and positive *y* means forward. + The raw-event list contains a W key-down at 5 ms, a D key-down at 10 ms, a W + key-up at 50 ms, an S key-down at 60 ms, a D key-up at 70 ms, and an S + key-up at 80 ms. ``InputSystem`` produces this canonical event stream: + + .. code-block:: text + + [ + ( 5 ms, vec2(0, 1)), # W pressed + (10 ms, vec2(1, 1)), # D pressed; W remains pressed + (50 ms, vec2(1, 0)), # W released + (60 ms, vec2(1, -1)), # S pressed; D remains pressed + (70 ms, vec2(0, -1)), # D released + (80 ms, vec2(0, 0)), # S released + ] + + The timestamps are the original raw-event times, not the time at which + ``InputSystem`` processes the list. + +This layer handles raw-to-canonical conversion concerns such as device-value +normalization, dead zones, axis conventions, and event ordering. Its output +describes the user's intent in a stable, device-independent form. It does not +create model embeddings or know how a particular inference pipeline represents +conditioning. + +InputMapping +~~~~~~~~~~~~ + +``InputMapping`` consumes the ordered list of timestamped, canonicalized +user-input events returned by ``InputSystem`` and produces the model-ready, +per-step inference conditioning expected by an ``InferenceSession``. Depending +on the model, this conversion can include embedding control values, rendering +a control representation, changing layouts, or assembling tensors. + +.. admonition:: Example + :class: note + + ``integrations/omnidreams`` represents canonicalized driving input as a + floating-point steering-wheel angle and a floating-point paddle/brake value. + Its ``InputMapping`` runs the vehicle-dynamics simulation, renders the + resulting HD map with the Ludus renderer, and produces the rendered RGB HD + map as the per-step user-input condition. The resulting tensor has shape + ``(3, H, W)``. + +The ``(3, H, W)`` output is specific to OmniDreams, not a universal +``InputMapping`` contract. Another ``InferenceSession`` might expect an image +embedding as its condition. In that case, ``InputMapping`` can use an image +encoder to encode the frame and return the resulting embedding instead. + +This is the boundary between application-level control semantics and +model-specific conditioning. Replacing a keyboard with a controller should +usually affect the ``InputSystem``; replacing the model or its control encoder +should usually affect the ``InputMapping``. + +OutputTarget +~~~~~~~~~~~~ + +``OutputTarget`` consumes the ``FrameStream`` produced by the inference +session. A target can present frames in a native window, send them to a video +encoder, publish them through a WebRTC host, or adapt them for another output +system. + +The output target owns presentation and transport concerns. It must not be +responsible for interpreting user controls or advancing model inference. +Buffering and backpressure policies belong at this output boundary so that a +slow consumer does not silently redefine inference behavior. + +InferenceSession +~~~~~~~~~~~~~~~~ + +``InferenceSession`` is the execution boundary for the main inference +pipeline. It accepts inference input, maintains the state required across +autoregressive steps, runs the pipeline, and exposes generated output as a +``FrameStream``. + +The session receives model-ready data only. It does not poll devices, +canonicalize user intent, or present generated frames. After accepting global +inference conditioning, it retains the active global condition across later +steps until the application supplies an update or the session ends. + +Input data flow +--------------- + +The input path deliberately separates physical device readings, semantic +controls, and model-ready conditioning. This separation allows devices and +models to evolve independently. + +User conditioning +~~~~~~~~~~~~~~~~~ + +Raw user input +^^^^^^^^^^^^^^ + +**Raw user input** is a reading or event in the vocabulary of a physical input +source. Examples include: + +* WASD key presses and releases; +* digital wheel input; +* controller joystick readings; and +* Meta Quest hand-tracking readings. + +Raw events can depend on a particular device, driver, and upstream input +framework. They are collected and timestamped before entering FlashDreams. The +application passes the ordered raw-event list to ``InputSystem``; raw events +must not be passed directly to ``InferenceSession``. + +Canonicalized user input +^^^^^^^^^^^^^^^^^^^^^^^^ + +**Canonicalized user input** expresses user intent in the vocabulary of the +interaction, independent of the device that produced it. Typical structures +include: + +* a 2D character-movement vector and a 2D camera-movement vector for + character-control games; +* a floating-point wheel value and a floating-point paddle value for driving; + and +* hand-tracking positions, correction vectors, or another agreed semantic hand + control for Cosmos-style interaction models. + +The exact structure depends on the interaction type and can evolve as its +semantics become clearer. ``InputSystem`` emits these values as an ordered +stream of timestamped, canonicalized events. The important invariant is that +equivalent intent from different devices has the same canonical +representation. + +Per-step inference conditioning +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Per-step inference conditioning** is the model-ready encoding of +canonicalized user input for one inference step. ``InputMapping`` produces it by +performing whatever embedding, rendering, or tensor conversion the selected +model requires. + +This term distinguishes the changing user control for one step from global +conditioning, which normally remains stable across many steps. + +Inference input +^^^^^^^^^^^^^^^ + +**Inference input** is the complete input delivered to ``InferenceSession``. +It is the runtime boundary object, not another name for a raw or canonicalized +control. It can carry: + +* the per-step inference conditioning; and +* optional global inference conditioning. + +The first inference step generally carries both. On later steps, the global +condition remains active inside the session, so the application normally sends +only new per-step inference conditioning. Omitting global conditioning means +"continue using the active global condition"; it must not mean "clear the +global condition." + +Global conditioning +~~~~~~~~~~~~~~~~~~~ + +Global conditioning establishes the scene-level context for generation and can +contain model-specific data. Two of the most common examples are: + +* a **global conditioning frame**, sometimes called an initial frame by a + model; and +* a **global conditioning prompt**, containing the text description for the + run. + +The runtime uses *global conditioning frame* instead of *initial frame* +because the condition is not inherently limited to initialization. A future +runtime can replace it while a session is already running. + +Raw and canonicalized global conditioning +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**Raw global conditioning** is the application-facing representation. For +example, the prompt is text and the conditioning frame is image data. + +**Canonicalized global conditioning** is the model-ready representation sent +through inference input as **global inference conditioning**. A text prompt is +typically converted into embedded tokens. A conditioning frame is +model-dependent: one model might convert it into CLIP embeddings, while +another might retain a frame or spatial representation such as an HD-map +condition. + +For that reason, *canonicalized* is preferred over *embedded* for the combined +global condition. It does not incorrectly imply that every part of the global +condition must become an embedding. + +Updating global conditioning during a run +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Although mid-run global-conditioning updates are not implemented yet, the +runtime contracts must leave room for them. An application could, for example, +submit a new conditioning frame and prompt to make an OmniDreams driving scene +transition suddenly to rainy weather. + +A later inference input can therefore carry new global inference conditioning +alongside its per-step conditioning. The session then treats it as a change to +the active global context. When no update is present, the session reuses the +previous context. The exact effects on model history, caches, and transition +behavior are model-specific and must be defined by the corresponding pipeline; +the application-level contract must not assume that global conditioning is +initialization-only. + +End-to-end runtime loop +----------------------- + +At a conceptual level, one runtime iteration follows these steps: + +#. ``Application`` passes ``InputSystem`` the ordered list of timestamped + raw input events accumulated upstream since the previous runtime iteration. +#. ``InputSystem`` converts that list into an ordered stream of timestamped, + canonicalized user-input events. +#. ``InputMapping`` consumes this canonical event stream and produces per-step + inference conditioning. +#. ``Application`` packages that data as inference input, adding canonicalized + global conditioning on the first step or whenever it changes. +#. ``InferenceSession`` advances the pipeline and emits generated frames + through ``FrameStream``. +#. ``OutputTarget`` consumes the stream for display, encoding, transport, or + another presentation path. + +These boundaries are the central architectural constraint: an upstream input +source collects timestamped raw events, ``InputSystem`` produces canonical +events, ``InputMapping`` produces model-ready conditioning, +``InferenceSession`` runs the model, and ``OutputTarget`` delivers the result. diff --git a/docs/source/developer_guides/index.rst b/docs/source/developer_guides/index.rst index 7cc2bac85..7b7b50573 100644 --- a/docs/source/developer_guides/index.rst +++ b/docs/source/developer_guides/index.rst @@ -60,6 +60,7 @@ generated clip, see :doc:`/quickstart/index`. :hidden: :maxdepth: 1 + flashdreams_runtime inference_pipeline_overview config_system new_integration diff --git a/docs/source/developer_guides/local_benchmarks.rst b/docs/source/developer_guides/local_benchmarks.rst index 687d95aa2..62842ba32 100644 --- a/docs/source/developer_guides/local_benchmarks.rst +++ b/docs/source/developer_guides/local_benchmarks.rst @@ -132,6 +132,27 @@ input stream is shorter than the requested duration. ``interactive-drive`` is left out of this shipped MP4 suite for now because its public CLI is a live presenter rather than a file-writing runner. +Omnidreams Shared Demo Comparison +--------------------------------- + +``configs/omnidreams_demo_replay_benchmarks.json`` contains a one-minute manual +comparison between the legacy Omnidreams single-view runner and the experimental +shared demo replay path: + +.. code-block:: bash + + uv run flashdreams-benchmark \ + --scenario-file configs/omnidreams_demo_replay_benchmarks.json \ + --scenario omnidreams-sv-runner-baseline \ + --scenario omnidreams-sv-demo-replay \ + --output-dir artifacts/benchmarks/omnidreams-demo-replay-compare + +Use the generated report's MP4 links for side-by-side manual review. The legacy +runner writes the stacked HDMap/RGB canvas while the shared demo writes generated +RGB output, so this comparison intentionally disables automatic baseline quality +scoring until those output layouts are aligned. Both scenarios use ``226`` +blocks, matching the shipped Omnidreams one-minute baseline. + Quality Hooks ------------- diff --git a/flashdreams/flashdreams/runtime/README.md b/flashdreams/flashdreams/runtime/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/flashdreams/flashdreams/runtime/application.py b/flashdreams/flashdreams/runtime/application.py new file mode 100644 index 000000000..7d73eac61 --- /dev/null +++ b/flashdreams/flashdreams/runtime/application.py @@ -0,0 +1,205 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Application configuration and runtime orchestration.""" + +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from typing import Generic, TypeVar + +from flashdreams.infra.config import InstantiateConfig +from flashdreams.runtime.global_condition import ( + GlobalConditionHandler, + RawGlobalCondition, +) +from flashdreams.runtime.inference_runtime import ( + InferenceRuntime, + InferenceRuntimeConfig, +) +from flashdreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceInput, +) +from flashdreams.runtime.input_system import UserInputHandler +from flashdreams.runtime.output_system import InferenceOutputHandler + +RuntimeT = TypeVar("RuntimeT", bound=InferenceRuntime) +"""Inference-runtime type owned by the application.""" + + +@dataclass(kw_only=True) +class ApplicationConfig(InstantiateConfig, Generic[RuntimeT]): + """Configuration for constructing an inference application.""" + + _target: type["Application"] = field(default_factory=lambda: Application) + + inference_runtime: InferenceRuntimeConfig[RuntimeT] + """Configuration used to construct the application runtime.""" + + +class Application(ABC, Generic[RuntimeT]): + """Own the components required by an inference application. + + Subclasses construct the application-specific input, global-condition, and + output handlers through initialization hooks called by this base constructor. + """ + + _inference_runtime: RuntimeT + """Runtime that owns the shared inference pipeline.""" + + _user_input_handler: UserInputHandler + """Handler that produces the next per-step user condition.""" + + _inference_global_condition: InferenceGlobalCondition + """Rollout-wide condition supplied when initializing inference.""" + + _global_condition_handler: GlobalConditionHandler + """Handler that converts application-facing rollout conditions.""" + + _inference_output_handler: InferenceOutputHandler + """Handler that consumes output produced by inference steps.""" + + def __init__( + self, + config: ApplicationConfig[RuntimeT], + inference_global_condition: InferenceGlobalCondition, + ) -> None: + """Initialize the application from its configuration. + + Args: + config: Runtime construction configuration. + inference_global_condition: Initial model-ready rollout condition. + + Raises: + TypeError: A subclass does not initialize a valid input, + global-condition, or output handler. + """ + self._inference_runtime = config.inference_runtime.setup() + self._inference_global_condition = inference_global_condition + + user_input_handler = self._initialize_user_input_handler(config) + global_condition_handler = self._initialize_global_condition_handler(config) + inference_output_handler = self._initialize_inference_output_handler(config) + + if not isinstance(user_input_handler, UserInputHandler): + raise TypeError( + f"{type(self).__name__} did not initialize a user input handler" + ) + if not isinstance(global_condition_handler, GlobalConditionHandler): + raise TypeError( + f"{type(self).__name__} did not initialize a global condition handler" + ) + if not isinstance(inference_output_handler, InferenceOutputHandler): + raise TypeError( + f"{type(self).__name__} did not initialize an inference output handler" + ) + + self._user_input_handler = user_input_handler + self._global_condition_handler = global_condition_handler + self._inference_output_handler = inference_output_handler + + @abstractmethod + def _initialize_user_input_handler( + self, config: ApplicationConfig[RuntimeT] + ) -> UserInputHandler | None: + """Construct the application's user-input handler. + + Args: + config: Application configuration, including any subclass fields. + + Returns: + Initialized handler, or ``None`` when initialization failed. + """ + + @abstractmethod + def _initialize_global_condition_handler( + self, config: ApplicationConfig[RuntimeT] + ) -> GlobalConditionHandler | None: + """Construct the application's global-condition handler. + + Args: + config: Application configuration, including any subclass fields. + + Returns: + Initialized handler, or ``None`` when initialization failed. + """ + + @abstractmethod + def _initialize_inference_output_handler( + self, config: ApplicationConfig[RuntimeT] + ) -> InferenceOutputHandler | None: + """Construct the application's inference-output handler. + + Args: + config: Application configuration, including any subclass fields. + + Returns: + Initialized handler, or ``None`` when initialization failed. + """ + + def handle_global_condition( + self, raw_global_condition: RawGlobalCondition + ) -> InferenceGlobalCondition: + """Convert and store a raw rollout-wide condition. + + Args: + raw_global_condition: Application-facing rollout condition. + + Returns: + Model-ready condition stored for the next application run. + + Raises: + TypeError: The handler returns a value that is not an inference global + condition. + """ + inference_global_condition = self._global_condition_handler( + raw_global_condition + ) + if not isinstance(inference_global_condition, InferenceGlobalCondition): + raise TypeError( + f"{type(self._global_condition_handler).__name__} did not return an " + "inference global condition" + ) + self._inference_global_condition = inference_global_condition + return inference_global_condition + + def run(self) -> None: + """Run inference until the user-input handler is exhausted. + + A new inference session is created for the run. The global condition is + included only in the first inference input because it initializes the + rollout-wide state for that session. + """ + inference_session = self._inference_runtime.create_session() + global_condition: InferenceGlobalCondition | None = ( + self._inference_global_condition + ) + + while True: + try: + user_condition = self._user_input_handler() + except StopIteration: + return + + inference_input = InferenceInput( + user_condition=user_condition, + global_condition=global_condition, + ) + inference_output = inference_session.step(inference_input) + self._inference_output_handler(inference_output) + global_condition = None + + +__all__ = ["Application", "ApplicationConfig"] diff --git a/flashdreams/flashdreams/runtime/builtin/application/video_output_application.py b/flashdreams/flashdreams/runtime/builtin/application/video_output_application.py new file mode 100644 index 000000000..2dfdeec4e --- /dev/null +++ b/flashdreams/flashdreams/runtime/builtin/application/video_output_application.py @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Application base with video-artifact output handling.""" + +from dataclasses import dataclass, field +from pathlib import Path +from typing import Generic, TypeVar + +from flashdreams.runtime.application import Application, ApplicationConfig +from flashdreams.runtime.builtin.inference_output.handler.video_output_handler import ( + VideoOutputHandler, +) +from flashdreams.runtime.inference_runtime import InferenceRuntime + +RuntimeT = TypeVar("RuntimeT", bound=InferenceRuntime) +"""Inference-runtime type owned by the video-output application.""" + + +@dataclass(kw_only=True) +class VideoOutputApplicationConfig(ApplicationConfig[RuntimeT], Generic[RuntimeT]): + """Configuration for an application that writes video output.""" + + _target: type["VideoOutputApplication"] = field( + default_factory=lambda: VideoOutputApplication + ) + + artifact_path: str | Path + """Destination written by the video output handler.""" + + +class VideoOutputApplication(Application[RuntimeT], Generic[RuntimeT]): + """Application base that collects inference frames into a video artifact.""" + + _inference_output_handler: VideoOutputHandler + """Video handler constructed by the output initialization hook.""" + + def _initialize_inference_output_handler( + self, config: ApplicationConfig[RuntimeT] + ) -> VideoOutputHandler: + """Construct the video output handler from application configuration. + + Args: + config: Application configuration accepted for the base hook contract. + + Returns: + Handler configured with the artifact destination. + + Raises: + TypeError: The application was not given video-output configuration. + """ + if not isinstance(config, VideoOutputApplicationConfig): + raise TypeError( + "VideoOutputApplication requires VideoOutputApplicationConfig; " + f"got {type(config).__name__}" + ) + return VideoOutputHandler(config.artifact_path) + + def run(self) -> None: + """Run inference and finish the video artifact after input exhaustion.""" + super().run() + self._inference_output_handler.finish() + + +__all__ = ["VideoOutputApplication", "VideoOutputApplicationConfig"] diff --git a/flashdreams/flashdreams/runtime/builtin/inference_output/frame_chunk.py b/flashdreams/flashdreams/runtime/builtin/inference_output/frame_chunk.py new file mode 100644 index 000000000..0fddb55e3 --- /dev/null +++ b/flashdreams/flashdreams/runtime/builtin/inference_output/frame_chunk.py @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tensor frame-chunk output contract for the builtin runtime.""" + +from typing import Annotated + +from flashdreams.runtime.inference_session import InferenceOutput +from pydantic import Field +from torch import Tensor + + +class FrameChunkOutput(InferenceOutput): + """Output containing a generated frame chunk.""" + + value: Tensor + """Generated frame chunk with integration-specific tensor layout.""" + + start_timestamp: Annotated[float, Field(ge=0, allow_inf_nan=False)] + """Timestamp of the first frame in seconds on the presentation timeline.""" + + fps: Annotated[float, Field(gt=0, allow_inf_nan=False)] + """Frame rate used to present the chunk.""" + + @property + def frame_present_time(self) -> float: + """Return the presentation duration of one frame in seconds.""" + return 1.0 / self.fps diff --git a/flashdreams/flashdreams/runtime/builtin/inference_output/handler/video_output_handler.py b/flashdreams/flashdreams/runtime/builtin/inference_output/handler/video_output_handler.py new file mode 100644 index 000000000..db703215c --- /dev/null +++ b/flashdreams/flashdreams/runtime/builtin/inference_output/handler/video_output_handler.py @@ -0,0 +1,175 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Video artifact handler for generated frame chunks.""" + +from __future__ import annotations + +import math +from pathlib import Path + +import torch +from flashdreams.infra.runner_io import ( + DEFAULT_RUNNER_INSTALL_HINT, + write_video_tensor, +) +from flashdreams.runtime.builtin.inference_output.frame_chunk import ( + FrameChunkOutput, +) +from flashdreams.runtime.output_system import InferenceOutputHandler +from pydantic import validate_call +from torch import Tensor + +_TIMESTAMP_ABS_TOLERANCE_SECONDS = 1e-6 +"""Tolerance for accumulated floating-point presentation timestamps.""" + + +class VideoOutputHandler(InferenceOutputHandler): + """Collect frame chunks and write a horizontally tiled video artifact.""" + + artifact_path: Path + """Path written when :meth:`finish` is called.""" + + _chunks: list[Tensor] + """CPU frame chunks awaiting artifact creation.""" + + _chunk_shape: tuple[int, int, int, int, int] | None + """Stable non-temporal ``[B, V, C, H, W]`` shape, if established.""" + + _fps: float | None + """Presentation frame rate established by the first chunk.""" + + _next_timestamp: float | None + """Expected presentation timestamp for the next chunk.""" + + _finished: bool + """Whether the artifact has been written successfully.""" + + def __init__(self, artifact_path: str | Path) -> None: + """Initialize an empty video artifact handler. + + Args: + artifact_path: Destination passed to the shared FFmpeg video writer. + """ + self.artifact_path = Path(artifact_path) + self._chunks = [] + self._chunk_shape = None + self._fps = None + self._next_timestamp = None + self._finished = False + + @validate_call + def __call__(self, inference_output: FrameChunkOutput) -> None: + """Collect one frame chunk for the output artifact. + + Args: + inference_output: RGB frames in ``[B, V, T, C, H, W]`` layout. + + Raises: + RuntimeError: :meth:`finish` has already written the artifact. + ValueError: The chunk shape, frame rate, or timestamp is inconsistent + with the output stream. + """ + if self._finished: + raise RuntimeError("cannot receive frame chunks after finish()") + + chunk = inference_output.value + if chunk.ndim != 6: + raise ValueError( + "expected a rank-6 frame chunk in [B, V, T, C, H, W] layout; " + f"got rank {chunk.ndim} with shape {tuple(chunk.shape)}" + ) + batch, views, frames, channels, height, width = map(int, chunk.shape) + if batch != 1 or channels != 3: + raise ValueError( + "expected frame chunk shape [B=1, V, T, C=3, H, W]; " + f"got {tuple(chunk.shape)}" + ) + if any(size <= 0 for size in (views, frames, height, width)): + raise ValueError( + "expected every frame chunk axis to be positive; " + f"got {tuple(chunk.shape)}" + ) + + chunk_shape = (batch, views, channels, height, width) + if self._chunk_shape is not None and chunk_shape != self._chunk_shape: + raise ValueError( + "expected frame chunks to share [B, V, C, H, W] dimensions; " + f"expected {self._chunk_shape}, got {chunk_shape}" + ) + + fps = inference_output.fps + if self._fps is not None and not math.isclose( + fps, + self._fps, + rel_tol=1e-9, + abs_tol=0.0, + ): + raise ValueError(f"expected frame chunk fps {self._fps}; got {fps}") + if self._next_timestamp is not None and not math.isclose( + inference_output.start_timestamp, + self._next_timestamp, + rel_tol=0.0, + abs_tol=_TIMESTAMP_ABS_TOLERANCE_SECONDS, + ): + raise ValueError( + "expected contiguous frame chunk timestamp " + f"{self._next_timestamp}; got {inference_output.start_timestamp}" + ) + + self._chunks.append(chunk.detach().cpu()) + self._chunk_shape = chunk_shape + self._fps = fps + self._next_timestamp = inference_output.start_timestamp + frames / fps + + def finish(self) -> Path: + """Finish receiving chunks and write the video artifact. + + Returns: + Path written by the shared video writer. Repeated calls return the + same path without writing the artifact again. + + Raises: + ValueError: No frame chunks have been received. + RuntimeError: Internal stream metadata is incomplete. + """ + if self._finished: + return self.artifact_path + if not self._chunks: + raise ValueError("cannot finish a video output without frame chunks") + if self._fps is None: + raise RuntimeError("video output frame rate was not initialized") + + video = torch.cat(self._chunks, dim=2) + _, views, frames, channels, height, width = map(int, video.shape) + canvas = ( + video[0] + .permute(1, 3, 0, 4, 2) + .reshape(frames, height, views * width, channels) + ) + artifact_path = write_video_tensor( + canvas, + self.artifact_path, + fps=self._fps, + layout="thwc", + install_hint=DEFAULT_RUNNER_INSTALL_HINT, + ) + self.artifact_path = artifact_path + self._chunks.clear() + self._finished = True + return artifact_path + + +__all__ = ["VideoOutputHandler"] diff --git a/flashdreams/flashdreams/runtime/builtin/user_input/keyboard.py b/flashdreams/flashdreams/runtime/builtin/user_input/keyboard.py new file mode 100644 index 000000000..fe91f4cc6 --- /dev/null +++ b/flashdreams/flashdreams/runtime/builtin/user_input/keyboard.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Raw keyboard-event input contract for the builtin runtime.""" + +from enum import Enum + +from flashdreams.runtime.input_system import RawUserInput + + +class KeyboardEvent(str, Enum): + """Keyboard edge types reported by raw input sources.""" + + KEY_DOWN = "keydown" + KEY_UP = "keyup" + + +class KeyboardKey(str, Enum): + """Keyboard key identifiers supported by builtin input handlers.""" + + W = "w" + A = "a" + S = "s" + D = "d" + Q = "q" + E = "e" + I = "i" + J = "j" + K = "k" + L = "l" + UP = "up" + DOWN = "down" + LEFT = "left" + RIGHT = "right" + SPACE = "space" + + +class RawUserKeyboardEvent(RawUserInput): + """Timestamped raw keyboard edge received from an input source.""" + + event: KeyboardEvent + """Keyboard edge reported by the input source.""" + + key: KeyboardKey + """Supported keyboard key associated with the edge.""" diff --git a/flashdreams/flashdreams/runtime/builtin/user_input/mouse.py b/flashdreams/flashdreams/runtime/builtin/user_input/mouse.py new file mode 100644 index 000000000..1236742e3 --- /dev/null +++ b/flashdreams/flashdreams/runtime/builtin/user_input/mouse.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Raw mouse-button event contract for the builtin runtime.""" + +from enum import Enum + +from flashdreams.runtime.input_system import RawUserInput + + +class MouseEvent(str, Enum): + """Mouse-button edge types reported by raw input sources.""" + + BUTTON_DOWN = "mousedown" + BUTTON_UP = "mouseup" + + +class MouseButton(str, Enum): + """Mouse buttons supported by builtin input handlers.""" + + LEFT = "left" + MIDDLE = "middle" + RIGHT = "right" + + +class RawUserMouseEvent(RawUserInput): + """Timestamped raw mouse-button edge received from an input source.""" + + event: MouseEvent + """Mouse-button edge reported by the input source.""" + + button: MouseButton + """Mouse button associated with the edge.""" diff --git a/flashdreams/flashdreams/runtime/global_condition.py b/flashdreams/flashdreams/runtime/global_condition.py new file mode 100644 index 000000000..6a41ba082 --- /dev/null +++ b/flashdreams/flashdreams/runtime/global_condition.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Raw global-condition contract and conversion handler interface.""" + +from abc import ABC, abstractmethod + +from flashdreams.runtime.inference_session import InferenceGlobalCondition +from pydantic import ConfigDict, validate_call, with_config +from typing_extensions import TypedDict + + +@with_config(ConfigDict(arbitrary_types_allowed=True, extra="forbid")) +class RawGlobalCondition(TypedDict): + """Base typed dictionary for application-facing rollout conditions.""" + + +class GlobalConditionHandler(ABC): + """Interface for converting raw rollout data into inference conditions.""" + + @abstractmethod + @validate_call + def __call__( + self, raw_global_condition: RawGlobalCondition + ) -> InferenceGlobalCondition: + """Convert a raw global condition into a model-ready condition. + + Args: + raw_global_condition: Application-facing rollout condition. + + Returns: + Model-ready rollout condition for an inference session. + """ + + +__all__ = ["GlobalConditionHandler", "RawGlobalCondition"] diff --git a/flashdreams/flashdreams/runtime/inference_runtime.py b/flashdreams/flashdreams/runtime/inference_runtime.py new file mode 100644 index 000000000..843819756 --- /dev/null +++ b/flashdreams/flashdreams/runtime/inference_runtime.py @@ -0,0 +1,138 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Distributed inference runtime with shared pipeline ownership.""" + +import os +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import Any, Generic, TypeVar, cast + +import torch +from flashdreams.core.distributed import init as init_distributed +from flashdreams.infra.config import InstantiateConfig +from flashdreams.infra.pipeline import ( + StreamInferencePipeline, + StreamInferencePipelineConfig, +) +from flashdreams.runtime.inference_session import InferenceSession + + +def _is_torchrun_env() -> bool: + """Return whether ``torchrun`` set the distributed rendezvous variables.""" + return "RANK" in os.environ and "WORLD_SIZE" in os.environ + + +SessionT = TypeVar("SessionT", bound=InferenceSession) +"""Session type parameter for :class:`InferenceRuntime`.""" + +RuntimeT = TypeVar("RuntimeT", bound="InferenceRuntime") +"""Runtime type constructed by :class:`InferenceRuntimeConfig`.""" + + +@dataclass(kw_only=True) +class InferenceRuntimeConfig(InstantiateConfig, Generic[RuntimeT]): + """Configuration for constructing an inference runtime.""" + + _target: type[RuntimeT] + + pipeline: StreamInferencePipelineConfig + """Pipeline configuration instantiated and shared by runtime sessions.""" + + session_type: type[InferenceSession] + """Concrete session type created by the runtime.""" + + def setup(self, **kwargs: Any) -> RuntimeT: + """Construct the configured inference runtime. + + Args: + **kwargs: Additional constructor arguments for the runtime. + + Returns: + Configured inference runtime. + """ + return self._target(self, **kwargs) + + +class InferenceRuntime(ABC, Generic[SessionT]): + """Shared pipeline runtime for distributed inference sessions. + + Construction initializes PyTorch distributed when launched by ``torchrun``, + records rank metadata, and constructs one pipeline shared by every session. + The concrete session type associates the runtime with its pipeline type, so + callers only parameterize the runtime with ``SessionT``. + Subclasses implement :meth:`warmup` for integration-specific model execution. + """ + + ## Distributed state + + _local_rank: int + """Process-local rank; ``0`` outside distributed runs.""" + + _global_rank: int + """Global process rank; ``0`` outside distributed runs.""" + + _world_size: int + """Number of distributed processes; ``1`` outside distributed runs.""" + + _is_rank_zero: bool + """Whether this process is the global rank-zero process.""" + + _pipeline: StreamInferencePipeline + """Pipeline constructed once and shared by all sessions.""" + + _session_type: type[SessionT] + """Concrete session type created by :meth:`create_session`.""" + + def __init__( + self, + config: InferenceRuntimeConfig, + ) -> None: + """Initialize distributed state and construct the shared pipeline. + + Args: + config: Runtime construction configuration. + """ + # Initialize before pipeline construction so context-parallel components + # observe torchrun's world size while allocating their runtime state. + if _is_torchrun_env() and not torch.distributed.is_initialized(): + init_distributed() + + # Snapshot launch metadata for rank-gated runtime work while preserving + # stable single-process defaults for ordinary Python processes. + if torch.distributed.is_initialized(): + self._local_rank = int(os.environ.get("LOCAL_RANK", "0")) + self._global_rank = torch.distributed.get_rank() + self._world_size = torch.distributed.get_world_size() + else: + self._local_rank = 0 + self._global_rank = 0 + self._world_size = 1 + self._is_rank_zero = self._global_rank == 0 + + self._pipeline = config.pipeline.setup() + self._session_type = cast(type[SessionT], config.session_type) + + def create_session(self) -> SessionT: + """Create a session backed by the shared pipeline. + + Returns: + Fresh session with its own pipeline cache. + """ + return self._session_type(self._pipeline) + + @abstractmethod + def warmup(self) -> None: + """Warm up the pipeline for inference.""" diff --git a/flashdreams/flashdreams/runtime/inference_session.py b/flashdreams/flashdreams/runtime/inference_session.py new file mode 100644 index 000000000..57fad5a79 --- /dev/null +++ b/flashdreams/flashdreams/runtime/inference_session.py @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Inference session contracts with pipeline and cache ownership.""" + +from abc import ABC, abstractmethod +from typing import Generic, TypeVar + +from flashdreams.infra.pipeline import ( + StreamInferencePipeline, + StreamInferencePipelineCache, +) +from pydantic import BaseModel, ConfigDict, validate_call + + +class InferenceUserCondition(BaseModel): + """Base model for per-step user conditions.""" + + model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid") + + +class InferenceGlobalCondition(BaseModel): + """Base model for rollout-wide conditions.""" + + model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid") + + +UserConditionT = TypeVar("UserConditionT", bound=InferenceUserCondition) +"""User-condition type parameter for :class:`InferenceInput`.""" + +GlobalConditionT = TypeVar("GlobalConditionT", bound=InferenceGlobalCondition) +"""Global-condition type parameter for :class:`InferenceInput`.""" + + +class InferenceInput(BaseModel, Generic[UserConditionT, GlobalConditionT]): + """Validated conditions consumed by one inference step.""" + + model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid") + + user_condition: UserConditionT + """Required per-step user condition.""" + + global_condition: GlobalConditionT | None = None + """Optional rollout-wide condition.""" + + +class InferenceOutput(BaseModel): + """Base model for outputs produced by one inference step.""" + + model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid") + + +# TODO: Replace StreamInferencePipeline with the flashdreams.pipeline module. +PipelineT = TypeVar("PipelineT", bound=StreamInferencePipeline) +"""Pipeline type parameter for :class:`InferenceSession`.""" + + +class InferenceSession(ABC, Generic[PipelineT]): + """Stateful interface around an inference pipeline and session cache. + + Subclasses implement :meth:`step` for integration-specific rollout I/O. + """ + + _pipeline: PipelineT + """Pipeline owned and driven by the inference session.""" + + _cache: StreamInferencePipelineCache + """Current per-session cache initialized by the pipeline.""" + + def __init__(self, pipeline: PipelineT) -> None: + """Initialize the session and reset its pipeline cache. + + Args: + pipeline: Pipeline to drive. + """ + self._pipeline = pipeline + self.reset() + + def reset(self) -> None: + """Reset the session with a fresh pipeline cache.""" + self._cache = self._pipeline.initialize_cache() + + @abstractmethod + @validate_call + def step(self, inference_input: InferenceInput) -> InferenceOutput: + """Run one inference step. + + Args: + inference_input: Input for the next inference step. + + Returns: + Output produced by the inference step. + + Raises: + ValidationError: ``inference_input`` fails Pydantic validation. + """ diff --git a/flashdreams/flashdreams/runtime/input_system.py b/flashdreams/flashdreams/runtime/input_system.py new file mode 100644 index 000000000..2e8152eef --- /dev/null +++ b/flashdreams/flashdreams/runtime/input_system.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""User-input contracts and handler interface for inference conditioning.""" + +from abc import ABC, abstractmethod +from typing import Annotated + +from flashdreams.runtime.inference_session import InferenceUserCondition +from pydantic import ConfigDict, Field, validate_call, with_config +from typing_extensions import TypedDict + + +@with_config(ConfigDict(arbitrary_types_allowed=True, extra="forbid")) +class RawUserInput(TypedDict): + """Base typed dictionary for device-specific user input.""" + + timestamp: Annotated[float, Field(ge=0, allow_inf_nan=False)] + """Event timestamp in seconds on the input source's monotonic clock.""" + + +@with_config(ConfigDict(arbitrary_types_allowed=True, extra="forbid")) +class CanonicalizedUserInput(TypedDict): + """Base typed dictionary for device-independent user intent.""" + + +class UserInputHandler(ABC): + """Interface for producing inference conditioning from user input.""" + + @abstractmethod + @validate_call + def __call__(self) -> InferenceUserCondition: + """Return a model-ready per-step condition. + + Returns: + Model-ready condition for one inference step. + """ diff --git a/flashdreams/flashdreams/runtime/output_system.py b/flashdreams/flashdreams/runtime/output_system.py new file mode 100644 index 000000000..b0fec716c --- /dev/null +++ b/flashdreams/flashdreams/runtime/output_system.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Inference-output handler interface for application-specific results.""" + +from abc import ABC, abstractmethod +from typing import Any + +from flashdreams.runtime.inference_session import InferenceOutput +from pydantic import validate_call + + +class InferenceOutputHandler(ABC): + """Interface for consuming output from an inference step.""" + + @abstractmethod + @validate_call + def __call__(self, inference_output: InferenceOutput) -> Any: + """Convert inference output into an application-specific result. + + Args: + inference_output: Output produced by one inference step. + + Returns: + Handler-specific result. + """ diff --git a/flashdreams/pyproject.toml b/flashdreams/pyproject.toml index 06278038c..cd5ef01dc 100644 --- a/flashdreams/pyproject.toml +++ b/flashdreams/pyproject.toml @@ -36,6 +36,7 @@ dependencies = [ # non-subclassable TypeAliasType in NumPy 2.5 (notably on Python 3.13). "numpy>=1.24,<2.5", "nvidia-ml-py>=12.0", + "pydantic>=2,<3", "safetensors>=0.4", "tqdm>=4.60", "transformers>=5.0,<6", diff --git a/flashdreams/tests/runtime/mocks.py b/flashdreams/tests/runtime/mocks.py new file mode 100644 index 000000000..2931ecac7 --- /dev/null +++ b/flashdreams/tests/runtime/mocks.py @@ -0,0 +1,166 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Shared inference pipeline and session test doubles.""" + +from __future__ import annotations + +from typing import TypeAlias + +from flashdreams.infra.pipeline import ( + StreamInferencePipeline, + StreamInferencePipelineCache, + StreamInferencePipelineConfig, +) +from flashdreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceInput, + InferenceOutput, + InferenceSession, + InferenceUserCondition, +) +from pydantic import validate_call +from torch import Tensor, nn + + +class MockStreamInferencePipelineCache(StreamInferencePipelineCache): + """In-memory pipeline cache without model-specific state.""" + + def __init__(self) -> None: + """Initialize an empty cache.""" + + +class MockStreamInferencePipeline(StreamInferencePipeline): + """Pipeline test double that records cache initialization.""" + + initialize_cache_calls: int + """Number of caches initialized for inference sessions.""" + + def __init__(self) -> None: + """Initialize the pipeline without model components.""" + nn.Module.__init__(self) + self.initialize_cache_calls = 0 + + def initialize_cache( + self, + transformer_context: object | None = None, + encoder_context: object | None = None, + decoder_context: object | None = None, + ) -> MockStreamInferencePipelineCache: + """Create and record a fresh inference-session cache.""" + del transformer_context, encoder_context, decoder_context + self.initialize_cache_calls += 1 + return MockStreamInferencePipelineCache() + + +class MockStreamInferencePipelineConfig(StreamInferencePipelineConfig): + """Pipeline config test double that returns a configured pipeline.""" + + pipeline: MockStreamInferencePipeline + """Pipeline returned by :meth:`setup`.""" + + setup_calls: int + """Number of times :meth:`setup` has been called.""" + + def __init__(self, pipeline: MockStreamInferencePipeline) -> None: + """Initialize with the pipeline returned by :meth:`setup`.""" + self.pipeline = pipeline + self.setup_calls = 0 + + def setup(self) -> MockStreamInferencePipeline: + """Return the configured pipeline and record the setup call.""" + self.setup_calls += 1 + return self.pipeline + + +class MockInferenceSession(InferenceSession[MockStreamInferencePipeline]): + """Inference session test double that records inputs and outputs.""" + + def __init__( + self, + pipeline: MockStreamInferencePipeline | None = None, + ) -> None: + """Initialize with a supplied or fresh mock pipeline.""" + self.inputs: list[InferenceInput] = [] + self.outputs: list[InferenceOutput] = [] + super().__init__( + pipeline if pipeline is not None else MockStreamInferencePipeline() + ) + + def step(self, inference_input: InferenceInput) -> InferenceOutput: + """Record an input and return a unique empty output.""" + inference_output = InferenceOutput() + self.inputs.append(inference_input) + self.outputs.append(inference_output) + return inference_output + + +class MockUserCondition(InferenceUserCondition): + """User-provided controls for validated inference steps.""" + + movement: Tensor + """Embedded latent tensor describing character movement.""" + + camera: Tensor + """Embedded latent tensor describing camera rotation.""" + + +class MockGlobalCondition(InferenceGlobalCondition): + """Session-wide controls for validated inference steps.""" + + frame: Tensor + """Embedded latent tensor describing the global conditioning frame.""" + + prompt: Tensor + """Embedded latent tensor describing prompt conditioning.""" + + +MockInferenceInput: TypeAlias = InferenceInput[MockUserCondition, MockGlobalCondition] +"""Inference input with fully specialized nested condition models.""" + + +class MockInferenceOutput(InferenceOutput): + """Output returned by the validated inference session.""" + + frame_chunk: Tensor + """Fully decoded frame chunk from the model latent.""" + + +class ValidatedInferenceSession(InferenceSession[MockStreamInferencePipeline]): + """Inference session with Pydantic-validated condition models.""" + + @validate_call + def step(self, inference_input: MockInferenceInput) -> MockInferenceOutput: + """Return a frame chunk from the validated inference input.""" + global_condition = inference_input.global_condition + frame_chunk = ( + global_condition.frame + if global_condition is not None + else inference_input.user_condition.camera + ) + return MockInferenceOutput(frame_chunk=frame_chunk) + + +__all__ = [ + "MockGlobalCondition", + "MockInferenceInput", + "MockInferenceOutput", + "MockInferenceSession", + "MockStreamInferencePipeline", + "MockStreamInferencePipelineCache", + "MockStreamInferencePipelineConfig", + "MockUserCondition", + "ValidatedInferenceSession", +] diff --git a/flashdreams/tests/runtime/test_application.py b/flashdreams/tests/runtime/test_application.py new file mode 100644 index 000000000..4b65762a0 --- /dev/null +++ b/flashdreams/tests/runtime/test_application.py @@ -0,0 +1,375 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU tests for inference application component ownership.""" + +from dataclasses import dataclass, field + +import pytest +from flashdreams.runtime.application import Application, ApplicationConfig +from flashdreams.runtime.global_condition import ( + GlobalConditionHandler, + RawGlobalCondition, +) +from flashdreams.runtime.inference_runtime import ( + InferenceRuntime, + InferenceRuntimeConfig, +) +from flashdreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceOutput, + InferenceUserCondition, +) +from flashdreams.runtime.input_system import UserInputHandler +from flashdreams.runtime.output_system import InferenceOutputHandler + +from .mocks import ( + MockInferenceSession, + MockStreamInferencePipeline, + MockStreamInferencePipelineConfig, +) + +pytestmark = pytest.mark.ci_cpu + + +## Component test doubles + + +class _MockInferenceRuntime(InferenceRuntime[MockInferenceSession]): + """Runtime test double that skips pipeline construction.""" + + def __init__(self, config: InferenceRuntimeConfig) -> None: + """Retain the runtime config without constructing a pipeline.""" + self.config = config + + def warmup(self) -> None: + """Complete warmup without model execution.""" + + +class _MockUserInputHandler(UserInputHandler): + """User-input handler test double.""" + + def __call__(self) -> InferenceUserCondition: + """Return an empty user condition.""" + return InferenceUserCondition() + + +class _MockInferenceOutputHandler(InferenceOutputHandler): + """Inference-output handler test double.""" + + def __call__(self, inference_output: InferenceOutput) -> None: + """Consume an inference output without producing a result.""" + del inference_output + + +class _MockGlobalConditionHandler(GlobalConditionHandler): + """Global-condition handler test double.""" + + def __init__(self) -> None: + """Initialize the conversion record.""" + self.conditions: list[RawGlobalCondition] = [] + + def __call__( + self, raw_global_condition: RawGlobalCondition + ) -> InferenceGlobalCondition: + """Record a raw condition and return a model-ready condition.""" + self.conditions.append(raw_global_condition) + return InferenceGlobalCondition() + + +@dataclass(kw_only=True) +class _MockApplicationConfig(ApplicationConfig[_MockInferenceRuntime]): + """Configuration for the component-ownership application test double.""" + + _target: type["_MockApplication"] = field(default_factory=lambda: _MockApplication) + + +class _MockApplication(Application[_MockInferenceRuntime]): + """Application test double that constructs no-op handlers.""" + + def _initialize_user_input_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> UserInputHandler: + """Construct a no-op user-input handler.""" + assert isinstance(config, _MockApplicationConfig) + return _MockUserInputHandler() + + def _initialize_global_condition_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> GlobalConditionHandler: + """Construct a recording global-condition handler.""" + assert isinstance(config, _MockApplicationConfig) + return _MockGlobalConditionHandler() + + def _initialize_inference_output_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> InferenceOutputHandler: + """Construct a no-op inference-output handler.""" + assert isinstance(config, _MockApplicationConfig) + return _MockInferenceOutputHandler() + + +## Application ownership + + +def test_application_privately_owns_inference_components() -> None: + """Verify construction creates a runtime and retains every component.""" + global_condition = InferenceGlobalCondition() + + runtime_config = InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ) + config = _MockApplicationConfig( + inference_runtime=runtime_config, + ) + application = _MockApplication(config, global_condition) + + assert isinstance(application._inference_runtime, _MockInferenceRuntime) + assert application._inference_runtime.config is runtime_config + assert isinstance(application._user_input_handler, _MockUserInputHandler) + assert application._inference_global_condition is global_condition + assert isinstance( + application._global_condition_handler, _MockGlobalConditionHandler + ) + assert isinstance( + application._inference_output_handler, _MockInferenceOutputHandler + ) + + +class _MissingUserInputApplication(_MockApplication): + """Application test double that fails to construct its input handler.""" + + def _initialize_user_input_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> UserInputHandler | None: + """Return no user-input handler.""" + del config + return None + + +class _MissingInferenceOutputApplication(_MockApplication): + """Application test double that fails to construct its output handler.""" + + def _initialize_inference_output_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> InferenceOutputHandler | None: + """Return no inference-output handler.""" + del config + return None + + +class _MissingGlobalConditionHandlerApplication(_MockApplication): + """Application test double that fails to construct its global handler.""" + + def _initialize_global_condition_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> GlobalConditionHandler | None: + """Return no global-condition handler.""" + del config + return None + + +def test_application_rejects_missing_user_input_handler() -> None: + """Verify construction fails when the child omits its input handler.""" + config = _MockApplicationConfig( + inference_runtime=InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ), + ) + + with pytest.raises(TypeError, match="did not initialize a user input handler"): + _MissingUserInputApplication(config, InferenceGlobalCondition()) + + +def test_application_rejects_missing_inference_output_handler() -> None: + """Verify construction fails when the child omits its output handler.""" + config = _MockApplicationConfig( + inference_runtime=InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ), + ) + + with pytest.raises( + TypeError, match="did not initialize an inference output handler" + ): + _MissingInferenceOutputApplication(config, InferenceGlobalCondition()) + + +def test_application_rejects_missing_global_condition_handler() -> None: + """Verify construction fails when the child omits its global handler.""" + config = _MockApplicationConfig( + inference_runtime=InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ), + ) + + with pytest.raises( + TypeError, match="did not initialize a global condition handler" + ): + _MissingGlobalConditionHandlerApplication( + config, + InferenceGlobalCondition(), + ) + + +def test_application_handles_raw_global_condition() -> None: + """Verify public conversion replaces the condition used by future runs.""" + config = _MockApplicationConfig( + inference_runtime=InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ), + ) + application = _MockApplication(config, InferenceGlobalCondition()) + raw_global_condition: RawGlobalCondition = {} + + inference_global_condition = application.handle_global_condition( + raw_global_condition + ) + + handler = application._global_condition_handler + assert isinstance(handler, _MockGlobalConditionHandler) + assert handler.conditions == [raw_global_condition] + assert application._inference_global_condition is inference_global_condition + + +## Application execution + + +class _RunInferenceRuntime(InferenceRuntime[MockInferenceSession]): + """Runtime test double that constructs and returns one session.""" + + def __init__(self, config: InferenceRuntimeConfig) -> None: + """Initialize the session returned by :meth:`create_session`.""" + del config + self.session = MockInferenceSession() + self.create_session_calls = 0 + + def create_session(self) -> MockInferenceSession: + """Return the configured session and record the creation request.""" + self.create_session_calls += 1 + return self.session + + def warmup(self) -> None: + """Complete warmup without model execution.""" + + +class _RunUserInputHandler(UserInputHandler): + """Finite user-input handler test double.""" + + def __init__(self, conditions: list[InferenceUserCondition]) -> None: + """Initialize with the conditions to return before exhaustion.""" + self.conditions = iter(conditions) + self.calls = 0 + + def __call__(self) -> InferenceUserCondition: + """Return the next user condition or signal exhaustion.""" + self.calls += 1 + return next(self.conditions) + + +class _RunInferenceOutputHandler(InferenceOutputHandler): + """Inference-output handler that records consumed outputs.""" + + def __init__(self) -> None: + """Initialize the consumed output record.""" + self.outputs: list[InferenceOutput] = [] + + def __call__(self, inference_output: InferenceOutput) -> None: + """Record an inference output in call order.""" + self.outputs.append(inference_output) + + +@dataclass(kw_only=True) +class _RunApplicationConfig(ApplicationConfig[_RunInferenceRuntime]): + """Configuration for the finite-loop application test double.""" + + _target: type["_RunApplication"] = field(default_factory=lambda: _RunApplication) + + user_conditions: list[InferenceUserCondition] + """Conditions returned by the child-created input handler.""" + + +class _RunApplication(Application[_RunInferenceRuntime]): + """Application test double that constructs recording handlers.""" + + def _initialize_user_input_handler( + self, config: ApplicationConfig[_RunInferenceRuntime] + ) -> UserInputHandler: + """Construct the finite user-input handler.""" + assert isinstance(config, _RunApplicationConfig) + return _RunUserInputHandler(config.user_conditions) + + def _initialize_global_condition_handler( + self, config: ApplicationConfig[_RunInferenceRuntime] + ) -> GlobalConditionHandler: + """Construct the recording global-condition handler.""" + assert isinstance(config, _RunApplicationConfig) + return _MockGlobalConditionHandler() + + def _initialize_inference_output_handler( + self, config: ApplicationConfig[_RunInferenceRuntime] + ) -> InferenceOutputHandler: + """Construct the recording inference-output handler.""" + assert isinstance(config, _RunApplicationConfig) + return _RunInferenceOutputHandler() + + +def test_application_run_processes_inputs_until_handler_exhaustion() -> None: + """Verify the application builds inputs and dispatches every output.""" + user_conditions = [InferenceUserCondition(), InferenceUserCondition()] + global_condition = InferenceGlobalCondition() + runtime_config = InferenceRuntimeConfig( + _target=_RunInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ) + config = _RunApplicationConfig( + inference_runtime=runtime_config, + user_conditions=user_conditions, + ) + application = _RunApplication(config, global_condition) + runtime = application._inference_runtime + session = runtime.session + user_input_handler = application._user_input_handler + output_handler = application._inference_output_handler + + assert isinstance(user_input_handler, _RunUserInputHandler) + assert isinstance(output_handler, _RunInferenceOutputHandler) + + application.run() + + # A run owns one stateful session and polls once more to observe exhaustion. + assert runtime.create_session_calls == 1 + assert user_input_handler.calls == 3 + + # The global condition initializes the first step and is omitted thereafter. + assert len(session.inputs) == 2 + assert session.inputs[0].user_condition is user_conditions[0] + assert session.inputs[0].global_condition is global_condition + assert session.inputs[1].user_condition is user_conditions[1] + assert session.inputs[1].global_condition is None + + # Each inference output is dispatched to the output handler in step order. + assert output_handler.outputs == session.outputs diff --git a/flashdreams/tests/runtime/test_frame_chunk_output.py b/flashdreams/tests/runtime/test_frame_chunk_output.py new file mode 100644 index 000000000..98162ccab --- /dev/null +++ b/flashdreams/tests/runtime/test_frame_chunk_output.py @@ -0,0 +1,77 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Pydantic validation tests for builtin frame-chunk outputs.""" + +from typing import Any + +import pytest +import torch +from flashdreams.runtime.builtin.inference_output.frame_chunk import ( + FrameChunkOutput, +) +from pydantic import TypeAdapter, ValidationError + +pytestmark = pytest.mark.ci_cpu + +_FRAME_CHUNK_OUTPUT_ADAPTER = TypeAdapter(FrameChunkOutput) + + +## Valid frame chunks + + +def test_frame_chunk_output_accepts_valid_timing_metadata() -> None: + """Verify Pydantic retains valid frame data and presentation timing.""" + frame_chunk = torch.zeros(1, 1, 4, 3, 8, 8) + + output = _FRAME_CHUNK_OUTPUT_ADAPTER.validate_python( + {"value": frame_chunk, "start_timestamp": 1.25, "fps": 30.0} + ) + + assert output.value is frame_chunk + assert output.start_timestamp == pytest.approx(1.25) + assert output.fps == pytest.approx(30.0) + assert output.frame_present_time == pytest.approx(1.0 / 30.0) + + +## Invalid frame chunks + + +# Each payload isolates a missing field, invalid value, or unsupported extra field. +@pytest.mark.parametrize( + "inference_output", + [ + {}, + {"value": torch.zeros(1), "start_timestamp": 0.0}, + {"value": torch.zeros(1), "fps": 30.0}, + {"value": "not-a-tensor", "start_timestamp": 0.0, "fps": 30.0}, + {"value": torch.zeros(1), "start_timestamp": -1.0, "fps": 30.0}, + {"value": torch.zeros(1), "start_timestamp": float("nan"), "fps": 30.0}, + {"value": torch.zeros(1), "start_timestamp": 0.0, "fps": 0.0}, + {"value": torch.zeros(1), "start_timestamp": 0.0, "fps": float("inf")}, + { + "value": torch.zeros(1), + "start_timestamp": 0.0, + "fps": 30.0, + "extra": True, + }, + ], +) +def test_frame_chunk_output_rejects_invalid_payloads( + inference_output: Any, +) -> None: + """Verify Pydantic rejects invalid frame data and timing metadata.""" + with pytest.raises(ValidationError): + _FRAME_CHUNK_OUTPUT_ADAPTER.validate_python(inference_output) diff --git a/flashdreams/tests/runtime/test_global_condition.py b/flashdreams/tests/runtime/test_global_condition.py new file mode 100644 index 000000000..8b3b5afde --- /dev/null +++ b/flashdreams/tests/runtime/test_global_condition.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU tests for raw global-condition conversion contracts.""" + +from typing import Any, cast + +import pytest +from flashdreams.runtime.global_condition import ( + GlobalConditionHandler, + RawGlobalCondition, +) +from flashdreams.runtime.inference_session import InferenceGlobalCondition +from pydantic import ValidationError, validate_call + +pytestmark = pytest.mark.ci_cpu + + +class _RawPromptCondition(RawGlobalCondition): + """Raw prompt supplied by an application boundary.""" + + prompt: str + """Unprocessed rollout prompt.""" + + +class _PromptCondition(InferenceGlobalCondition): + """Model-ready prompt condition used by the test handler.""" + + prompt: str + """Normalized rollout prompt.""" + + +class _PromptConditionHandler(GlobalConditionHandler): + """Normalize a raw prompt into an inference condition.""" + + @validate_call + def __call__(self, raw_global_condition: _RawPromptCondition) -> _PromptCondition: + """Normalize whitespace around the rollout prompt.""" + return _PromptCondition(prompt=raw_global_condition["prompt"].strip()) + + +def test_global_condition_handler_validates_and_converts_raw_condition() -> None: + """Verify a concrete handler receives validated typed-dictionary data.""" + handler = _PromptConditionHandler() + + condition = handler(_RawPromptCondition(prompt=" drive forward ")) + + assert condition.prompt == "drive forward" + + +def test_global_condition_handler_rejects_invalid_raw_condition() -> None: + """Verify Pydantic rejects invalid raw condition fields and extras.""" + handler = _PromptConditionHandler() + + with pytest.raises(ValidationError): + handler(cast(Any, {"prompt": 42})) + with pytest.raises(ValidationError): + handler(cast(Any, {"prompt": "drive", "unexpected": True})) diff --git a/flashdreams/tests/runtime/test_inference_runtime.py b/flashdreams/tests/runtime/test_inference_runtime.py new file mode 100644 index 000000000..f35a60f9b --- /dev/null +++ b/flashdreams/tests/runtime/test_inference_runtime.py @@ -0,0 +1,117 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU tests for inference runtime pipeline and session ownership.""" + +from __future__ import annotations + +import pytest +import torch +from flashdreams.runtime.inference_runtime import ( + InferenceRuntime, + InferenceRuntimeConfig, +) + +from .mocks import ( + MockInferenceSession, + MockStreamInferencePipeline, + MockStreamInferencePipelineCache, + MockStreamInferencePipelineConfig, +) + +pytestmark = pytest.mark.ci_cpu + + +## Runtime test doubles + + +class _MockInferenceRuntime(InferenceRuntime[MockInferenceSession]): + """Concrete runtime mock with a no-op warmup.""" + + def warmup(self) -> None: + """Complete warmup without running model computation.""" + + +## Fixtures + + +@pytest.fixture +def runtime_bundle( + monkeypatch: pytest.MonkeyPatch, +) -> tuple[ + _MockInferenceRuntime, + MockStreamInferencePipelineConfig, + MockStreamInferencePipeline, +]: + """Build a single-process runtime with mocked pipeline setup.""" + # Keep the fixture on the deterministic non-distributed initialization path. + monkeypatch.delenv("RANK", raising=False) + monkeypatch.delenv("WORLD_SIZE", raising=False) + monkeypatch.setattr(torch.distributed, "is_initialized", lambda: False) + + pipeline = MockStreamInferencePipeline() + pipeline_config = MockStreamInferencePipelineConfig(pipeline) + runtime_config = InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=pipeline_config, + session_type=MockInferenceSession, + ) + runtime = runtime_config.setup() + return runtime, pipeline_config, pipeline + + +## Runtime ownership behavior + + +def test_runtime_sets_up_and_privately_holds_pipeline( + runtime_bundle: tuple[ + _MockInferenceRuntime, + MockStreamInferencePipelineConfig, + MockStreamInferencePipeline, + ], +) -> None: + """Verify runtime construction sets up and retains one pipeline.""" + runtime, pipeline_config, pipeline = runtime_bundle + + assert pipeline_config.setup_calls == 1 + assert runtime._pipeline is pipeline + assert runtime._session_type is MockInferenceSession + assert runtime._local_rank == 0 + assert runtime._global_rank == 0 + assert runtime._world_size == 1 + assert runtime._is_rank_zero + + +def test_create_session_privately_shares_pipeline_and_initializes_fresh_cache( + runtime_bundle: tuple[ + _MockInferenceRuntime, + MockStreamInferencePipelineConfig, + MockStreamInferencePipeline, + ], +) -> None: + """Verify created sessions share the pipeline but own separate caches.""" + runtime, pipeline_config, pipeline = runtime_bundle + + first_session = runtime.create_session() + second_session = runtime.create_session() + + assert pipeline_config.setup_calls == 1 + assert first_session is not second_session + assert first_session._pipeline is pipeline + assert second_session._pipeline is pipeline + assert isinstance(first_session._cache, MockStreamInferencePipelineCache) + assert isinstance(second_session._cache, MockStreamInferencePipelineCache) + assert first_session._cache is not second_session._cache + assert pipeline.initialize_cache_calls == 2 diff --git a/flashdreams/tests/runtime/test_inference_session.py b/flashdreams/tests/runtime/test_inference_session.py new file mode 100644 index 000000000..268959375 --- /dev/null +++ b/flashdreams/tests/runtime/test_inference_session.py @@ -0,0 +1,149 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Pydantic validation tests for inference sessions.""" + +from __future__ import annotations + +from typing import Any + +import pytest +import torch +from pydantic import ValidationError + +from .mocks import ( + MockGlobalCondition, + MockStreamInferencePipeline, + MockUserCondition, + ValidatedInferenceSession, +) + +pytestmark = pytest.mark.ci_cpu + + +## Fixtures and condition factories + + +@pytest.fixture +def session() -> ValidatedInferenceSession: + """Create a session backed by the lightweight pipeline double.""" + return ValidatedInferenceSession(MockStreamInferencePipeline()) + + +def _user_condition() -> MockUserCondition: + """Build a complete per-step condition for validation tests.""" + return MockUserCondition( + movement=torch.tensor([1.0, 0.0, -1.0]), + camera=torch.eye(4), + ) + + +def _global_condition() -> MockGlobalCondition: + """Build a complete rollout-wide condition for validation tests.""" + return MockGlobalCondition( + frame=torch.zeros(3, 8, 8), + prompt=torch.ones(4, 16), + ) + + +## Accepted session inputs + + +def test_step_validates_nested_conditions(session: ValidatedInferenceSession) -> None: + """Verify complete nested conditions pass step validation.""" + user_condition = _user_condition() + global_condition = _global_condition() + inference_input: Any = { + "user_condition": user_condition, + "global_condition": global_condition, + } + + # Pass a raw mapping so ``step`` performs Pydantic validation and conversion. + output = session.step(inference_input) + + assert torch.equal(output.frame_chunk, global_condition.frame) + + +def test_step_accepts_missing_optional_global_condition( + session: ValidatedInferenceSession, +) -> None: + """Verify step accepts an omitted optional global condition.""" + user_condition = _user_condition() + inference_input: Any = {"user_condition": user_condition} + + output = session.step(inference_input) + + assert torch.equal(output.frame_chunk, user_condition.camera) + + +## Rejected session inputs + + +def test_step_rejects_missing_user_condition( + session: ValidatedInferenceSession, +) -> None: + """Verify step rejects an omitted required user condition.""" + inference_input: Any = {"global_condition": _global_condition()} + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert any( + error["loc"][-1:] == ("user_condition",) for error in exc_info.value.errors() + ) + + +@pytest.mark.parametrize("missing_field", ["movement", "camera"]) +def test_step_rejects_missing_user_field( + session: ValidatedInferenceSession, + missing_field: str, +) -> None: + """Verify step rejects a user condition missing a required tensor field.""" + user_condition = _user_condition().model_dump() + del user_condition[missing_field] + inference_input: Any = { + "user_condition": user_condition, + "global_condition": _global_condition(), + } + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert any( + error["loc"][-2:] == ("user_condition", missing_field) + for error in exc_info.value.errors() + ) + + +@pytest.mark.parametrize("missing_field", ["frame", "prompt"]) +def test_step_rejects_missing_global_field( + session: ValidatedInferenceSession, + missing_field: str, +) -> None: + """Verify step rejects a global condition missing a required tensor field.""" + global_condition = _global_condition().model_dump() + del global_condition[missing_field] + inference_input: Any = { + "user_condition": _user_condition(), + "global_condition": global_condition, + } + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert any( + error["loc"][-2:] == ("global_condition", missing_field) + for error in exc_info.value.errors() + ) diff --git a/flashdreams/tests/runtime/test_keyboard_input.py b/flashdreams/tests/runtime/test_keyboard_input.py new file mode 100644 index 000000000..5fa4483ac --- /dev/null +++ b/flashdreams/tests/runtime/test_keyboard_input.py @@ -0,0 +1,87 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Pydantic validation tests for builtin keyboard input.""" + +from typing import Any + +import pytest +from flashdreams.runtime.builtin.user_input.keyboard import ( + KeyboardEvent, + KeyboardKey, + RawUserKeyboardEvent, +) +from pydantic import TypeAdapter, ValidationError + +pytestmark = pytest.mark.ci_cpu + +_RAW_KEYBOARD_EVENT_ADAPTER = TypeAdapter(RawUserKeyboardEvent) + + +## Keyboard event validation + + +@pytest.mark.parametrize( + ("value", "expected"), + [ + ("keydown", KeyboardEvent.KEY_DOWN), + ("keyup", KeyboardEvent.KEY_UP), + ], +) +def test_keyboard_event_parses_enum_values( + value: str, + expected: KeyboardEvent, +) -> None: + """Verify Pydantic parses wire values into keyboard event members.""" + event = _RAW_KEYBOARD_EVENT_ADAPTER.validate_python( + {"timestamp": 1.0, "event": value, "key": "w"} + ) + + assert event["event"] is expected + + +@pytest.mark.parametrize("value", ["keypress", 1, None]) +def test_keyboard_event_rejects_invalid_enum_values(value: Any) -> None: + """Verify Pydantic rejects values outside the keyboard event enum.""" + with pytest.raises(ValidationError): + _RAW_KEYBOARD_EVENT_ADAPTER.validate_python( + {"timestamp": 1.0, "event": value, "key": "w"} + ) + + +## Keyboard key validation + + +@pytest.mark.parametrize("expected", list(KeyboardKey)) +def test_keyboard_key_parses_enum_values(expected: KeyboardKey) -> None: + """Verify Pydantic parses supported key strings into enum members.""" + event = _RAW_KEYBOARD_EVENT_ADAPTER.validate_python( + { + "timestamp": 1.0, + "event": KeyboardEvent.KEY_DOWN, + "key": expected.value, + } + ) + + assert event["key"] is expected + + +@pytest.mark.parametrize("value", ["enter", "", 1, None]) +def test_keyboard_key_rejects_invalid_enum_values(value: Any) -> None: + """Verify Pydantic rejects values outside the keyboard key enum.""" + with pytest.raises(ValidationError): + _RAW_KEYBOARD_EVENT_ADAPTER.validate_python( + {"timestamp": 1.0, "event": "keydown", "key": value} + ) diff --git a/flashdreams/tests/runtime/test_mouse_input.py b/flashdreams/tests/runtime/test_mouse_input.py new file mode 100644 index 000000000..143f0f7ed --- /dev/null +++ b/flashdreams/tests/runtime/test_mouse_input.py @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Pydantic validation tests for builtin mouse input.""" + +from typing import Any + +import pytest +from flashdreams.runtime.builtin.user_input.mouse import ( + MouseButton, + MouseEvent, + RawUserMouseEvent, +) +from pydantic import TypeAdapter, ValidationError + +pytestmark = pytest.mark.ci_cpu + +_RAW_MOUSE_EVENT_ADAPTER = TypeAdapter(RawUserMouseEvent) + + +## Mouse event validation + + +@pytest.mark.parametrize("expected", list(MouseEvent)) +def test_mouse_event_parses_enum_values(expected: MouseEvent) -> None: + """Verify Pydantic parses mouse edge strings into enum members.""" + event = _RAW_MOUSE_EVENT_ADAPTER.validate_python( + {"timestamp": 1.0, "event": expected.value, "button": "left"} + ) + + assert event["event"] is expected + + +## Mouse button validation + + +@pytest.mark.parametrize("expected", list(MouseButton)) +def test_mouse_button_parses_enum_values(expected: MouseButton) -> None: + """Verify Pydantic parses mouse button strings into enum members.""" + event = _RAW_MOUSE_EVENT_ADAPTER.validate_python( + { + "timestamp": 1.0, + "event": MouseEvent.BUTTON_DOWN, + "button": expected.value, + } + ) + + assert event["button"] is expected + + +@pytest.mark.parametrize("value", ["mousemove", "click", 1, None]) +def test_mouse_event_rejects_invalid_enum_values(value: Any) -> None: + """Verify Pydantic rejects values outside the mouse event enum.""" + with pytest.raises(ValidationError): + _RAW_MOUSE_EVENT_ADAPTER.validate_python( + {"timestamp": 1.0, "event": value, "button": "left"} + ) + + +@pytest.mark.parametrize("value", ["back", "", 1, None]) +def test_mouse_button_rejects_invalid_enum_values(value: Any) -> None: + """Verify Pydantic rejects values outside the mouse button enum.""" + with pytest.raises(ValidationError): + _RAW_MOUSE_EVENT_ADAPTER.validate_python( + {"timestamp": 1.0, "event": "mousedown", "button": value} + ) diff --git a/flashdreams/tests/runtime/test_video_output_application.py b/flashdreams/tests/runtime/test_video_output_application.py new file mode 100644 index 000000000..1ce63d66e --- /dev/null +++ b/flashdreams/tests/runtime/test_video_output_application.py @@ -0,0 +1,152 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU tests for the builtin video-output application.""" + +from pathlib import Path + +import pytest +from flashdreams.runtime.application import Application, ApplicationConfig +from flashdreams.runtime.builtin.application.video_output_application import ( + VideoOutputApplication, + VideoOutputApplicationConfig, +) +from flashdreams.runtime.builtin.inference_output.handler.video_output_handler import ( + VideoOutputHandler, +) +from flashdreams.runtime.global_condition import ( + GlobalConditionHandler, + RawGlobalCondition, +) +from flashdreams.runtime.inference_runtime import ( + InferenceRuntime, + InferenceRuntimeConfig, +) +from flashdreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceUserCondition, +) +from flashdreams.runtime.input_system import UserInputHandler + +from .mocks import ( + MockInferenceSession, + MockStreamInferencePipeline, + MockStreamInferencePipelineConfig, +) + +pytestmark = pytest.mark.ci_cpu + + +class _MockInferenceRuntime(InferenceRuntime[MockInferenceSession]): + """Runtime test double that skips pipeline construction.""" + + def __init__(self, config: InferenceRuntimeConfig) -> None: + """Retain the runtime configuration.""" + self.config = config + + def warmup(self) -> None: + """Complete warmup without model execution.""" + + +class _MockUserInputHandler(UserInputHandler): + """User-input handler test double.""" + + def __call__(self) -> InferenceUserCondition: + """Return an empty user condition.""" + return InferenceUserCondition() + + +class _MockGlobalConditionHandler(GlobalConditionHandler): + """Global-condition handler test double.""" + + def __call__( + self, raw_global_condition: RawGlobalCondition + ) -> InferenceGlobalCondition: + """Return an empty inference global condition.""" + del raw_global_condition + return InferenceGlobalCondition() + + +class _TestVideoOutputApplication(VideoOutputApplication[_MockInferenceRuntime]): + """Concrete video-output application test double.""" + + def _initialize_user_input_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> UserInputHandler: + """Construct the application user-input handler.""" + del config + return _MockUserInputHandler() + + def _initialize_global_condition_handler( + self, config: ApplicationConfig[_MockInferenceRuntime] + ) -> GlobalConditionHandler: + """Construct the global-condition handler.""" + del config + return _MockGlobalConditionHandler() + + +def test_video_output_application_initializes_video_handler(tmp_path: Path) -> None: + """Verify construction binds the artifact path to a video output handler.""" + runtime_config = InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ) + artifact_path = tmp_path / "generated.mp4" + config = VideoOutputApplicationConfig( + inference_runtime=runtime_config, + artifact_path=artifact_path, + ) + + application = _TestVideoOutputApplication( + config, + InferenceGlobalCondition(), + ) + + # The base constructor obtains each handler through its child initialization hook. + assert isinstance(application._user_input_handler, _MockUserInputHandler) + assert isinstance(application._inference_output_handler, VideoOutputHandler) + assert application._inference_output_handler.artifact_path == artifact_path + + +def test_video_output_application_finishes_video_handler_after_run( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify a completed application run finishes its video output handler.""" + lifecycle: list[str] = [] + + def run(_application: Application) -> None: + lifecycle.append("run") + + def finish(handler: VideoOutputHandler) -> Path: + lifecycle.append("finish") + return handler.artifact_path + + monkeypatch.setattr(Application, "run", run) + monkeypatch.setattr(VideoOutputHandler, "finish", finish) + config = VideoOutputApplicationConfig( + inference_runtime=InferenceRuntimeConfig( + _target=_MockInferenceRuntime, + pipeline=MockStreamInferencePipelineConfig(MockStreamInferencePipeline()), + session_type=MockInferenceSession, + ), + artifact_path=tmp_path / "generated.mp4", + ) + application = _TestVideoOutputApplication(config, InferenceGlobalCondition()) + + application.run() + + assert lifecycle == ["run", "finish"] diff --git a/flashdreams/tests/runtime/test_video_output_handler.py b/flashdreams/tests/runtime/test_video_output_handler.py new file mode 100644 index 000000000..0552af2d4 --- /dev/null +++ b/flashdreams/tests/runtime/test_video_output_handler.py @@ -0,0 +1,173 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU tests for the builtin video output handler.""" + +from pathlib import Path + +import pytest +import torch +from flashdreams.runtime.builtin.inference_output.frame_chunk import ( + FrameChunkOutput, +) +from flashdreams.runtime.builtin.inference_output.handler import ( + video_output_handler, +) +from flashdreams.runtime.builtin.inference_output.handler.video_output_handler import ( + VideoOutputHandler, +) +from torch import Tensor + +pytestmark = pytest.mark.ci_cpu + + +def _frame_chunk( + value: Tensor, + *, + start_timestamp: float = 0.0, + fps: float = 24.0, +) -> FrameChunkOutput: + """Build a frame chunk with presentation metadata.""" + return FrameChunkOutput( + value=value, + start_timestamp=start_timestamp, + fps=fps, + ) + + +## Artifact writing + + +def test_video_output_handler_collects_tiles_and_writes_chunks( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify finish concatenates time and tiles views like OmniDreams.""" + written_videos: list[Tensor] = [] + written_paths: list[Path] = [] + written_options: list[tuple[float, str, str]] = [] + + def write_video_tensor( + video: Tensor, + path: str | Path, + *, + fps: float, + layout: str, + install_hint: str, + ) -> Path: + written_videos.append(video) + written_paths.append(Path(path)) + written_options.append((float(fps), layout, install_hint)) + return Path(path) + + monkeypatch.setattr( + video_output_handler, + "write_video_tensor", + write_video_tensor, + ) + first = torch.empty(1, 2, 2, 3, 2, 3) + first[:, 0, 0].fill_(-1.0) + first[:, 1, 0].fill_(-0.5) + first[:, 0, 1].fill_(0.0) + first[:, 1, 1].fill_(0.5) + second = torch.empty(1, 2, 1, 3, 2, 3) + second[:, 0, 0].fill_(0.75) + second[:, 1, 0].fill_(1.0) + artifact_path = tmp_path / "nested" / "artifact.mp4" + handler = VideoOutputHandler(artifact_path) + + assert handler(_frame_chunk(first)) is None + assert handler(_frame_chunk(second, start_timestamp=2.0 / 24.0)) is None + assert handler.finish() == artifact_path + assert handler.finish() == artifact_path + + # One write contains all temporal chunks. Each frame places view zero to the + # left of view one, matching the OmniDreams runner's THWC canvas. + assert written_paths == [artifact_path] + assert len(written_videos) == 1 + canvas = written_videos[0] + assert canvas.shape == (3, 2, 6, 3) + torch.testing.assert_close(canvas[0, :, :3], torch.full((2, 3, 3), -1.0)) + torch.testing.assert_close(canvas[0, :, 3:], torch.full((2, 3, 3), -0.5)) + torch.testing.assert_close(canvas[1, :, :3], torch.zeros(2, 3, 3)) + torch.testing.assert_close(canvas[1, :, 3:], torch.full((2, 3, 3), 0.5)) + torch.testing.assert_close(canvas[2, :, :3], torch.full((2, 3, 3), 0.75)) + torch.testing.assert_close(canvas[2, :, 3:], torch.ones(2, 3, 3)) + assert written_options[0][:2] == (24.0, "thwc") + assert written_options[0][2] + + +## Stream validation and lifecycle + + +def test_video_output_handler_rejects_empty_finish(tmp_path: Path) -> None: + """Verify finish requires at least one received frame chunk.""" + handler = VideoOutputHandler(tmp_path / "empty.mp4") + + with pytest.raises(ValueError, match="without frame chunks"): + handler.finish() + + +def test_video_output_handler_rejects_invalid_or_inconsistent_chunks( + tmp_path: Path, +) -> None: + """Verify stream shape, frame rate, and timestamp invariants.""" + handler = VideoOutputHandler(tmp_path / "invalid.mp4") + + with pytest.raises(ValueError, match="rank-6"): + handler(_frame_chunk(torch.zeros(1, 1, 3, 2, 2))) + + handler(_frame_chunk(torch.zeros(1, 1, 2, 3, 2, 2))) + with pytest.raises(ValueError, match="share.*dimensions"): + handler( + _frame_chunk( + torch.zeros(1, 1, 1, 3, 3, 2), + start_timestamp=2.0 / 24.0, + ) + ) + with pytest.raises(ValueError, match="fps 24.0"): + handler( + _frame_chunk( + torch.zeros(1, 1, 1, 3, 2, 2), + start_timestamp=2.0 / 24.0, + fps=30.0, + ) + ) + with pytest.raises(ValueError, match="contiguous.*timestamp"): + handler( + _frame_chunk( + torch.zeros(1, 1, 1, 3, 2, 2), + start_timestamp=1.0, + ) + ) + + +def test_video_output_handler_rejects_chunks_after_finish( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify a successfully finished handler cannot receive more chunks.""" + monkeypatch.setattr( + video_output_handler, + "write_video_tensor", + lambda _video, path, **_kwargs: Path(path), + ) + handler = VideoOutputHandler(tmp_path / "finished.mp4") + chunk = _frame_chunk(torch.zeros(1, 1, 1, 3, 2, 2)) + handler(chunk) + handler.finish() + + with pytest.raises(RuntimeError, match="after finish"): + handler(chunk) diff --git a/flashdreams/tests/test_benchmark_harness.py b/flashdreams/tests/test_benchmark_harness.py index d70f9eb5d..1de03b5db 100644 --- a/flashdreams/tests/test_benchmark_harness.py +++ b/flashdreams/tests/test_benchmark_harness.py @@ -245,6 +245,50 @@ def test_shipped_one_minute_demo_scenarios_load() -> None: } +def test_shipped_omnidreams_demo_replay_scenarios_load() -> None: + repo_root = Path(__file__).resolve().parents[2] + scenarios = load_scenario_file( + repo_root / "configs" / "omnidreams_demo_replay_benchmarks.json" + ) + + assert set(scenarios) == { + "omnidreams-sv-runner-baseline", + "omnidreams-sv-demo-replay", + } + + baseline = scenarios["omnidreams-sv-runner-baseline"] + assert baseline.report_group is not None + assert baseline.report_group.id == "omnidreams-demo" + assert _command_value(baseline.command, "--total-blocks") == "226" + assert "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae" in baseline.command + assert "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae-perf" not in ( + baseline.command + ) + assert baseline.quality_baseline_compare is False + + demo = scenarios["omnidreams-sv-demo-replay"] + assert demo.output_dir_arg is None + assert demo.command[:5] == ( + "uv", + "run", + "--project", + "integrations/omnidreams", + "omnidreams-demo", + ) + assert demo.command[5] == "replay" + assert _command_value(demo.command, "--preset-id") == ( + "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae" + ) + assert _command_value(demo.command, "--total-blocks") == "226" + assert _command_value(demo.command, "--output") == ( + "{output_dir}/omnidreams-sv-demo-replay.mp4" + ) + assert "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae-perf" not in ( + demo.command + ) + assert demo.quality_baseline_compare is False + + def test_shipped_deterministic_quality_scenarios_load() -> None: repo_root = Path(__file__).resolve().parents[2] scenarios = load_scenario_file( diff --git a/integrations/omnidreams/omnidreams/config.py b/integrations/omnidreams/omnidreams/config.py index 9cfac26ab..4fee8537d 100644 --- a/integrations/omnidreams/omnidreams/config.py +++ b/integrations/omnidreams/omnidreams/config.py @@ -13,15 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""User-facing configs for Omnidreams. - -Hosts both the pre-built :class:`OmnidreamsPipelineConfig` literals -and the per-slug :class:`OmnidreamsRunnerConfig` literals that drive -``flashdreams-run``. Each ``RUNNER_*`` literal is wired into the -``flashdreams.runner_configs`` entry-point group by this package's -``pyproject.toml`` and discovered at install time -- no in-tree -registration is performed here. -""" +"""Pre-built OmniDreams inference pipeline configurations.""" from __future__ import annotations @@ -29,21 +21,6 @@ from typing import cast import torch -from omnidreams.encoder.pixel_shuffle import ( - PixelShuffleVAEEncoderConfig, -) -from omnidreams.pipeline import ( - OmnidreamsPipelineConfig, -) -from omnidreams.runner import OmnidreamsRunnerConfig -from omnidreams.transformer import CosmosTransformerConfig -from omnidreams.transformer.impl.network import ( - CosmosDiTNetworkConfig, -) -from omnidreams.vae_native import ( - OmnidreamsWanVAEEncoderConfig as WanVAEEncoderConfig, -) - from flashdreams.infra.config import derive_config from flashdreams.infra.diffusion.model import DiffusionModelConfig from flashdreams.infra.diffusion.scheduler.fm import ( @@ -55,7 +32,6 @@ from flashdreams.infra.encoder.text.cosmos_reason1 import ( CosmosReason1TextEncoderConfig, ) -from flashdreams.infra.runner import RunnerConfig from flashdreams.recipes.taehv import ( AVAILABLE_TAEHV_CHECKPOINT_PATHS, TeahvVAEDecoderConfig, @@ -64,6 +40,19 @@ AVAILABLE_WAN_VAE_CHECKPOINT_PATHS, WanVAEDecoderConfig, ) +from omnidreams.encoder.pixel_shuffle import ( + PixelShuffleVAEEncoderConfig, +) +from omnidreams.pipeline import ( + OmnidreamsPipelineConfig, +) +from omnidreams.transformer import CosmosTransformerConfig +from omnidreams.transformer.impl.network import ( + CosmosDiTNetworkConfig, +) +from omnidreams.vae_native import ( + OmnidreamsWanVAEEncoderConfig as WanVAEEncoderConfig, +) AVAILABLE_OMNIDREAMS_CHECKPOINT_PATHS: dict[str, str] = { "1view-vae-chunk2": ( @@ -428,148 +417,3 @@ def _lightvae_fp8_state_path() -> str | None: ) } """All shipped Omnidreams variants, keyed by ``name``.""" - - -## Per-variant runner-config literals (slug == ``name``). - -_DEFAULT_PROMPT_1V = ( - "Driving scene from a front-facing car camera. Urban environment with roads, " - "vehicles, pedestrians, traffic signs, and buildings. Clear visibility, " - "realistic lighting, photorealistic quality. High resolution dashcam footage " - "of city driving." -) -_DEFAULT_PROMPT_4V = ( - "Wide-angle urban street scene from a low, dashboard-level viewpoint. " - "A straight two-lane road with a faded center line and curbside parking on " - "both sides. Parked sedans and SUVs in neutral colors line the curbs. On the " - "right, a white stucco mid-rise building with blue fabric awnings, rectangular " - "windows, and small storefronts at street level. On the left, a low commercial " - "strip with dark trim, glass fronts, signage, and shaded sidewalks. Mature green " - "trees punctuate both sides. Clear blue sky with sparse soft clouds. Bright midday " - "sunlight, natural colors, realistic materials, crisp shadows, clean asphalt texture." -) - -RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE = OmnidreamsRunnerConfig( - runner_name=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE.name, - description="Single-view 2-step distilled chunk2 (LightVAE + LightTAE).", - pipeline=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF = OmnidreamsRunnerConfig( - runner_name=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF.name, - description=( - "Single-view chunk2 perf preset (compile + CUDA graphs across all stages)." - ), - pipeline=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF = OmnidreamsRunnerConfig( - runner_name=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF.name, - description=( - "Single-view chunk2 native VAE perf preset " - "(LightVAE FP8 encoder + PyTorch LightTAE decoder)." - ), - pipeline=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_SV_2STEPS_CHUNK2_LOC6_VAE_VAE = OmnidreamsRunnerConfig( - runner_name=SV_2STEPS_CHUNK2_LOC6_VAE_VAE.name, - description="Single-view chunk2 with the full Wan VAE on encoder + decoder.", - pipeline=SV_2STEPS_CHUNK2_LOC6_VAE_VAE, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_SV_2STEPS_CHUNK3_LOC6_VAE_VAE = OmnidreamsRunnerConfig( - runner_name=SV_2STEPS_CHUNK3_LOC6_VAE_VAE.name, - description="Single-view chunk3 (len_t=3) with the full Wan VAE.", - pipeline=SV_2STEPS_CHUNK3_LOC6_VAE_VAE, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE = OmnidreamsRunnerConfig( - runner_name=SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE.name, - description="Single-view chunk4 with the PixelShuffle HDMap encoder + LightTAE.", - pipeline=SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE = OmnidreamsRunnerConfig( - runner_name=MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE.name, - description="4-camera multi-view chunk4 (PixelShuffle HDMap + LightTAE).", - pipeline=MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE, - prompt=_DEFAULT_PROMPT_4V, -) - -RUNNER_SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M = OmnidreamsRunnerConfig( - runner_name=SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M.name, - description=( - "Teacher: single-view 35-step UniPC chunk2 (Cosmos2 2B, 720p, CFG=3.0)." - ), - pipeline=SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M = OmnidreamsRunnerConfig( - runner_name=SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M.name, - description=( - "Teacher: single-view 35-step bidirectional chunk48 (one rollout, 720p)." - ), - pipeline=SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_EXPERIMENT1_BASELINE = OmnidreamsRunnerConfig( - runner_name=EXPERIMENT1_BASELINE.name, - description="Experiment-1 baseline (re-publishes the chunk2 perf chassis).", - pipeline=EXPERIMENT1_BASELINE, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE = OmnidreamsRunnerConfig( - runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE.name, - description="Experiment-1: skip-finalize-kv-cache ablation.", - pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350 = OmnidreamsRunnerConfig( - runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350.name, - description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 350].", - pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250 = OmnidreamsRunnerConfig( - runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250.name, - description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 250].", - pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150 = OmnidreamsRunnerConfig( - runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150.name, - description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 150].", - pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150, - prompt=_DEFAULT_PROMPT_1V, -) - -RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100 = OmnidreamsRunnerConfig( - runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100.name, - description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 100].", - pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100, - prompt=_DEFAULT_PROMPT_1V, -) - - -OMNIDREAMS_RUNNERS: dict[str, RunnerConfig] = { - cfg.runner_name: cfg - for cfg in ( - RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE, - RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF, - ) -} -"""All shipped Omnidreams runners (single- and multi-view variants), -keyed by ``runner_name``.""" diff --git a/integrations/omnidreams/omnidreams/runner_config.py b/integrations/omnidreams/omnidreams/runner_config.py new file mode 100644 index 000000000..082e10350 --- /dev/null +++ b/integrations/omnidreams/omnidreams/runner_config.py @@ -0,0 +1,199 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Legacy ``flashdreams-run`` configuration for OmniDreams pipelines.""" + +from flashdreams.infra.runner import RunnerConfig +from omnidreams.config import ( + EXPERIMENT1_BASELINE, + EXPERIMENT1_SKIP_FINALIZE_KV_CACHE, + EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100, + EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150, + EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250, + EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350, + MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE, + SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE, + SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF, + SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF, + SV_2STEPS_CHUNK2_LOC6_VAE_VAE, + SV_2STEPS_CHUNK3_LOC6_VAE_VAE, + SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE, + SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M, + SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M, +) +from omnidreams.runner import OmnidreamsRunnerConfig + +## Per-variant runner-config literals (slug == ``name``). + +_DEFAULT_PROMPT_1V = ( + "Driving scene from a front-facing car camera. Urban environment with roads, " + "vehicles, pedestrians, traffic signs, and buildings. Clear visibility, " + "realistic lighting, photorealistic quality. High resolution dashcam footage " + "of city driving." +) +_DEFAULT_PROMPT_4V = ( + "Wide-angle urban street scene from a low, dashboard-level viewpoint. " + "A straight two-lane road with a faded center line and curbside parking on " + "both sides. Parked sedans and SUVs in neutral colors line the curbs. On the " + "right, a white stucco mid-rise building with blue fabric awnings, rectangular " + "windows, and small storefronts at street level. On the left, a low commercial " + "strip with dark trim, glass fronts, signage, and shaded sidewalks. Mature green " + "trees punctuate both sides. Clear blue sky with sparse soft clouds. Bright midday " + "sunlight, natural colors, realistic materials, crisp shadows, clean asphalt texture." +) + +RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE = OmnidreamsRunnerConfig( + runner_name=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE.name, + description="Single-view 2-step distilled chunk2 (LightVAE + LightTAE).", + pipeline=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF = OmnidreamsRunnerConfig( + runner_name=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF.name, + description=( + "Single-view chunk2 perf preset (compile + CUDA graphs across all stages)." + ), + pipeline=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF = OmnidreamsRunnerConfig( + runner_name=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF.name, + description=( + "Single-view chunk2 native VAE perf preset " + "(LightVAE FP8 encoder + PyTorch LightTAE decoder)." + ), + pipeline=SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_SV_2STEPS_CHUNK2_LOC6_VAE_VAE = OmnidreamsRunnerConfig( + runner_name=SV_2STEPS_CHUNK2_LOC6_VAE_VAE.name, + description="Single-view chunk2 with the full Wan VAE on encoder + decoder.", + pipeline=SV_2STEPS_CHUNK2_LOC6_VAE_VAE, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_SV_2STEPS_CHUNK3_LOC6_VAE_VAE = OmnidreamsRunnerConfig( + runner_name=SV_2STEPS_CHUNK3_LOC6_VAE_VAE.name, + description="Single-view chunk3 (len_t=3) with the full Wan VAE.", + pipeline=SV_2STEPS_CHUNK3_LOC6_VAE_VAE, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE = OmnidreamsRunnerConfig( + runner_name=SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE.name, + description="Single-view chunk4 with the PixelShuffle HDMap encoder + LightTAE.", + pipeline=SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE = OmnidreamsRunnerConfig( + runner_name=MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE.name, + description="4-camera multi-view chunk4 (PixelShuffle HDMap + LightTAE).", + pipeline=MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE, + prompt=_DEFAULT_PROMPT_4V, +) + +RUNNER_SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M = OmnidreamsRunnerConfig( + runner_name=SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M.name, + description=( + "Teacher: single-view 35-step UniPC chunk2 (Cosmos2 2B, 720p, CFG=3.0)." + ), + pipeline=SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M = OmnidreamsRunnerConfig( + runner_name=SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M.name, + description=( + "Teacher: single-view 35-step bidirectional chunk48 (one rollout, 720p)." + ), + pipeline=SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_EXPERIMENT1_BASELINE = OmnidreamsRunnerConfig( + runner_name=EXPERIMENT1_BASELINE.name, + description="Experiment-1 baseline (re-publishes the chunk2 perf chassis).", + pipeline=EXPERIMENT1_BASELINE, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE = OmnidreamsRunnerConfig( + runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE.name, + description="Experiment-1: skip-finalize-kv-cache ablation.", + pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350 = OmnidreamsRunnerConfig( + runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350.name, + description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 350].", + pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250 = OmnidreamsRunnerConfig( + runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250.name, + description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 250].", + pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150 = OmnidreamsRunnerConfig( + runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150.name, + description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 150].", + pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150, + prompt=_DEFAULT_PROMPT_1V, +) + +RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100 = OmnidreamsRunnerConfig( + runner_name=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100.name, + description="Experiment-1: skip-finalize + denoising_timesteps=[1000, 100].", + pipeline=EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100, + prompt=_DEFAULT_PROMPT_1V, +) + + +OMNIDREAMS_RUNNERS: dict[str, RunnerConfig] = { + cfg.runner_name: cfg + for cfg in ( + RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE, + RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF, + ) +} +"""All shipped Omnidreams runners (single- and multi-view variants), +keyed by ``runner_name``.""" + +__all__ = [ + "OMNIDREAMS_RUNNERS", + "RUNNER_EXPERIMENT1_BASELINE", + "RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE", + "RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE100", + "RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE150", + "RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE250", + "RUNNER_EXPERIMENT1_SKIP_FINALIZE_KV_CACHE_NOISE350", + "RUNNER_MV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE", + "RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE", + "RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_NATIVE_PERF", + "RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF", + "RUNNER_SV_2STEPS_CHUNK2_LOC6_VAE_VAE", + "RUNNER_SV_2STEPS_CHUNK3_LOC6_VAE_VAE", + "RUNNER_SV_2STEPS_CHUNK4_LOC8_PSHUFFLE_LIGHTTAE", + "RUNNER_SV_35STEPS_CHUNK2_LOC24_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M", + "RUNNER_SV_35STEPS_CHUNK48_LOC48_COSMOS2_2B_RES720P_30FPS_HDMAP_VAE_MADS1M", +] diff --git a/integrations/omnidreams/omnidreams/runtime/application/headless.py b/integrations/omnidreams/omnidreams/runtime/application/headless.py new file mode 100644 index 000000000..c04d32e5d --- /dev/null +++ b/integrations/omnidreams/omnidreams/runtime/application/headless.py @@ -0,0 +1,597 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""Headless Omnidreams application with HDMap input and video output.""" + +from __future__ import annotations + +import argparse +import copy +from collections.abc import Sequence +from dataclasses import dataclass, field +from pathlib import Path +from typing import Generic, TypeVar + +import torch +from flashdreams.infra.runner_io import ( + DEFAULT_RUNNER_INSTALL_HINT, + load_first_frame_tensor, +) +from flashdreams.runtime.application import ApplicationConfig +from flashdreams.runtime.builtin.application.video_output_application import ( + VideoOutputApplication, + VideoOutputApplicationConfig, +) +from flashdreams.runtime.global_condition import GlobalConditionHandler +from flashdreams.runtime.inference_runtime import ( + InferenceRuntime, + InferenceRuntimeConfig, +) +from flashdreams.runtime.input_system import UserInputHandler +from omnidreams.config import OMNIDREAMS_CONFIGS +from omnidreams.constants import NEGATIVE_PROMPT +from omnidreams.pipeline import OmnidreamsPipeline +from omnidreams.runtime.global_condition import ( + GlobalConditionHandler as OmnidreamsGlobalConditionHandler, +) +from omnidreams.runtime.global_condition import RawGlobalCondition +from omnidreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceSession, +) +from omnidreams.runtime.user_input.hdmap_input_handler import HDMapInputHandler +from omnidreams.transformer import CosmosTransformerConfig + +RuntimeT = TypeVar("RuntimeT", bound=InferenceRuntime) +"""Inference-runtime type owned by the headless application.""" + +DEFAULT_TEXT_PROMPT = ( + "Driving scene from a front-facing car camera. Urban environment with roads, " + "vehicles, pedestrians, traffic signs, and buildings. Clear visibility, " + "realistic lighting, photorealistic quality. High resolution dashcam footage " + "of city driving." +) +"""Default positive prompt for a single-view Omnidreams rollout.""" + +DEFAULT_VIDEO_HEIGHT = 704 +"""Default pixel-space height for HDMap and first-frame inputs.""" + +DEFAULT_VIDEO_WIDTH = 1280 +"""Default pixel-space width for HDMap and first-frame inputs.""" + +DEFAULT_NUM_CHUNKS = 60 +"""Default number of autoregressive chunks generated by a headless rollout.""" + +DEFAULT_ARTIFACT_PATH = Path("outputs/omnidreams.mp4") +"""Default video artifact path for direct application construction.""" + +EXAMPLE_DATA_HF_REPO = "nvidia/omni-dreams-samples" +"""Hugging Face dataset containing single-view HDMap clips and first frames.""" + +EXAMPLE_DATA_HF_BROWSER_URL = ( + "https://huggingface.co/datasets/nvidia/omni-dreams-samples/tree/main/" + "data/single_view" +) +"""Browser URL listing the available single-view example UUIDs.""" + +DEFAULT_EXAMPLE_DATA_UUID = "239560dc-33d1-11ef-9720-00044bcbccac" +"""Default bundled single-view scene UUID.""" + + +@dataclass(kw_only=True) +class OmnidreamsInferenceRuntimeConfig( + InferenceRuntimeConfig["OmnidreamsInferenceRuntime"] +): + """Configuration for the runtime used by the headless CLI.""" + + _target: type[OmnidreamsInferenceRuntime] = field( + default_factory=lambda: OmnidreamsInferenceRuntime + ) + + device: str = "cuda" + """Device receiving the fully constructed inference pipeline.""" + + +class OmnidreamsInferenceRuntime(InferenceRuntime[InferenceSession]): + """Own an Omnidreams pipeline on the configured inference device.""" + + _pipeline: OmnidreamsPipeline + """Pipeline narrowed to the integration type after construction.""" + + def __init__(self, config: OmnidreamsInferenceRuntimeConfig) -> None: + """Construct and place the configured Omnidreams pipeline. + + Args: + config: Pipeline, session, and device configuration. + + Raises: + TypeError: The pipeline config does not construct Omnidreams. + """ + super().__init__(config) + if not isinstance(self._pipeline, OmnidreamsPipeline): + raise TypeError( + "OmnidreamsInferenceRuntime requires an OmnidreamsPipeline; " + f"got {type(self._pipeline).__name__}" + ) + device = f"cuda:{self._local_rank}" if self._world_size > 1 else config.device + self._pipeline = self._pipeline.to(device).eval() + + def warmup(self) -> None: + """Complete the optional warmup hook without a synthetic rollout.""" + + +@dataclass(kw_only=True) +class OmnidreamsHeadlessConfig( + VideoOutputApplicationConfig[RuntimeT], Generic[RuntimeT] +): + """Configuration for a headless HDMap-conditioned application.""" + + _target: type[OmnidreamsHeadless] = field( + default_factory=lambda: OmnidreamsHeadless + ) + + hdmap_path: str | Path | None = None + """HDMap video; required unless bundled example data supplies it.""" + + first_frame_path: str | Path | None = None + """Initial RGB image or video; required unless example data supplies it.""" + + example_data: bool = False + """Download bundled inputs for any path that is not configured.""" + + example_data_uuid: str = DEFAULT_EXAMPLE_DATA_UUID + """Bundled single-view scene UUID selected when ``example_data`` is enabled.""" + + artifact_path: str | Path = DEFAULT_ARTIFACT_PATH + """Destination written by the video output handler.""" + + text_prompt: str = DEFAULT_TEXT_PROMPT + """Positive prompt applied to the generated driving scene.""" + + negative_text_prompt: str = NEGATIVE_PROMPT + """Negative prompt used for classifier-free guidance.""" + + num_frames: int | None = None + """Exact generated frame count; mutually exclusive with ``num_chunks``.""" + + num_chunks: int | None = DEFAULT_NUM_CHUNKS + """Exact generated chunk count; defaults to ``DEFAULT_NUM_CHUNKS``.""" + + pixel_height: int = DEFAULT_VIDEO_HEIGHT + """Resize target height for HDMap videos and first-frame images.""" + + pixel_width: int = DEFAULT_VIDEO_WIDTH + """Resize target width for HDMap videos and first-frame images.""" + + +class OmnidreamsHeadless(VideoOutputApplication[RuntimeT], Generic[RuntimeT]): + """Run Omnidreams from an HDMap video and write generated video output.""" + + def __init__( + self, + config: OmnidreamsHeadlessConfig[RuntimeT], + ) -> None: + """Initialize all input, conditioning, inference, and output components. + + Args: + config: Runtime and application-facing rollout configuration. + + Raises: + ValueError: The rollout limit or raw global condition is invalid. + """ + _validate_generation_limit(config.num_frames, config.num_chunks) + hdmap_path, first_frame_path = _resolve_input_paths(config) + config.hdmap_path = hdmap_path + config.first_frame_path = first_frame_path + super().__init__(config, _placeholder_global_condition()) + + pipeline = self._inference_runtime._pipeline + if not isinstance(pipeline, OmnidreamsPipeline): + raise TypeError( + "OmnidreamsHeadless requires an OmnidreamsPipeline; " + f"got {type(pipeline).__name__}" + ) + first_frame_image = _load_first_frame( + first_frame_path, + pixel_height=config.pixel_height, + pixel_width=config.pixel_width, + device=pipeline.device, + dtype=pipeline.diffusion_model.dtype, + ) + self.handle_global_condition( + RawGlobalCondition( + text_prompt=config.text_prompt, + negative_text_prompt=config.negative_text_prompt, + first_frame_image=first_frame_image, + ) + ) + pipeline.release_oneshot_encoders() + + def _initialize_global_condition_handler( + self, config: ApplicationConfig[RuntimeT] + ) -> GlobalConditionHandler: + """Construct the raw-condition embedding handler for the pipeline. + + Args: + config: Application configuration accepted for the base hook contract. + + Returns: + Handler backed by the runtime pipeline's one-shot encoders. + + Raises: + TypeError: The configured runtime does not own an Omnidreams pipeline. + """ + del config + pipeline = self._inference_runtime._pipeline + if not isinstance(pipeline, OmnidreamsPipeline): + raise TypeError( + "OmnidreamsHeadless requires an OmnidreamsPipeline; " + f"got {type(pipeline).__name__}" + ) + return OmnidreamsGlobalConditionHandler(pipeline) + + def _initialize_user_input_handler( + self, config: ApplicationConfig[RuntimeT] + ) -> UserInputHandler: + """Construct the HDMap input handler for the Omnidreams pipeline. + + Args: + config: Application configuration accepted for the base hook contract. + + Returns: + Handler that yields correctly sized HDMap chunks on the pipeline device. + + Raises: + TypeError: The application was not given headless configuration, or the + configured runtime does not own an Omnidreams pipeline. + """ + if not isinstance(config, OmnidreamsHeadlessConfig): + raise TypeError( + "OmnidreamsHeadless requires OmnidreamsHeadlessConfig; " + f"got {type(config).__name__}" + ) + if config.hdmap_path is None: + raise ValueError("OmnidreamsHeadless requires an HDMap path") + pipeline = self._inference_runtime._pipeline + if not isinstance(pipeline, OmnidreamsPipeline): + raise TypeError( + "OmnidreamsHeadless requires an OmnidreamsPipeline; " + f"got {type(pipeline).__name__}" + ) + return HDMapInputHandler( + config.hdmap_path, + get_num_frames=pipeline.get_num_frames, + num_frames=config.num_frames, + num_chunks=config.num_chunks, + pixel_height=config.pixel_height, + pixel_width=config.pixel_width, + device=pipeline.device, + dtype=pipeline.diffusion_model.dtype, + ) + + +def download_single_view_example_data(uuid: str) -> tuple[Path, Path]: + """Download the HDMap video and first frame for one example UUID. + + Args: + uuid: UUID of a scene under the dataset's ``data/single_view`` directory. + + Returns: + Local cached paths to the HDMap video and first-frame image. + + Raises: + FileNotFoundError: The UUID contains no HDMap video. + RuntimeError: The UUID contains more than one HDMap video. + """ + from huggingface_hub import HfApi, hf_hub_download + from huggingface_hub.hf_api import RepoFile + + subdir = f"data/single_view/{uuid}" + entries = HfApi().list_repo_tree( + repo_id=EXAMPLE_DATA_HF_REPO, + repo_type="dataset", + path_in_repo=subdir, + recursive=False, + ) + files = [entry.path for entry in entries if isinstance(entry, RepoFile)] + hdmap_candidates = [path for path in files if path.endswith("_hdmap.mp4")] + if not hdmap_candidates: + raise FileNotFoundError( + f"No '*_hdmap.mp4' under {subdir!r} in Hugging Face dataset " + f"{EXAMPLE_DATA_HF_REPO!r}. Pick a UUID listed at " + f"{EXAMPLE_DATA_HF_BROWSER_URL} via --example-data-uuid, or supply " + "--hdmap-path and --first-frame-path explicitly." + ) + if len(hdmap_candidates) > 1: + raise RuntimeError( + f"Multiple '*_hdmap.mp4' files under {subdir!r} in " + f"{EXAMPLE_DATA_HF_REPO!r}: {hdmap_candidates}." + ) + + hdmap_path = Path( + hf_hub_download( + repo_id=EXAMPLE_DATA_HF_REPO, + repo_type="dataset", + filename=hdmap_candidates[0], + ) + ) + first_frame_path = Path( + hf_hub_download( + repo_id=EXAMPLE_DATA_HF_REPO, + repo_type="dataset", + filename=f"{subdir}/first_frame.png", + ) + ) + return hdmap_path, first_frame_path + + +def _resolve_input_paths( + config: OmnidreamsHeadlessConfig, +) -> tuple[Path, Path]: + """Resolve explicit or bundled HDMap and first-frame inputs. + + Args: + config: Headless application configuration containing input selection. + + Returns: + Resolved HDMap and first-frame paths. + + Raises: + ValueError: Either path is missing while example data is disabled. + """ + hdmap_path = config.hdmap_path + first_frame_path = config.first_frame_path + if config.example_data and (hdmap_path is None or first_frame_path is None): + example_hdmap_path, example_first_frame_path = ( + download_single_view_example_data(config.example_data_uuid) + ) + hdmap_path = hdmap_path or example_hdmap_path + first_frame_path = first_frame_path or example_first_frame_path + + if hdmap_path is None or first_frame_path is None: + missing = [ + name + for name, path in ( + ("--hdmap-path", hdmap_path), + ("--first-frame-path", first_frame_path), + ) + if path is None + ] + raise ValueError( + f"{', '.join(missing)} must be supplied unless example_data is enabled" + ) + return Path(hdmap_path), Path(first_frame_path) + + +def _validate_generation_limit(num_frames: int | None, num_chunks: int | None) -> None: + """Validate that exactly one positive rollout limit is configured.""" + if (num_frames is None) == (num_chunks is None): + raise ValueError("exactly one of num_frames or num_chunks must be configured") + for name, value in (("num_frames", num_frames), ("num_chunks", num_chunks)): + if value is not None and ( + isinstance(value, bool) or not isinstance(value, int) or value <= 0 + ): + raise ValueError(f"{name} must be a positive integer; got {value!r}") + + +def _headless_config_names() -> tuple[str, ...]: + """Return shipped single-view pipeline names supported by this application.""" + return tuple( + sorted( + name + for name, config in OMNIDREAMS_CONFIGS.items() + if isinstance(config.diffusion_model.transformer, CosmosTransformerConfig) + and config.diffusion_model.transformer.num_views == 1 + ) + ) + + +def _parse_bool(value: str) -> bool: + """Parse a command-line boolean accepted as an explicit value.""" + normalized = value.strip().lower() + if normalized in {"1", "true", "yes", "on"}: + return True + if normalized in {"0", "false", "no", "off"}: + return False + raise argparse.ArgumentTypeError(f"expected a boolean value, got {value!r}") + + +def build_parser() -> argparse.ArgumentParser: + """Build the ``omnidreams-headless`` command-line parser.""" + parser = argparse.ArgumentParser( + prog="omnidreams-headless", + description=( + "Run a single-view Omnidreams rollout from an HDMap video and " + "write the generated frames to a video artifact." + ), + ) + parser.add_argument( + "--config", + required=True, + choices=_headless_config_names(), + help="Shipped single-view pipeline configuration to run.", + ) + parser.add_argument( + "--artifact-path", + type=Path, + help="Destination video artifact path; defaults to outputs/.mp4.", + ) + parser.add_argument( + "--hdmap-path", + type=Path, + help="HDMap video consumed one inference chunk at a time.", + ) + parser.add_argument( + "--first-frame-path", + type=Path, + help=( + "Initial RGB image or video. Video inputs use their first frame and " + "must match the HDMap resolution." + ), + ) + parser.add_argument( + "--example-data", + nargs="?", + const=True, + default=False, + type=_parse_bool, + help="Download bundled inputs for paths that were not supplied.", + ) + parser.add_argument( + "--example-data-uuid", + default=DEFAULT_EXAMPLE_DATA_UUID, + help="Bundled single-view scene UUID.", + ) + parser.add_argument( + "--text-prompt", + default=DEFAULT_TEXT_PROMPT, + help="Positive text prompt for the generated driving scene.", + ) + parser.add_argument( + "--negative-text-prompt", + default=NEGATIVE_PROMPT, + help="Negative text prompt for classifier-free guidance.", + ) + parser.add_argument( + "--device", + default="cuda", + help="Inference device; defaults to cuda.", + ) + + parser.add_argument( + "--pixel-height", + type=int, + default=DEFAULT_VIDEO_HEIGHT, + help=f"Input resize height; defaults to {DEFAULT_VIDEO_HEIGHT}.", + ) + parser.add_argument( + "--pixel-width", + type=int, + default=DEFAULT_VIDEO_WIDTH, + help=f"Input resize width; defaults to {DEFAULT_VIDEO_WIDTH}.", + ) + + rollout_limit = parser.add_mutually_exclusive_group() + rollout_limit.add_argument( + "--num-frames", + type=int, + help="Exact frame count ending on an autoregressive chunk boundary.", + ) + rollout_limit.add_argument( + "--num-chunks", + "--total-blocks", + dest="num_chunks", + type=int, + help=( + "Exact number of autoregressive chunks to generate; defaults to " + f"{DEFAULT_NUM_CHUNKS} when neither rollout limit is provided." + ), + ) + return parser + + +def _load_first_frame( + path: Path, + *, + pixel_height: int, + pixel_width: int, + device: torch.device, + dtype: torch.dtype, +) -> torch.Tensor: + """Load one normalized first frame in ``[1, 1, 1, 3, H, W]`` layout.""" + frame = load_first_frame_tensor( + path, + pixel_height=pixel_height, + pixel_width=pixel_width, + device=device, + dtype=dtype, + allow_video=True, + install_hint=DEFAULT_RUNNER_INSTALL_HINT, + ) + return frame.unsqueeze(1).unsqueeze(1) + + +def _placeholder_global_condition() -> InferenceGlobalCondition: + """Build the temporary condition replaced before the application runs.""" + return InferenceGlobalCondition( + text_embeddings=torch.empty(1, 1, 1, 1), + image_embeddings=torch.empty(1, 1, 1, 1, 1, 1), + ) + + +def _run_from_args(args: argparse.Namespace) -> None: + """Construct and run the headless application from parsed arguments.""" + artifact_path = args.artifact_path or Path("outputs") / f"{args.config}.mp4" + num_chunks = args.num_chunks + if args.num_frames is None and num_chunks is None: + num_chunks = DEFAULT_NUM_CHUNKS + + pipeline_config = copy.deepcopy(OMNIDREAMS_CONFIGS[args.config]) + runtime_config = OmnidreamsInferenceRuntimeConfig( + pipeline=pipeline_config, + session_type=InferenceSession, + device=args.device, + ) + application_config = OmnidreamsHeadlessConfig( + inference_runtime=runtime_config, + artifact_path=artifact_path, + hdmap_path=args.hdmap_path, + first_frame_path=args.first_frame_path, + example_data=args.example_data, + example_data_uuid=args.example_data_uuid, + text_prompt=args.text_prompt, + negative_text_prompt=args.negative_text_prompt, + num_frames=args.num_frames, + num_chunks=num_chunks, + pixel_height=args.pixel_height, + pixel_width=args.pixel_width, + ) + application = OmnidreamsHeadless(application_config) + application.run() + + +def main(argv: Sequence[str] | None = None) -> int: + """Parse command-line arguments and run the headless application. + + Args: + argv: Optional explicit arguments; ``None`` reads from ``sys.argv``. + + Returns: + Process exit status. + """ + args = build_parser().parse_args(argv) + _run_from_args(args) + return 0 + + +__all__ = [ + "DEFAULT_ARTIFACT_PATH", + "DEFAULT_EXAMPLE_DATA_UUID", + "DEFAULT_NUM_CHUNKS", + "DEFAULT_TEXT_PROMPT", + "DEFAULT_VIDEO_HEIGHT", + "DEFAULT_VIDEO_WIDTH", + "OmnidreamsHeadless", + "OmnidreamsHeadlessConfig", + "OmnidreamsInferenceRuntime", + "OmnidreamsInferenceRuntimeConfig", + "build_parser", + "main", +] + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/integrations/omnidreams/omnidreams/runtime/global_condition.py b/integrations/omnidreams/omnidreams/runtime/global_condition.py new file mode 100644 index 000000000..14a0ebf03 --- /dev/null +++ b/integrations/omnidreams/omnidreams/runtime/global_condition.py @@ -0,0 +1,155 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Raw and embedded global conditions for Omnidreams inference.""" + +from typing import Annotated, TypeAlias + +import torch +from flashdreams.runtime.global_condition import ( + GlobalConditionHandler as BaseGlobalConditionHandler, +) +from flashdreams.runtime.global_condition import ( + RawGlobalCondition as BaseRawGlobalCondition, +) +from omnidreams.pipeline import OmnidreamsPipeline +from omnidreams.runtime.inference_session import InferenceGlobalCondition +from pydantic import AfterValidator, StringConstraints, validate_call +from torch import Tensor + + +def _validate_first_frame_image(tensor: Tensor) -> Tensor: + """Validate a normalized single-view first-frame image tensor.""" + if tensor.ndim != 6: + raise ValueError( + "expected a rank-6 first-frame image in " + "[B=1, V=1, T=1, C=3, H, W] layout; " + f"got rank {tensor.ndim} with shape {tuple(tensor.shape)}" + ) + if tuple(tensor.shape[:4]) != (1, 1, 1, 3): + raise ValueError( + "expected first-frame image shape [B=1, V=1, T=1, C=3, H, W]; " + f"got {tuple(tensor.shape)}" + ) + if tensor.shape[-2] <= 0 or tensor.shape[-1] <= 0: + raise ValueError( + "expected positive first-frame image spatial dimensions; " + f"got {tuple(tensor.shape)}" + ) + if not tensor.dtype.is_floating_point: + raise ValueError( + "first-frame image must use a floating-point dtype for normalized " + f"[-1, 1] pixels; got {tensor.dtype}" + ) + return tensor + + +_TextPrompt: TypeAlias = Annotated[ + str, StringConstraints(strip_whitespace=True, min_length=1) +] +"""Validated non-empty positive text prompt.""" + +_NegativeTextPrompt: TypeAlias = Annotated[ + str, StringConstraints(strip_whitespace=True) +] +"""Validated negative text prompt; the empty prompt remains valid.""" + +_FirstFrameImage: TypeAlias = Annotated[ + Tensor, AfterValidator(_validate_first_frame_image) +] +"""Normalized first-frame pixels in ``[1, 1, 1, 3, H, W]`` layout.""" + + +class RawGlobalCondition(BaseRawGlobalCondition): + """Application-facing Omnidreams rollout conditions.""" + + text_prompt: _TextPrompt + """Positive prompt applied to the generated driving scene.""" + + negative_text_prompt: _NegativeTextPrompt + """Negative prompt embedded for classifier-free guidance.""" + + first_frame_image: _FirstFrameImage + """Normalized first-frame pixels in ``[1, 1, 1, 3, H, W]`` layout.""" + + +class GlobalConditionHandler(BaseGlobalConditionHandler): + """Embed raw Omnidreams prompts and a first-frame image.""" + + _pipeline: OmnidreamsPipeline + """Pipeline whose one-shot encoders produce the rollout embeddings.""" + + def __init__(self, pipeline: OmnidreamsPipeline) -> None: + """Initialize the handler with a pipeline containing one-shot encoders. + + Args: + pipeline: Omnidreams pipeline used to validate and embed conditions. + + Raises: + RuntimeError: The pipeline's text or image encoder is not loaded. + """ + self._pipeline = pipeline + self._require_encoders() + + @torch.no_grad() + @validate_call + def __call__( + self, raw_global_condition: RawGlobalCondition + ) -> InferenceGlobalCondition: + """Embed raw prompts and first-frame pixels for an inference session. + + Args: + raw_global_condition: Positive and negative prompts plus normalized + first-frame pixels. + + Returns: + Model-ready text, negative-text, and image embeddings. + + Raises: + RuntimeError: The pipeline's text or image encoder is not loaded. + ValidationError: The raw condition fails Pydantic validation. + ValueError: The image resolution violates pipeline alignment. + """ + text_encoder, image_encoder = self._require_encoders() + first_frame_image = raw_global_condition["first_frame_image"] + self._pipeline._validate_image_resolution(first_frame_image) + + text_embeddings = text_encoder([raw_global_condition["text_prompt"]]).unsqueeze( + 0 + ) + negative_text_embeddings = text_encoder( + [raw_global_condition["negative_text_prompt"]] + ).unsqueeze(0) + image_embeddings = image_encoder(first_frame_image) + return InferenceGlobalCondition( + text_embeddings=text_embeddings, + negative_text_embeddings=negative_text_embeddings, + image_embeddings=image_embeddings, + ) + + def _require_encoders(self): + """Return loaded one-shot encoders or fail with lifecycle guidance.""" + text_encoder = self._pipeline.text_encoder + image_encoder = self._pipeline.image_encoder + if text_encoder is None or image_encoder is None: + raise RuntimeError( + "GlobalConditionHandler requires loaded Omnidreams text and image " + "encoders; construct the pipeline with both encoder configs and " + "do not release one-shot encoders before conversion" + ) + return text_encoder, image_encoder + + +__all__ = ["GlobalConditionHandler", "RawGlobalCondition"] diff --git a/integrations/omnidreams/omnidreams/runtime/inference_session.py b/integrations/omnidreams/omnidreams/runtime/inference_session.py new file mode 100644 index 000000000..eaa0d2b0c --- /dev/null +++ b/integrations/omnidreams/omnidreams/runtime/inference_session.py @@ -0,0 +1,337 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Omnidreams inference session with embedding and HDMap conditions.""" + +from typing import Annotated, TypeAlias, cast + +from flashdreams.infra.decoder import StreamingVideoDecoder +from flashdreams.runtime.builtin.inference_output.frame_chunk import FrameChunkOutput +from flashdreams.runtime.inference_session import ( + InferenceGlobalCondition as BaseInferenceGlobalCondition, +) +from flashdreams.runtime.inference_session import InferenceInput as BaseInferenceInput +from flashdreams.runtime.inference_session import ( + InferenceSession as BaseInferenceSession, +) +from flashdreams.runtime.inference_session import ( + InferenceUserCondition as BaseInferenceUserCondition, +) +from omnidreams.pipeline import OmnidreamsPipeline, OmnidreamsPipelineCache +from pydantic import AfterValidator, Field, TypeAdapter, ValidationInfo +from torch import Tensor +from typing_extensions import TypedDict + + +def _validate_tensor_shape( + tensor: Tensor, + expected_shape: tuple[int | None, ...], + shape_description: str, +) -> Tensor: + """Validate a tensor's rank, fixed axes, and non-empty dimensions.""" + expected_rank = len(expected_shape) + if tensor.ndim != expected_rank: + raise ValueError( + f"expected a rank-{expected_rank} tensor; got rank-{tensor.ndim} " + f"with shape {tuple(tensor.shape)}" + ) + + if any( + expected_size is not None and tensor.shape[axis] != expected_size + for axis, expected_size in enumerate(expected_shape) + ): + raise ValueError( + f"expected tensor shape {shape_description}; got {tuple(tensor.shape)}" + ) + + if any(size <= 0 for size in tensor.shape): + raise ValueError( + f"expected every axis in tensor shape {shape_description} to be positive; " + f"got {tuple(tensor.shape)}" + ) + return tensor + + +def _validate_hdmap(tensor: Tensor) -> Tensor: + return _validate_tensor_shape( + tensor, + (None, None, None, 3, None, None), + "[B, V, T, 3, H, W]", + ) + + +def _validate_text_embeddings(tensor: Tensor) -> Tensor: + return _validate_tensor_shape( + tensor, + (None, None, None, None), + "[B, V, L, D]", + ) + + +def _validate_image_embeddings(tensor: Tensor) -> Tensor: + return _validate_tensor_shape( + tensor, + (None, None, 1, None, None, None), + "[B, V, 1, Cl, Hl, Wl]", + ) + + +_HDMapTensor: TypeAlias = Annotated[Tensor, AfterValidator(_validate_hdmap)] +_TextEmbeddingsTensor: TypeAlias = Annotated[ + Tensor, AfterValidator(_validate_text_embeddings) +] +_ImageEmbeddingsTensor: TypeAlias = Annotated[ + Tensor, AfterValidator(_validate_image_embeddings) +] + + +class InferenceUserCondition(BaseInferenceUserCondition): + """Per-step HDMap condition for Omnidreams inference.""" + + hdmap: _HDMapTensor + """HDMap pixels ``[B, V, T, 3, H, W]`` for the next video chunk.""" + + +class InferenceGlobalCondition(BaseInferenceGlobalCondition): + """Rollout-wide embedding conditions for Omnidreams inference.""" + + text_embeddings: _TextEmbeddingsTensor + """Text embeddings ``[B, V, L, D]`` for the rollout prompts.""" + + negative_text_embeddings: _TextEmbeddingsTensor | None = None + """Optional negative-prompt embeddings ``[B, V, L, D]`` used for CFG.""" + + image_embeddings: _ImageEmbeddingsTensor + """First-frame image embeddings ``[B, V, 1, Cl, Hl, Wl]``.""" + + +InferenceInput: TypeAlias = BaseInferenceInput[ + InferenceUserCondition, InferenceGlobalCondition +] +"""Omnidreams conditions consumed by one inference step.""" + + +class _InferenceValidationContext(TypedDict): + """Pipeline-dependent state supplied to Pydantic input validation.""" + + pipeline: OmnidreamsPipeline + """Pipeline whose shape contracts apply to the input.""" + + autoregressive_index: int + """Index of the step being validated.""" + + rollout_resolution: tuple[int, int] | None + """Pixel resolution established by the active rollout, if any.""" + + +def _validate_condition_shapes( + inference_input: InferenceInput, + validation_info: ValidationInfo, +) -> InferenceInput: + """Validate shape relationships between per-step and rollout conditions.""" + global_condition = inference_input.global_condition + hdmap = inference_input.user_condition.hdmap + + if global_condition is not None: + text_embeddings = global_condition.text_embeddings + image_embeddings = global_condition.image_embeddings + batch_view_shapes = { + "hdmap": tuple(hdmap.shape[:2]), + "text_embeddings": tuple(text_embeddings.shape[:2]), + "image_embeddings": tuple(image_embeddings.shape[:2]), + } + if len(set(batch_view_shapes.values())) != 1: + raise ValueError( + "expected hdmap, text_embeddings, and image_embeddings to share " + f"[B, V] dimensions; got {batch_view_shapes}" + ) + + negative_text_embeddings = global_condition.negative_text_embeddings + if ( + negative_text_embeddings is not None + and negative_text_embeddings.shape != text_embeddings.shape + ): + raise ValueError( + "expected negative_text_embeddings shape to match text_embeddings; " + f"got {tuple(negative_text_embeddings.shape)} and " + f"{tuple(text_embeddings.shape)}" + ) + + if validation_info.context is None: + return inference_input + + context = cast(_InferenceValidationContext, validation_info.context) + pipeline = context["pipeline"] + autoregressive_index = context["autoregressive_index"] + rollout_resolution = context["rollout_resolution"] + + pipeline._validate_image_resolution(hdmap) + + actual_frames = int(hdmap.shape[2]) + expected_frames = pipeline.get_num_frames(autoregressive_index) + if actual_frames != expected_frames: + raise ValueError( + f"expected hdmap T={expected_frames} at autoregressive index " + f"{autoregressive_index}; got T={actual_frames}" + ) + + hdmap_resolution = (int(hdmap.shape[-2]), int(hdmap.shape[-1])) + if rollout_resolution is not None and hdmap_resolution != rollout_resolution: + raise ValueError( + f"expected hdmap resolution {rollout_resolution} for the active rollout; " + f"got {hdmap_resolution}" + ) + + if global_condition is not None: + decoder = pipeline.decoder + assert isinstance(decoder, StreamingVideoDecoder) + compression = decoder.spatial_compression_ratio + expected_latent_resolution = ( + hdmap_resolution[0] // compression, + hdmap_resolution[1] // compression, + ) + image_embeddings = global_condition.image_embeddings + image_latent_resolution = ( + int(image_embeddings.shape[-2]), + int(image_embeddings.shape[-1]), + ) + if image_latent_resolution != expected_latent_resolution: + raise ValueError( + "expected image_embeddings latent resolution " + f"{expected_latent_resolution} for hdmap resolution " + f"{hdmap_resolution}; got {image_latent_resolution}" + ) + return inference_input + + +_ValidatedInferenceInput: TypeAlias = Annotated[ + InferenceInput, AfterValidator(_validate_condition_shapes) +] + +_INFERENCE_INPUT_ADAPTER = TypeAdapter(_ValidatedInferenceInput) + +_PresentationFps: TypeAlias = Annotated[float, Field(gt=0, allow_inf_nan=False)] +_PRESENTATION_FPS_ADAPTER = TypeAdapter(_PresentationFps) + + +class InferenceSession(BaseInferenceSession): + """Stateful Omnidreams inference session backed by a per-rollout cache.""" + + _pipeline: OmnidreamsPipeline + """Omnidreams pipeline shared with the inference runtime.""" + + _cache: OmnidreamsPipelineCache | None + """Per-rollout cache; ``None`` until global conditions initialize it.""" + + autoregressive_index: int + """Zero-based index assigned to the next inference step.""" + + presentation_fps: _PresentationFps + """Frame rate used for output presentation timestamps.""" + + _rollout_resolution: tuple[int, int] | None + """HDMap pixel resolution fixed by the first successful rollout step.""" + + _presented_frame_count: int + """Number of frames emitted on the current presentation timeline.""" + + def __init__( + self, + pipeline: OmnidreamsPipeline, + *, + presentation_fps: _PresentationFps = 30.0, + ) -> None: + """Initialize the session with a presentation frame rate. + + Args: + pipeline: Omnidreams pipeline to drive. + presentation_fps: Frame rate for output presentation timestamps. + + Raises: + ValidationError: ``presentation_fps`` is not positive and finite. + """ + self.presentation_fps = _PRESENTATION_FPS_ADAPTER.validate_python( + presentation_fps + ) + super().__init__(pipeline) + + def reset(self) -> None: + """Reset the session to await rollout-wide embedding conditions.""" + self._cache = None + self.autoregressive_index = 0 + self._rollout_resolution = None + self._presented_frame_count = 0 + + def step(self, inference_input: InferenceInput) -> FrameChunkOutput: + """Generate one video chunk from validated Omnidreams conditions. + + Args: + inference_input: Per-step HDMap and optional first-step embeddings. + + Returns: + Decoded video chunk for the current autoregressive step. + + Raises: + ValueError: Global conditions are missing on the first step or are + supplied after the rollout cache has been initialized. + ValidationError: ``inference_input`` fails Pydantic validation. + """ + inference_input = _INFERENCE_INPUT_ADAPTER.validate_python( + inference_input, + context=_InferenceValidationContext( + pipeline=self._pipeline, + autoregressive_index=self.autoregressive_index, + rollout_resolution=self._rollout_resolution, + ), + ) + global_condition = inference_input.global_condition + if self._cache is None: + if global_condition is None: + raise ValueError( + "global_condition is required on the first step after reset()." + ) + self._cache = self._pipeline.initialize_cache_from_embeddings( + text_embeddings=global_condition.text_embeddings, + image_embeddings=global_condition.image_embeddings, + negative_text_embeddings=global_condition.negative_text_embeddings, + ) + hdmap = inference_input.user_condition.hdmap + self._rollout_resolution = ( + int(hdmap.shape[-2]), + int(hdmap.shape[-1]), + ) + elif global_condition is not None: + # TODO: Support in rollout global condition modification. + raise ValueError( + "global_condition can only be supplied on the first step after reset()." + ) + + video = self._pipeline.generate( + autoregressive_index=self.autoregressive_index, + cache=self._cache, + hdmap=inference_input.user_condition.hdmap, + ) + self._pipeline.finalize( + autoregressive_index=self.autoregressive_index, + cache=self._cache, + ) + start_timestamp = self._presented_frame_count / self.presentation_fps + self._presented_frame_count += int(video.shape[2]) + self.autoregressive_index += 1 + return FrameChunkOutput( + value=video, + start_timestamp=start_timestamp, + fps=self.presentation_fps, + ) diff --git a/integrations/omnidreams/omnidreams/runtime/user_input/hdmap_input_handler.py b/integrations/omnidreams/omnidreams/runtime/user_input/hdmap_input_handler.py new file mode 100644 index 000000000..04a80a3fc --- /dev/null +++ b/integrations/omnidreams/omnidreams/runtime/user_input/hdmap_input_handler.py @@ -0,0 +1,241 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""HDMap video input handler for Omnidreams inference.""" + +from __future__ import annotations + +from collections.abc import Callable +from pathlib import Path + +import torch +from flashdreams.infra.runner_io import ( + DEFAULT_RUNNER_INSTALL_HINT, + read_video_rgb, + resize_rgb_video, + rgb_video_to_normalized_tensor, +) +from flashdreams.runtime.input_system import UserInputHandler +from omnidreams.runtime.inference_session import InferenceUserCondition + + +class HDMapInputHandler(UserInputHandler): + """Iterate over an HDMap video as model-ready inference conditions. + + Args: + hdmap_video_path: Path to an RGB HDMap video. + get_num_frames: Optional function mapping an autoregressive step index to + its required number of pixel frames. Pass the pipeline's + ``get_num_frames`` method when feeding an Omnidreams inference session. + When omitted, each call returns one frame. + num_frames: Exact number of frames to return across all calls. The count + must end on a chunk boundary. Mutually exclusive with ``num_chunks``. + num_chunks: Exact number of complete conditions to return. Mutually + exclusive with ``num_frames``. + pixel_height: Optional resize target height. Must be supplied together + with ``pixel_width``. + pixel_width: Optional resize target width. Must be supplied together + with ``pixel_height``. + device: Device on which returned HDMap tensors are stored. + dtype: Floating-point dtype used for normalized HDMap pixels. + + Raises: + TypeError: ``dtype`` is not floating point or the frame-count provider + returns a non-integer value while resolving a requested limit. + ValueError: The decoded video is malformed, a limit is invalid, the exact + frame count does not end on a chunk boundary, or the video is too short. + """ + + def __init__( + self, + hdmap_video_path: str | Path, + *, + get_num_frames: Callable[[int], int] | None = None, + num_frames: int | None = None, + num_chunks: int | None = None, + pixel_height: int | None = None, + pixel_width: int | None = None, + device: torch.device | str = "cpu", + dtype: torch.dtype = torch.float32, + ) -> None: + """Load and normalize the HDMap video for iterative consumption.""" + if not dtype.is_floating_point: + raise TypeError(f"dtype must be floating point; got {dtype}") + _validate_rollout_limits(num_frames=num_frames, num_chunks=num_chunks) + _validate_resize_dimensions( + pixel_height=pixel_height, + pixel_width=pixel_width, + ) + + self.hdmap_video_path = Path(hdmap_video_path) + video = read_video_rgb( + self.hdmap_video_path, + install_hint=DEFAULT_RUNNER_INSTALL_HINT, + ) + if video.ndim != 4 or video.shape[-1] != 3: + raise ValueError( + "expected an RGB HDMap video with shape [T, H, W, 3]; " + f"got {tuple(video.shape)}" + ) + if any(size <= 0 for size in video.shape): + raise ValueError( + f"HDMap video must have non-empty dimensions: {self.hdmap_video_path}" + ) + if pixel_height is not None and pixel_width is not None: + video = resize_rgb_video( + video, + pixel_height=pixel_height, + pixel_width=pixel_width, + install_hint=DEFAULT_RUNNER_INSTALL_HINT, + ) + + hdmap = rgb_video_to_normalized_tensor( + video, + device=torch.device(device), + dtype=dtype, + ) + # A path represents one rollout and one camera view. Each call slices the + # temporal axis while retaining the condition's [B, V, T, C, H, W] layout. + self._hdmap = hdmap.unsqueeze(0).unsqueeze(0) + self._get_num_frames = get_num_frames or _one_frame_per_condition + self._autoregressive_index = 0 + self._next_frame_index = 0 + self._num_chunks = self._resolve_num_chunks( + num_frames=num_frames, + num_chunks=num_chunks, + ) + + def __call__(self) -> InferenceUserCondition: + """Return the next complete HDMap condition. + + Returns: + Normalized HDMap pixels for the next inference step. + + Raises: + TypeError: The frame-count provider does not return an integer. + ValueError: The frame-count provider returns a non-positive count. + StopIteration: The configured limit or available complete video chunks + have been exhausted. + """ + if ( + self._num_chunks is not None + and self._autoregressive_index >= self._num_chunks + ): + raise StopIteration + + num_frames = self._validated_num_frames(self._autoregressive_index) + end_frame_index = self._next_frame_index + num_frames + if end_frame_index > self._hdmap.shape[2]: + raise StopIteration + + condition = InferenceUserCondition( + hdmap=self._hdmap[:, :, self._next_frame_index : end_frame_index] + ) + self._next_frame_index = end_frame_index + self._autoregressive_index += 1 + return condition + + def _validated_num_frames(self, autoregressive_index: int) -> int: + """Return the validated frame count for one autoregressive step.""" + num_frames = self._get_num_frames(autoregressive_index) + if isinstance(num_frames, bool) or not isinstance(num_frames, int): + raise TypeError( + "get_num_frames must return an integer; " + f"got {num_frames!r} at autoregressive index " + f"{autoregressive_index}" + ) + if num_frames <= 0: + raise ValueError( + "get_num_frames must return a positive value; " + f"got {num_frames} at autoregressive index " + f"{autoregressive_index}" + ) + return num_frames + + def _resolve_num_chunks( + self, + *, + num_frames: int | None, + num_chunks: int | None, + ) -> int | None: + """Resolve an optional exact frame or chunk limit to a chunk count.""" + available_num_frames = int(self._hdmap.shape[2]) + if num_frames is not None and num_frames > available_num_frames: + raise ValueError( + f"requested rollout requires {num_frames} HDMap frames; " + f"video contains {available_num_frames}" + ) + + resolved_num_chunks = num_chunks + required_num_frames = 0 + if num_frames is not None: + resolved_num_chunks = 0 + while required_num_frames < num_frames: + required_num_frames += self._validated_num_frames(resolved_num_chunks) + resolved_num_chunks += 1 + if required_num_frames != num_frames: + raise ValueError( + f"num_frames={num_frames} does not end on an autoregressive " + f"chunk boundary; the next boundary is {required_num_frames}" + ) + elif num_chunks is not None: + required_num_frames = sum( + self._validated_num_frames(index) for index in range(num_chunks) + ) + + if required_num_frames > available_num_frames: + raise ValueError( + f"requested rollout requires {required_num_frames} HDMap frames; " + f"video contains {available_num_frames}" + ) + return resolved_num_chunks + + +def _validate_rollout_limits(*, num_frames: int | None, num_chunks: int | None) -> None: + """Validate optional mutually exclusive rollout limits.""" + if num_frames is not None and num_chunks is not None: + raise ValueError("num_frames and num_chunks are mutually exclusive") + for name, value in (("num_frames", num_frames), ("num_chunks", num_chunks)): + if value is not None and ( + isinstance(value, bool) or not isinstance(value, int) or value <= 0 + ): + raise ValueError(f"{name} must be a positive integer; got {value!r}") + + +def _validate_resize_dimensions( + *, + pixel_height: int | None, + pixel_width: int | None, +) -> None: + """Validate optional paired resize dimensions.""" + if (pixel_height is None) != (pixel_width is None): + raise ValueError("pixel_height and pixel_width must be supplied together") + for name, value in ( + ("pixel_height", pixel_height), + ("pixel_width", pixel_width), + ): + if value is not None and ( + isinstance(value, bool) or not isinstance(value, int) or value <= 0 + ): + raise ValueError(f"{name} must be a positive integer; got {value!r}") + + +def _one_frame_per_condition(_autoregressive_index: int) -> int: + """Return the path-only handler's single-frame chunk size.""" + return 1 + + +__all__ = ["HDMapInputHandler"] diff --git a/integrations/omnidreams/pyproject.toml b/integrations/omnidreams/pyproject.toml index 99d35d73e..f92acfc36 100644 --- a/integrations/omnidreams/pyproject.toml +++ b/integrations/omnidreams/pyproject.toml @@ -22,7 +22,8 @@ name = "flashdreams-omnidreams" version = "0.1.0" description = "Omnidreams inference with flashdreams (webrtc / gRPC servers + the interactive-drive desktop demo)" readme = "README.md" -requires-python = ">=3.10,<3.14" +# PyNvVideoCodec 2.1 currently publishes wheels through CPython 3.12. +requires-python = ">=3.10,<3.13" dependencies = [ # Core inference / serving deps (consumed by ``omnidreams.webrtc``, # ``omnidreams.grpc``, and the ``omnidreams.interactive_drive`` desktop @@ -91,6 +92,9 @@ dev = [ ] [project.scripts] +# Generate a video artifact from prerecorded HDMap and first-frame inputs. +omnidreams-headless = "omnidreams.runtime.application.headless:main" + # ``omnidreams-prepare`` stages resources used by *both* demo paths # (desktop ``interactive-drive`` *and* ``omnidreams.webrtc.server``): # the scene USDZs from ``nvidia/omni-dreams-scenes`` and the @@ -104,6 +108,10 @@ omnidreams-prepare = "omnidreams.prepare:main" # FlashDreams generation, and DrivingGen adapter setup. omnidreams-eval = "omnidreams.eval.cli:main" +# Experimental shared demo API path. This coexists with the legacy +# WebRTC/gRPC/interactive-drive demos until the new adapter is proven. +omnidreams-demo = "omnidreams.demo.cli:main" + # Desktop interactive-drive demo entry point. Requires the # ``interactive-drive`` extra (it adds slangpy); without it the # presenter import fails fast with a clear message. @@ -119,8 +127,8 @@ interactive-drive-configuration = "omnidreams.interactive_drive.input_config.app # scans this group at CLI startup; the entry-point name itself is purely # informational, the registry key always comes from ``cfg.runner_name``. [project.entry-points."flashdreams.runner_configs"] -"omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae" = "omnidreams.config:RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE" -"omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae-perf" = "omnidreams.config:RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF" +"omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae" = "omnidreams.runner_config:RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE" +"omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae-perf" = "omnidreams.runner_config:RUNNER_SV_2STEPS_CHUNK2_LOC6_LIGHTVAE_LIGHTTAE_PERF" [tool.setuptools.packages.find] include = ["omnidreams*"] diff --git a/integrations/omnidreams/tests/runtime/test_global_condition.py b/integrations/omnidreams/tests/runtime/test_global_condition.py new file mode 100644 index 000000000..00c1f90ab --- /dev/null +++ b/integrations/omnidreams/tests/runtime/test_global_condition.py @@ -0,0 +1,176 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU tests for Omnidreams raw global-condition embedding.""" + +from typing import Any, cast + +import pytest +import torch +from omnidreams.pipeline import OmnidreamsPipeline +from omnidreams.runtime.global_condition import ( + GlobalConditionHandler, + RawGlobalCondition, +) +from omnidreams.runtime.inference_session import InferenceGlobalCondition +from pydantic import ValidationError +from torch import Tensor + +pytestmark = pytest.mark.ci_cpu + + +class _TextEncoder: + """Text-encoder test double that records prompts and returns embeddings.""" + + def __init__(self) -> None: + """Initialize the prompt record.""" + self.calls: list[list[str]] = [] + + def __call__(self, prompts: list[str]) -> Tensor: + """Return one deterministic embedding per prompt.""" + self.calls.append(prompts) + value = float(len(self.calls)) + return torch.full((len(prompts), 2, 4), value) + + +class _ImageEncoder: + """Image-encoder test double that records and spatially pools pixels.""" + + def __init__(self) -> None: + """Initialize the image record.""" + self.calls: list[Tensor] = [] + + def __call__(self, image: Tensor) -> Tensor: + """Return a small latent while preserving batch, view, and time axes.""" + self.calls.append(image) + return image.mean(dim=(-2, -1), keepdim=True) + + +class _Pipeline: + """Pipeline test double exposing the one-shot conditioning contract.""" + + def __init__(self) -> None: + """Initialize loaded encoders and image-validation records.""" + self.text_encoder: _TextEncoder | None = _TextEncoder() + self.image_encoder: _ImageEncoder | None = _ImageEncoder() + self.validated_images: list[Tensor] = [] + + def _validate_image_resolution(self, image: Tensor) -> None: + """Record the image passed through pipeline alignment validation.""" + self.validated_images.append(image) + + +def _handler() -> tuple[GlobalConditionHandler, _Pipeline]: + """Build a handler backed by lightweight one-shot encoders.""" + pipeline = _Pipeline() + return GlobalConditionHandler(cast(OmnidreamsPipeline, pipeline)), pipeline + + +def test_global_condition_handler_embeds_prompts_and_first_frame() -> None: + """Verify conversion produces the inference session's embedding layouts.""" + handler, pipeline = _handler() + first_frame_image = torch.full((1, 1, 1, 3, 8, 16), 0.5) + + condition = handler( + RawGlobalCondition( + text_prompt=" drive through a city ", + negative_text_prompt=" blurry ", + first_frame_image=first_frame_image, + ) + ) + + assert isinstance(condition, InferenceGlobalCondition) + assert pipeline.validated_images == [first_frame_image] + assert pipeline.text_encoder is not None + assert pipeline.text_encoder.calls == [["drive through a city"], ["blurry"]] + assert pipeline.image_encoder is not None + assert pipeline.image_encoder.calls == [first_frame_image] + assert condition.text_embeddings.shape == (1, 1, 2, 4) + assert condition.negative_text_embeddings is not None + assert condition.negative_text_embeddings.shape == (1, 1, 2, 4) + assert condition.image_embeddings.shape == (1, 1, 1, 3, 1, 1) + torch.testing.assert_close(condition.text_embeddings, torch.ones(1, 1, 2, 4)) + torch.testing.assert_close( + condition.negative_text_embeddings, + torch.full((1, 1, 2, 4), 2.0), + ) + + +@pytest.mark.parametrize( + "first_frame_image", + [ + torch.zeros(1, 1, 3, 8, 8), + torch.zeros(1, 2, 1, 3, 8, 8), + torch.zeros(1, 1, 1, 4, 8, 8), + torch.zeros(1, 1, 1, 3, 0, 8), + torch.zeros(1, 1, 1, 3, 8, 8, dtype=torch.uint8), + ], +) +def test_global_condition_handler_rejects_invalid_first_frame( + first_frame_image: Tensor, +) -> None: + """Verify raw first-frame tensors satisfy the single-view image contract.""" + handler, _pipeline = _handler() + + with pytest.raises(ValidationError): + handler( + cast( + Any, + { + "text_prompt": "city", + "negative_text_prompt": "blur", + "first_frame_image": first_frame_image, + }, + ) + ) + + +def test_global_condition_handler_rejects_invalid_prompt_and_extra_fields() -> None: + """Verify Pydantic validates raw prompt fields and rejects extras.""" + handler, _pipeline = _handler() + first_frame_image = torch.zeros(1, 1, 1, 3, 8, 8) + + with pytest.raises(ValidationError): + handler( + cast( + Any, + { + "text_prompt": " ", + "negative_text_prompt": "blur", + "first_frame_image": first_frame_image, + }, + ) + ) + with pytest.raises(ValidationError): + handler( + cast( + Any, + { + "text_prompt": "city", + "negative_text_prompt": "blur", + "first_frame_image": first_frame_image, + "unexpected": True, + }, + ) + ) + + +def test_global_condition_handler_requires_loaded_encoders() -> None: + """Verify construction fails after either one-shot encoder is released.""" + pipeline = _Pipeline() + pipeline.text_encoder = None + + with pytest.raises(RuntimeError, match="requires loaded.*text and image"): + GlobalConditionHandler(cast(OmnidreamsPipeline, pipeline)) diff --git a/integrations/omnidreams/tests/runtime/test_headless_application.py b/integrations/omnidreams/tests/runtime/test_headless_application.py new file mode 100644 index 000000000..b6909a024 --- /dev/null +++ b/integrations/omnidreams/tests/runtime/test_headless_application.py @@ -0,0 +1,599 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +"""CPU tests for the headless Omnidreams application.""" + +from dataclasses import dataclass, field +from pathlib import Path + +import pytest +import torch +from flashdreams.infra.decoder import StreamingVideoDecoder +from flashdreams.infra.diffusion.model import DiffusionModelConfig +from flashdreams.infra.diffusion.scheduler.fm_euler import ( + FlowMatchEulerDiscreteSchedulerConfig, +) +from flashdreams.infra.encoder import Encoder +from flashdreams.infra.encoder.text.cosmos_reason1 import ( + CosmosReason1TextEncoderConfig, +) +from flashdreams.recipes.taehv import TeahvVAEDecoder, TeahvVAEDecoderConfig +from flashdreams.recipes.taehv.impl import TAEHVCache +from flashdreams.runtime.builtin.application.video_output_application import ( + VideoOutputApplicationConfig, +) +from flashdreams.runtime.builtin.inference_output.handler.video_output_handler import ( + VideoOutputHandler, +) +from omnidreams.encoder.pixel_shuffle import PixelShuffleVAEEncoderConfig +from omnidreams.pipeline import OmnidreamsPipeline, OmnidreamsPipelineConfig +from omnidreams.runtime.application import headless as headless_module +from omnidreams.runtime.application.headless import ( + OmnidreamsHeadless, + OmnidreamsHeadlessConfig, + OmnidreamsInferenceRuntime, + OmnidreamsInferenceRuntimeConfig, +) +from omnidreams.runtime.global_condition import GlobalConditionHandler +from omnidreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceSession, + InferenceUserCondition, +) +from omnidreams.runtime.user_input import hdmap_input_handler +from omnidreams.runtime.user_input.hdmap_input_handler import HDMapInputHandler +from omnidreams.transformer import CosmosTransformerConfig +from omnidreams.transformer.impl.network import CosmosDiTNetworkConfig +from omnidreams.vae_native import OmnidreamsWanVAEEncoderConfig +from torch import Tensor + +pytestmark = pytest.mark.ci_cpu + + +@dataclass(kw_only=True) +class _TextEncoderConfig(CosmosReason1TextEncoderConfig): + """Configure the checkpoint-free text encoder used by the CPU pipeline.""" + + _target: type["_TextEncoder"] = field(default_factory=lambda: _TextEncoder) + + +class _TextEncoder(Encoder): + """Produce deterministic text embeddings without loading a checkpoint.""" + + def __init__(self, config: CosmosReason1TextEncoderConfig) -> None: + """Initialize the stateless encoder contract.""" + super().__init__(config) + + def forward(self, prompts: list[str]) -> Tensor: + """Return one fixed-size embedding sequence per prompt.""" + return torch.ones(len(prompts), 2, 4) + + +@dataclass(kw_only=True) +class _ImageEncoderConfig(OmnidreamsWanVAEEncoderConfig): + """Configure the checkpoint-free image encoder used by the CPU pipeline.""" + + _target: type["_ImageEncoder"] = field(default_factory=lambda: _ImageEncoder) + + +class _ImageEncoder(Encoder): + """Produce deterministic first-frame latents without loading a checkpoint.""" + + def __init__(self, config: OmnidreamsWanVAEEncoderConfig) -> None: + """Initialize the stateless encoder contract.""" + super().__init__(config) + + def forward(self, image: Tensor) -> Tensor: + """Pool pixels and expand them to the Omnidreams latent-channel count.""" + pooled = image.mean(dim=(-3, -2, -1), keepdim=True) + return pooled.expand(*image.shape[:3], 16, 1, 1) + + +@dataclass(kw_only=True) +class _CPUDecoderConfig(TeahvVAEDecoderConfig): + """Configure the checkpoint-free decoder used by the CPU pipeline.""" + + _target: type["_CPUDecoder"] = field(default_factory=lambda: _CPUDecoder) + + +class _CPUDecoder(TeahvVAEDecoder): + """Preserve the concrete TAEHV contract without loading decoder weights.""" + + def __init__(self, config: TeahvVAEDecoderConfig) -> None: + """Initialize only the streaming decoder interface.""" + StreamingVideoDecoder.__init__(self, config) + + def initialize_autoregressive_cache(self) -> TAEHVCache: + """Return an empty TAEHV-compatible cache.""" + return TAEHVCache() + + def forward( + self, + input: Tensor, + autoregressive_index: int = 0, + cache: TAEHVCache | None = None, + ) -> Tensor: + """Expose three latent channels as a cheap decoded video.""" + del autoregressive_index, cache + return input[..., :3, :, :] + + +def _pipeline_config() -> OmnidreamsPipelineConfig: + """Build an actual Omnidreams pipeline from tiny CPU components.""" + return OmnidreamsPipelineConfig( + name="test-omnidreams-headless", + text_encoder=_TextEncoderConfig(), + image_encoder=_ImageEncoderConfig(), + encoder=PixelShuffleVAEEncoderConfig(), + decoder=_CPUDecoderConfig(), + diffusion_model=DiffusionModelConfig( + transformer=CosmosTransformerConfig( + network=CosmosDiTNetworkConfig( + in_channels=16, + out_channels=16, + patch_spatial=1, + patch_temporal=1, + model_channels=12, + num_blocks=0, + num_heads=1, + mlp_ratio=1.0, + concat_padding_mask=False, + use_adaln_lora=False, + use_crossattn_projection=False, + crossattn_emb_channels=4, + additional_concat_ch=192, + ), + dtype=torch.float32, + checkpoint_path=None, + batch_shape=(1,), + num_views=1, + len_t=2, + h_extrapolation_ratio=1.0, + w_extrapolation_ratio=1.0, + window_size_t=2, + sink_size_t=0, + compile_network=False, + use_cuda_graph=False, + skip_finalize_kv_cache=True, + ), + scheduler=FlowMatchEulerDiscreteSchedulerConfig( + num_inference_steps=1, + fixed_timesteps=(1000.0, 0.0), + ), + seed=0, + ), + ) + + +def _runtime_config() -> OmnidreamsInferenceRuntimeConfig: + """Build the production runtime around the checkpoint-free CPU pipeline.""" + return OmnidreamsInferenceRuntimeConfig( + pipeline=_pipeline_config(), + session_type=InferenceSession, + device="cpu", + ) + + +def _patch_hdmap_video(monkeypatch: pytest.MonkeyPatch, *, num_frames: int) -> None: + """Patch HDMap decoding with an in-memory RGB video.""" + video = torch.zeros(num_frames, 2, 3, 3, dtype=torch.uint8) + + def normalize_video( + value: Tensor, + *, + device: torch.device, + dtype: torch.dtype, + ) -> Tensor: + """Convert the patched THWC video into normalized TCHW layout.""" + return value.permute(0, 3, 1, 2).to(device=device, dtype=dtype) + + monkeypatch.setattr( + hdmap_input_handler, + "read_video_rgb", + lambda _path, **_kwargs: video, + ) + monkeypatch.setattr( + hdmap_input_handler, + "rgb_video_to_normalized_tensor", + normalize_video, + ) + monkeypatch.setattr( + hdmap_input_handler, + "resize_rgb_video", + lambda value, **_kwargs: value, + ) + monkeypatch.setattr( + headless_module, + "_load_first_frame", + lambda _path, **_kwargs: torch.full((1, 1, 1, 3, 8, 8), 0.5), + ) + + +def test_omnidreams_headless_config_defaults(tmp_path: Path) -> None: + """Verify direct construction exposes stable rollout defaults.""" + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + hdmap_path=tmp_path / "hdmap.mp4", + first_frame_path=tmp_path / "first.png", + ) + + assert config.artifact_path == headless_module.DEFAULT_ARTIFACT_PATH + assert config.example_data is False + assert config.example_data_uuid == headless_module.DEFAULT_EXAMPLE_DATA_UUID + assert config.text_prompt == headless_module.DEFAULT_TEXT_PROMPT + assert config.negative_text_prompt == headless_module.NEGATIVE_PROMPT + assert config.num_frames is None + assert config.num_chunks == headless_module.DEFAULT_NUM_CHUNKS + assert config.pixel_height == headless_module.DEFAULT_VIDEO_HEIGHT + assert config.pixel_width == headless_module.DEFAULT_VIDEO_WIDTH + + +def test_omnidreams_headless_resolves_example_data( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify direct construction resolves bundled inputs before setup.""" + _patch_hdmap_video(monkeypatch, num_frames=13) + hdmap_path = tmp_path / "example_hdmap.mp4" + first_frame_path = tmp_path / "first_frame.png" + requested_uuids: list[str] = [] + + def download_example(uuid: str) -> tuple[Path, Path]: + """Record the requested UUID and return local test assets.""" + requested_uuids.append(uuid) + return hdmap_path, first_frame_path + + monkeypatch.setattr( + headless_module, + "download_single_view_example_data", + download_example, + ) + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + artifact_path=tmp_path / "generated.mp4", + example_data=True, + example_data_uuid="test-scene", + num_chunks=2, + ) + + application = OmnidreamsHeadless(config) + + assert requested_uuids == ["test-scene"] + assert config.hdmap_path == hdmap_path + assert config.first_frame_path == first_frame_path + input_handler = application._user_input_handler + assert isinstance(input_handler, HDMapInputHandler) + assert input_handler.hdmap_video_path == hdmap_path + + +def test_omnidreams_headless_requires_paths_without_example_data() -> None: + """Verify missing explicit inputs fail before runtime construction.""" + config = OmnidreamsHeadlessConfig(inference_runtime=_runtime_config()) + + with pytest.raises(ValueError, match="example_data is enabled"): + OmnidreamsHeadless(config) + + +@pytest.mark.parametrize( + ("num_frames", "num_chunks"), + [(13, None), (None, 2)], +) +def test_omnidreams_headless_initializes_hdmap_and_video_handlers( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, + num_frames: int | None, + num_chunks: int | None, +) -> None: + """Verify construction configures all production application handlers.""" + _patch_hdmap_video(monkeypatch, num_frames=13) + artifact_path = tmp_path / "generated.mp4" + hdmap_path = tmp_path / "hdmap.mp4" + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + artifact_path=artifact_path, + hdmap_path=hdmap_path, + first_frame_path=tmp_path / "first.png", + num_frames=num_frames, + num_chunks=num_chunks, + ) + + # The specialized integration config extends the reusable video config. + assert isinstance(config, VideoOutputApplicationConfig) + assert config._target is OmnidreamsHeadless + + application = OmnidreamsHeadless(config) + + # Runtime setup follows the production construction path and owns an actual + # Omnidreams pipeline instead of a manually assembled pipeline shell. + assert type(application._inference_runtime) is OmnidreamsInferenceRuntime + assert type(application._inference_runtime._pipeline) is OmnidreamsPipeline + + # The production input handler is set up during application initialization + # with the pipeline's chunk sizing, placement, and rollout limit. + input_handler = application._user_input_handler + assert type(input_handler) is HDMapInputHandler + assert input_handler.hdmap_video_path == hdmap_path + assert input_handler._get_num_frames(0) == 5 + assert input_handler._get_num_frames(1) == 8 + assert input_handler._num_chunks == 2 + assert input_handler._hdmap.device == torch.device("cpu") + assert input_handler._hdmap.dtype == torch.float32 + + # Construction embeds the config-owned prompt and first frame before + # releasing the one-shot encoders. + assert type(application._global_condition_handler) is GlobalConditionHandler + embedded_condition = application._inference_global_condition + assert isinstance(embedded_condition, InferenceGlobalCondition) + assert embedded_condition.text_embeddings.shape == (1, 1, 2, 4) + assert embedded_condition.negative_text_embeddings is not None + assert embedded_condition.negative_text_embeddings.shape == (1, 1, 2, 4) + assert embedded_condition.image_embeddings.shape == (1, 1, 1, 16, 1, 1) + assert application._inference_runtime._pipeline.text_encoder is None + assert application._inference_runtime._pipeline.image_encoder is None + + # The reusable parent binds the artifact destination to its video handler. + output_handler = application._inference_output_handler + assert isinstance(output_handler, VideoOutputHandler) + assert output_handler.artifact_path == artifact_path + + +@pytest.mark.parametrize( + ("num_frames", "num_chunks"), + [(13, None), (None, 2)], +) +def test_omnidreams_headless_limits_hdmap_input_during_initialization( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, + num_frames: int | None, + num_chunks: int | None, +) -> None: + """Verify both limit modes produce exactly two complete HDMap chunks.""" + _patch_hdmap_video(monkeypatch, num_frames=21) + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + artifact_path=tmp_path / "generated.mp4", + hdmap_path=tmp_path / "hdmap.mp4", + first_frame_path=tmp_path / "first.png", + num_frames=num_frames, + num_chunks=num_chunks, + ) + application = OmnidreamsHeadless(config) + input_handler = application._user_input_handler + + first = input_handler() + second = input_handler() + + assert isinstance(first, InferenceUserCondition) + assert isinstance(second, InferenceUserCondition) + assert first.hdmap.shape == (1, 1, 5, 3, 2, 3) + assert second.hdmap.shape == (1, 1, 8, 3, 2, 3) + with pytest.raises(StopIteration): + input_handler() + + +@pytest.mark.parametrize( + ("num_frames", "num_chunks", "message"), + [ + (None, None, "exactly one"), + (13, 2, "exactly one"), + (0, None, "num_frames must be a positive integer"), + (None, -1, "num_chunks must be a positive integer"), + ], +) +def test_omnidreams_headless_rejects_invalid_rollout_limits( + tmp_path: Path, + num_frames: int | None, + num_chunks: int | None, + message: str, +) -> None: + """Verify application initialization requires one positive rollout limit.""" + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + artifact_path=tmp_path / "generated.mp4", + hdmap_path=tmp_path / "hdmap.mp4", + first_frame_path=tmp_path / "first.png", + num_frames=num_frames, + num_chunks=num_chunks, + ) + + with pytest.raises(ValueError, match=message): + OmnidreamsHeadless(config) + + +def test_omnidreams_headless_rejects_non_boundary_frame_limit( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify an exact frame limit cannot split an autoregressive chunk.""" + _patch_hdmap_video(monkeypatch, num_frames=21) + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + artifact_path=tmp_path / "generated.mp4", + hdmap_path=tmp_path / "hdmap.mp4", + first_frame_path=tmp_path / "first.png", + num_frames=12, + num_chunks=None, + ) + + with pytest.raises(ValueError, match="next boundary is 13"): + OmnidreamsHeadless(config) + + +def test_omnidreams_headless_rejects_short_hdmap_video( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify construction fails when the HDMap cannot supply every chunk.""" + _patch_hdmap_video(monkeypatch, num_frames=20) + config = OmnidreamsHeadlessConfig( + inference_runtime=_runtime_config(), + artifact_path=tmp_path / "generated.mp4", + hdmap_path=tmp_path / "hdmap.mp4", + first_frame_path=tmp_path / "first.png", + num_chunks=3, + ) + + with pytest.raises(ValueError, match="requires 21 HDMap frames.*contains 20"): + OmnidreamsHeadless(config) + + +def test_headless_cli_builds_config_and_runs( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify argparse values drive the concrete application configuration.""" + config_name = headless_module._headless_config_names()[0] + monkeypatch.setitem( + headless_module.OMNIDREAMS_CONFIGS, + config_name, + _pipeline_config(), + ) + events: list[str] = [] + recorded: dict[str, object] = {} + + class _CLIApplication: + """Record CLI application construction and execution.""" + + def __init__(self, config: OmnidreamsHeadlessConfig) -> None: + """Store the application config produced by argument parsing.""" + recorded["config"] = config + + def run(self) -> None: + """Record application execution.""" + events.append("run") + + monkeypatch.setattr(headless_module, "OmnidreamsHeadless", _CLIApplication) + artifact_path = tmp_path / "generated.mp4" + hdmap_path = tmp_path / "hdmap.mp4" + first_frame_path = tmp_path / "first.png" + exit_status = headless_module.main( + [ + "--config", + config_name, + "--artifact-path", + str(artifact_path), + "--hdmap-path", + str(hdmap_path), + "--first-frame-path", + str(first_frame_path), + "--text-prompt", + "drive through a city", + "--negative-text-prompt", + "blurry", + "--device", + "cpu", + "--num-chunks", + "2", + ] + ) + + assert exit_status == 0 + assert events == ["run"] + + application_config = recorded["config"] + assert isinstance(application_config, OmnidreamsHeadlessConfig) + assert application_config.artifact_path == artifact_path + assert application_config.hdmap_path == hdmap_path + assert application_config.first_frame_path == first_frame_path + assert application_config.example_data is False + assert application_config.text_prompt == "drive through a city" + assert application_config.negative_text_prompt == "blurry" + assert application_config.num_frames is None + assert application_config.num_chunks == 2 + + runtime_config = application_config.inference_runtime + assert isinstance(runtime_config, OmnidreamsInferenceRuntimeConfig) + assert runtime_config.device == "cpu" + assert runtime_config.pipeline.name == "test-omnidreams-headless" + assert ( + runtime_config.pipeline is not headless_module.OMNIDREAMS_CONFIGS[config_name] + ) + + +def test_headless_cli_accepts_runtime_input_arguments( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Verify example-data selection and the chunk alias reach CLI dispatch.""" + recorded: dict[str, object] = {} + config_name = "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae-perf" + + monkeypatch.setattr( + headless_module, + "_run_from_args", + lambda args: recorded.update(vars(args)), + ) + + exit_status = headless_module.main( + [ + "--config", + config_name, + "--device", + "cuda:0", + "--example-data", + "True", + "--example-data-uuid", + "239560dc-33d1-11ef-9720-00044bcbccac", + "--total-blocks", + "60", + ] + ) + + assert exit_status == 0 + assert recorded["config"] == config_name + assert recorded["device"] == "cuda:0" + assert recorded["num_chunks"] == 60 + assert recorded["artifact_path"] is None + assert recorded["hdmap_path"] is None + assert recorded["first_frame_path"] is None + assert recorded["example_data"] is True + assert recorded["example_data_uuid"] == "239560dc-33d1-11ef-9720-00044bcbccac" + + +def test_headless_cli_uses_runtime_defaults( + monkeypatch: pytest.MonkeyPatch, + tmp_path: Path, +) -> None: + """Verify omitted optional arguments retain runtime defaults.""" + recorded: dict[str, object] = {} + config_name = "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae-perf" + + monkeypatch.setattr( + headless_module, + "_run_from_args", + lambda args: recorded.update(vars(args)), + ) + + assert ( + headless_module.main( + [ + "--config", + config_name, + "--hdmap-path", + str(tmp_path / "hdmap.mp4"), + "--first-frame-path", + str(tmp_path / "first.png"), + ] + ) + == 0 + ) + assert recorded["text_prompt"] == headless_module.DEFAULT_TEXT_PROMPT + assert recorded["negative_text_prompt"] == headless_module.NEGATIVE_PROMPT + assert recorded["pixel_height"] == headless_module.DEFAULT_VIDEO_HEIGHT + assert recorded["pixel_width"] == headless_module.DEFAULT_VIDEO_WIDTH + assert recorded["num_frames"] is None + assert recorded["num_chunks"] is None + assert recorded["example_data"] is False + assert recorded["example_data_uuid"] == headless_module.DEFAULT_EXAMPLE_DATA_UUID diff --git a/integrations/omnidreams/tests/runtime/test_inference_session.py b/integrations/omnidreams/tests/runtime/test_inference_session.py new file mode 100644 index 000000000..16e6992ce --- /dev/null +++ b/integrations/omnidreams/tests/runtime/test_inference_session.py @@ -0,0 +1,652 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""CPU lifecycle tests for the Omnidreams inference session.""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import Any + +import pytest +import torch +from flashdreams.infra.decoder import StreamingVideoDecoder +from flashdreams.infra.diffusion.model import DiffusionModelConfig +from flashdreams.infra.diffusion.scheduler.fm_euler import ( + FlowMatchEulerDiscreteSchedulerConfig, +) +from flashdreams.recipes.taehv import TeahvVAEDecoder, TeahvVAEDecoderConfig +from flashdreams.recipes.taehv.impl import TAEHVCache +from omnidreams.encoder.pixel_shuffle import ( + PixelShuffleVAEEncoderCache, + PixelShuffleVAEEncoderConfig, +) +from omnidreams.pipeline import OmnidreamsPipeline, OmnidreamsPipelineConfig +from omnidreams.runtime.inference_session import ( + InferenceGlobalCondition, + InferenceInput, + InferenceSession, + InferenceUserCondition, +) +from omnidreams.transformer import CosmosTransformerConfig +from omnidreams.transformer.impl.network import CosmosDiTNetworkConfig +from pydantic import ValidationError +from torch import Tensor + +pytestmark = pytest.mark.ci_cpu + + +## Mock Pipeline + +# OmnidreamsPipeline requires a Wan or TAEHV decoder. This lightweight TAEHV +# subclass preserves that concrete contract without downloading decoder weights; +# the pipeline, HDMap encoder, transformer, scheduler, and caches remain real. + + +@dataclass(kw_only=True) +class _CPUDecoderConfig(TeahvVAEDecoderConfig): + """Configure the checkpoint-free decoder used by the CPU pipeline fixture.""" + + _target: type[_CPUDecoder] = field(default_factory=lambda: _CPUDecoder) + + +class _CPUDecoder(TeahvVAEDecoder): + """Preserve the Taehv pipeline contract without loading decoder weights.""" + + def __init__(self, config: TeahvVAEDecoderConfig) -> None: + """Initialize only the streaming decoder interface.""" + StreamingVideoDecoder.__init__(self, config) + + def initialize_autoregressive_cache(self) -> TAEHVCache: + """Return an empty Taehv-compatible cache.""" + return TAEHVCache() + + def forward( + self, + input: Tensor, + autoregressive_index: int = 0, + cache: TAEHVCache | None = None, + ) -> Tensor: + """Expose three latent channels as a cheap decoded video.""" + del autoregressive_index, cache + # Decoded pixel quality is outside this session test; retaining RGB channels + # keeps output assertions representative without running a pretrained VAE. + return input[..., :3, :, :] + + +@pytest.fixture +def pipeline() -> OmnidreamsPipeline: + """Set up the actual Omnidreams pipeline with tiny CPU components.""" + config = OmnidreamsPipelineConfig( + name="test-omnidreams-inference-session", + # Conditions arrive as precomputed embeddings, so one-shot text/image + # encoders are unnecessary. PixelShuffle remains the real per-step path. + text_encoder=None, + image_encoder=None, + encoder=PixelShuffleVAEEncoderConfig(), + decoder=_CPUDecoderConfig(), + diffusion_model=DiffusionModelConfig( + transformer=CosmosTransformerConfig( + network=CosmosDiTNetworkConfig( + # An 8x8 RGB HDMap becomes a 192-channel 1x1 control latent. + # Zero blocks retain patching, conditioning, and final-layer + # execution while keeping the CPU fixture small. + in_channels=16, + out_channels=16, + patch_spatial=1, + patch_temporal=1, + model_channels=12, + num_blocks=0, + num_heads=1, + mlp_ratio=1.0, + concat_padding_mask=False, + use_adaln_lora=False, + use_crossattn_projection=False, + crossattn_emb_channels=4, + additional_concat_ch=192, + ), + # Keep ci_cpu on eager, random-init code paths with no downloads. + dtype=torch.float32, + checkpoint_path=None, + batch_shape=(1,), + num_views=1, + len_t=1, + h_extrapolation_ratio=1.0, + w_extrapolation_ratio=1.0, + window_size_t=1, + sink_size_t=0, + compile_network=False, + use_cuda_graph=False, + skip_finalize_kv_cache=True, + ), + # One Euler step is enough to exercise generation orchestration. + scheduler=FlowMatchEulerDiscreteSchedulerConfig( + num_inference_steps=1, + fixed_timesteps=(1000.0, 0.0), + ), + seed=0, + ), + ) + + pipeline = config.setup() + assert type(pipeline) is OmnidreamsPipeline + return pipeline + + +@pytest.fixture +def session(pipeline: OmnidreamsPipeline) -> InferenceSession: + """Construct an inference session from the actual pipeline.""" + return InferenceSession(pipeline) + + +## Condition Factories + + +def _user_condition( + value: float, + *, + num_frames: int = 1, + height: int = 8, + width: int = 8, +) -> InferenceUserCondition: + return InferenceUserCondition( + hdmap=torch.full((1, 1, num_frames, 3, height, width), value) + ) + + +def _global_condition( + value: float, + *, + include_negative: bool = False, + latent_height: int = 1, + latent_width: int = 1, +) -> InferenceGlobalCondition: + negative_text_embeddings = ( + torch.full((1, 1, 2, 4), value + 2) if include_negative else None + ) + return InferenceGlobalCondition( + text_embeddings=torch.full((1, 1, 2, 4), value), + negative_text_embeddings=negative_text_embeddings, + image_embeddings=torch.full( + (1, 1, 1, 16, latent_height, latent_width), value + 1 + ), + ) + + +## Session Conditioning + + +def test_step_runs_actual_pipeline_with_global_conditions( + session: InferenceSession, + pipeline: OmnidreamsPipeline, +) -> None: + """Verify the first step initializes and runs the actual pipeline.""" + user_condition = _user_condition(2.0) + global_condition = _global_condition(3.0, include_negative=True) + + output = session.step( + InferenceInput( + user_condition=user_condition, + global_condition=global_condition, + ) + ) + + # Exact type equality prevents a test double from silently replacing the + # integration pipeline while preserving isinstance compatibility. + assert type(pipeline) is OmnidreamsPipeline + assert session._cache is not None + # Pipeline caches record the last generated index; the session index points + # to the next step that will be generated. + assert session._cache.autoregressive_index == 0 + assert isinstance(session._cache.encoder_cache, PixelShuffleVAEEncoderCache) + assert session._cache.encoder_cache.autoregressive_index == 0 + assert session.autoregressive_index == 1 + assert output.value.shape == (1, 1, 1, 3, 1, 1) + assert torch.isfinite(output.value).all() + assert output.start_timestamp == pytest.approx(0.0) + assert output.fps == pytest.approx(30.0) + assert output.fps == session.presentation_fps + assert output.frame_present_time == pytest.approx(1.0 / 30.0) + + +def test_step_uses_session_presentation_fps( + pipeline: OmnidreamsPipeline, +) -> None: + """Verify output timing uses the session-specific presentation rate.""" + session = InferenceSession(pipeline, presentation_fps=24.0) + + output = session.step( + InferenceInput( + user_condition=_user_condition(2.0), + global_condition=_global_condition(3.0), + ) + ) + + assert session.presentation_fps == pytest.approx(24.0) + assert output.fps == pytest.approx(24.0) + assert output.frame_present_time == pytest.approx(1.0 / 24.0) + + +@pytest.mark.parametrize( + "presentation_fps", + [0.0, -1.0, float("nan"), float("inf")], +) +def test_session_rejects_invalid_presentation_fps( + pipeline: OmnidreamsPipeline, + presentation_fps: float, +) -> None: + """Verify sessions reject non-positive and non-finite presentation rates.""" + with pytest.raises(ValidationError): + InferenceSession(pipeline, presentation_fps=presentation_fps) + + +def test_step_reuses_actual_pipeline_cache_with_different_user_conditions( + session: InferenceSession, +) -> None: + """Verify later steps use new HDMaps while retaining rollout state.""" + first_output = session.step( + InferenceInput( + user_condition=_user_condition(1.0), + global_condition=_global_condition(2.0), + ) + ) + cache = session._cache + second_output = session.step( + InferenceInput(user_condition=_user_condition(7.0, num_frames=4)) + ) + + # The second user condition advances the same rollout cache rather than + # rebuilding global text/image conditioning. + assert session._cache is cache + assert cache is not None + assert cache.autoregressive_index == 1 + assert isinstance(cache.encoder_cache, PixelShuffleVAEEncoderCache) + assert cache.encoder_cache.autoregressive_index == 1 + assert session.autoregressive_index == 2 + assert first_output.value.shape == second_output.value.shape + assert torch.isfinite(first_output.value).all() + assert torch.isfinite(second_output.value).all() + assert first_output.start_timestamp == pytest.approx(0.0) + assert second_output.start_timestamp == pytest.approx( + first_output.value.shape[2] * first_output.frame_present_time + ) + assert second_output.fps == first_output.fps + + +def test_step_uses_different_global_conditions_after_reset( + session: InferenceSession, +) -> None: + """Verify reset creates an actual pipeline cache from new embeddings.""" + first_output = session.step( + InferenceInput( + user_condition=_user_condition(2.0), + global_condition=_global_condition(1.0), + ) + ) + first_cache = session._cache + assert first_cache is not None + first_image = first_cache.transformer_cache.image.clone() + + # Reset releases both the cache and its fixed pixel resolution, so a new + # rollout may use a different aligned HDMap/image-latent size. + session.reset() + second_output = session.step( + InferenceInput( + user_condition=_user_condition(8.0, height=16), + global_condition=_global_condition( + 9.0, + include_negative=True, + latent_height=2, + ), + ) + ) + + second_cache = session._cache + assert second_cache is not None + assert second_cache is not first_cache + assert not torch.equal(second_cache.transformer_cache.image, first_image) + assert not torch.equal(second_output.value, first_output.value) + assert second_output.start_timestamp == pytest.approx(0.0) + assert session.autoregressive_index == 1 + + +def test_step_requires_global_conditions_for_new_rollout( + session: InferenceSession, +) -> None: + """Verify a new rollout rejects an HDMap without embedding conditions.""" + with pytest.raises(ValueError, match="global_condition is required"): + session.step(InferenceInput(user_condition=_user_condition(1.0))) + + +def test_step_rejects_global_conditions_during_active_rollout( + session: InferenceSession, +) -> None: + """Verify an active rollout rejects replacement embedding conditions.""" + session.step( + InferenceInput( + user_condition=_user_condition(1.0), + global_condition=_global_condition(2.0), + ) + ) + cache = session._cache + + with pytest.raises(ValueError, match="can only be supplied on the first step"): + session.step( + InferenceInput( + user_condition=_user_condition(3.0, num_frames=4), + global_condition=_global_condition(4.0), + ) + ) + + # Rejection happens before pipeline generation and leaves both indices intact. + assert session._cache is cache + assert cache is not None + assert cache.autoregressive_index == 0 + assert session.autoregressive_index == 1 + + +## Pydantic Schema Validation + + +@pytest.mark.parametrize( + "missing_field", + ["hdmap", "text_embeddings", "image_embeddings"], +) +def test_step_validates_omnidreams_condition_fields( + session: InferenceSession, + missing_field: str, +) -> None: + """Verify Pydantic rejects missing required Omnidreams conditions.""" + inference_input: Any = { + "user_condition": {"hdmap": torch.zeros(1)}, + "global_condition": { + "text_embeddings": torch.zeros(1), + "image_embeddings": torch.zeros(1), + }, + } + container = ( + inference_input["user_condition"] + if missing_field == "hdmap" + else inference_input["global_condition"] + ) + del container[missing_field] + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert any( + error["loc"][-1:] == (missing_field,) for error in exc_info.value.errors() + ) + + +@pytest.mark.parametrize( + ("field_name", "expected_rank"), + [ + ("hdmap", 6), + ("text_embeddings", 4), + ("negative_text_embeddings", 4), + ("image_embeddings", 6), + ], +) +def test_step_validates_omnidreams_condition_tensor_ranks( + session: InferenceSession, + field_name: str, + expected_rank: int, +) -> None: + """Verify Pydantic rejects condition tensors with the wrong rank.""" + # Begin with a fully valid input and replace one field so the reported + # Pydantic location identifies only the dimension under test. + user_condition = _user_condition(1.0).model_dump() + global_condition = _global_condition(2.0, include_negative=True).model_dump() + condition = user_condition if field_name == "hdmap" else global_condition + condition[field_name] = torch.zeros((1,) * (expected_rank - 1)) + inference_input: Any = { + "user_condition": user_condition, + "global_condition": global_condition, + } + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + matching_errors = [ + error for error in exc_info.value.errors() if error["loc"][-1:] == (field_name,) + ] + assert len(matching_errors) == 1 + assert f"rank-{expected_rank}" in matching_errors[0]["msg"] + assert session._cache is None + assert session.autoregressive_index == 0 + + +@pytest.mark.parametrize( + ("field_name", "invalid_tensor", "expected_message"), + [ + ( + "hdmap", + torch.zeros(1, 1, 1, 4, 8, 8), + "[B, V, T, 3, H, W]", + ), + ( + "hdmap", + torch.zeros(1, 1, 0, 3, 8, 8), + "every axis", + ), + ( + "text_embeddings", + torch.zeros(1, 1, 0, 4), + "every axis", + ), + ( + "negative_text_embeddings", + torch.zeros(1, 1, 2, 0), + "every axis", + ), + ( + "image_embeddings", + torch.zeros(1, 1, 2, 16, 1, 1), + "[B, V, 1, Cl, Hl, Wl]", + ), + ( + "image_embeddings", + torch.zeros(1, 1, 1, 16, 0, 1), + "every axis", + ), + ], +) +def test_step_validates_omnidreams_condition_tensor_shapes( + session: InferenceSession, + field_name: str, + invalid_tensor: Tensor, + expected_message: str, +) -> None: + """Verify Pydantic rejects fixed-axis and empty condition shapes.""" + # Keep every other field valid to isolate fixed-axis and empty-axis checks. + user_condition = _user_condition(1.0).model_dump() + global_condition = _global_condition(2.0, include_negative=True).model_dump() + condition = user_condition if field_name == "hdmap" else global_condition + condition[field_name] = invalid_tensor + inference_input: Any = { + "user_condition": user_condition, + "global_condition": global_condition, + } + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + matching_errors = [ + error for error in exc_info.value.errors() if error["loc"][-1:] == (field_name,) + ] + assert len(matching_errors) == 1 + assert expected_message in matching_errors[0]["msg"] + assert session._cache is None + assert session.autoregressive_index == 0 + + +@pytest.mark.parametrize( + ("field_name", "invalid_tensor", "expected_message"), + [ + ( + "hdmap", + torch.zeros(1, 2, 1, 3, 8, 8), + "share [B, V] dimensions", + ), + ( + "text_embeddings", + torch.zeros(2, 1, 2, 4), + "share [B, V] dimensions", + ), + ( + "image_embeddings", + torch.zeros(1, 2, 1, 16, 1, 1), + "share [B, V] dimensions", + ), + ( + "negative_text_embeddings", + torch.zeros(1, 1, 3, 4), + "shape to match text_embeddings", + ), + ], +) +def test_step_validates_condition_shape_relationships( + session: InferenceSession, + field_name: str, + invalid_tensor: Tensor, + expected_message: str, +) -> None: + """Verify Pydantic validates shapes shared by multiple conditions.""" + # These tensors are individually valid; only their shared dimensions differ. + user_condition = _user_condition(1.0).model_dump() + global_condition = _global_condition(2.0, include_negative=True).model_dump() + condition = user_condition if field_name == "hdmap" else global_condition + condition[field_name] = invalid_tensor + inference_input: Any = { + "user_condition": user_condition, + "global_condition": global_condition, + } + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert expected_message in str(exc_info.value) + assert session._cache is None + assert session.autoregressive_index == 0 + + +## Pipeline-aware Pydantic Validation + + +def test_step_validates_hdmap_resolution_alignment_with_pipeline( + session: InferenceSession, +) -> None: + """Verify Pydantic applies the pipeline's pixel-alignment check.""" + # Width 9 violates the fixture's 8x VAE alignment while retaining rank/layout. + inference_input = InferenceInput( + user_condition=_user_condition(1.0, width=9), + global_condition=_global_condition(2.0), + ) + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert "must be divisible by 8" in str(exc_info.value) + assert session._cache is None + assert session.autoregressive_index == 0 + + +def test_step_validates_image_embedding_resolution_against_hdmap( + session: InferenceSession, +) -> None: + """Verify Pydantic relates image latent and HDMap pixel resolutions.""" + # A 16x8 HDMap requires a 2x1 latent, but the default global condition is 1x1. + inference_input = InferenceInput( + user_condition=_user_condition(1.0, height=16), + global_condition=_global_condition(2.0), + ) + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert "expected image_embeddings latent resolution (2, 1)" in str(exc_info.value) + assert session._cache is None + assert session.autoregressive_index == 0 + + +def test_step_validates_first_hdmap_frame_count_with_pipeline( + session: InferenceSession, +) -> None: + """Verify Pydantic checks the first AR step's HDMap frame count.""" + # len_t=1 produces one pixel frame at AR 0 despite the steady-state 4x ratio. + inference_input = InferenceInput( + user_condition=_user_condition(1.0, num_frames=4), + global_condition=_global_condition(2.0), + ) + + with pytest.raises(ValidationError) as exc_info: + session.step(inference_input) + + assert "expected hdmap T=1 at autoregressive index 0; got T=4" in str( + exc_info.value + ) + assert session._cache is None + assert session.autoregressive_index == 0 + + +def test_step_validates_later_hdmap_frame_count_with_pipeline( + session: InferenceSession, +) -> None: + """Verify Pydantic checks later AR steps using the pipeline index.""" + session.step( + InferenceInput( + user_condition=_user_condition(1.0), + global_condition=_global_condition(2.0), + ) + ) + cache = session._cache + + # Steady-state PixelShuffle/TAEHV geometry requires four input frames. + with pytest.raises(ValidationError) as exc_info: + session.step(InferenceInput(user_condition=_user_condition(3.0))) + + assert "expected hdmap T=4 at autoregressive index 1; got T=1" in str( + exc_info.value + ) + assert session._cache is cache + assert cache is not None + assert cache.autoregressive_index == 0 + assert session.autoregressive_index == 1 + + +def test_step_validates_hdmap_resolution_is_stable_during_rollout( + session: InferenceSession, +) -> None: + """Verify Pydantic rejects aligned resolution changes within a rollout.""" + session.step( + InferenceInput( + user_condition=_user_condition(1.0), + global_condition=_global_condition(2.0), + ) + ) + cache = session._cache + + # 16x8 is independently aligned; only changing the active rollout size is invalid. + with pytest.raises(ValidationError) as exc_info: + session.step( + InferenceInput(user_condition=_user_condition(3.0, num_frames=4, height=16)) + ) + + assert "expected hdmap resolution (8, 8)" in str(exc_info.value) + assert session._cache is cache + assert cache is not None + assert cache.autoregressive_index == 0 + assert session.autoregressive_index == 1 diff --git a/integrations/omnidreams/tests/test_demo_api.py b/integrations/omnidreams/tests/test_demo_api.py new file mode 100644 index 000000000..8426911be --- /dev/null +++ b/integrations/omnidreams/tests/test_demo_api.py @@ -0,0 +1,576 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +from collections.abc import Sequence +from pathlib import Path +from typing import Any, cast + +import omnidreams.demo.spec as spec_module +import omnidreams.demo.webrtc as demo_webrtc_module +import pytest +import torch +from aiohttp import web +from flashdreams.infra.video_output import VideoStepResult +from flashdreams.runtime import ( + InferenceConfig, + InferenceInput, + OutputArtifact, + OutputTarget, + StepResult, +) +from flashdreams.runtime.demo import ( + DemoSpec, + Mp4OutputSpec, + WebRTCOutputSpec, + serve_flashdreams_demo, +) +from flashdreams.runtime.demo.replay import run_replay_demo +from flashdreams.runtime.demo.webrtc import WebRTCDemo, build_webrtc_demo +from flashdreams.serving.webrtc.server import SESSION_MANAGER_KEY +from omnidreams.demo import ( + DEFAULT_OMNIDREAMS_PRESET, + OMNIDREAMS_MODEL_ID, + OmnidreamsDemoAdapter, + OmnidreamsReplayScenario, + OmnidreamsWebRTCScenario, +) +from omnidreams.demo.cli import _replay_spec, _webrtc_spec, parse_args +from omnidreams.demo.replay import ( + OmnidreamsReplayRuntime, + OmnidreamsReplayRuntimeOptions, +) +from omnidreams.demo.webrtc import OmnidreamsDemoWebRTCSessionManager +from omnidreams.runner_config import OMNIDREAMS_RUNNERS + +pytestmark = pytest.mark.ci_cpu + + +def test_omnidreams_demo_defaults_to_stable_non_perf_preset() -> None: + args = parse_args(["replay", "--output", "demo.mp4"]) + + assert args.preset_id == "omnidreams-sv-2steps-chunk2-loc6-lightvae-lighttae" + assert not args.preset_id.endswith("-perf") + + +def test_omnidreams_demo_adapter_declares_mp4_and_webrtc_modes() -> None: + adapter = OmnidreamsDemoAdapter() + + assert adapter.model_id == OMNIDREAMS_MODEL_ID + assert adapter.supported_input_modes() == ("replay", "keyboard-driving") + assert adapter.supported_output_modes() == ("mp4", "webrtc") + + +def test_omnidreams_replay_demo_uses_shared_runner(tmp_path: Path) -> None: + hdmap = tmp_path / "hdmap.mp4" + first_frame = tmp_path / "first.png" + hdmap.write_bytes(b"fake") + first_frame.write_bytes(b"fake") + pipeline_config = object() + adapter = OmnidreamsDemoAdapter() + output = _RecordingOutputTarget() + calls: list[dict[str, Any]] = [] + + def fake_runner(**kwargs: Any) -> Sequence[OutputArtifact]: + calls.append(kwargs) + return (OutputArtifact(kind="video/mp4", uri="memory://omnidreams"),) + + spec = DemoSpec( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + input_mode="replay", + scenario={ + "prompt": "drive through a city", + "hdmap_video_paths": (hdmap,), + "first_frame_paths": (first_frame,), + "camera_names": ("camera_front_wide_120fov",), + "total_blocks": 1, + }, + output=Mp4OutputSpec(path=tmp_path / "demo.mp4", fps=30), + config=InferenceConfig( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + runtime_options={"pipeline_config": pipeline_config}, + ), + ) + + artifacts = run_replay_demo( + spec=spec, + adapter=adapter, + output_target_factory=lambda output_spec: output, + runner=fake_runner, + ) + + assert artifacts == (OutputArtifact(kind="video/mp4", uri="memory://omnidreams"),) + assert len(calls) == 1 + assert calls[0]["adapter"] is adapter + assert calls[0]["config"] == spec.config + scenario = calls[0]["initial_inputs"].global_conditioning["scenario"] + assert isinstance(scenario, OmnidreamsReplayScenario) + assert scenario.prompts == ("drive through a city",) + assert scenario.hdmap_video_paths == (hdmap,) + assert scenario.first_frame_paths == (first_frame,) + assert scenario.camera_names == ("camera_front_wide_120fov",) + + +def test_omnidreams_replay_invalid_scenario_fails_before_runtime_creation( + tmp_path: Path, +) -> None: + adapter = OmnidreamsDemoAdapter( + replay_runtime_factory=lambda **kwargs: pytest.fail( + f"runtime should not be created: {kwargs}" + ) + ) + output_factory_calls = 0 + + def output_factory(output_spec: object) -> OutputTarget: + nonlocal output_factory_calls + del output_spec + output_factory_calls += 1 + return _RecordingOutputTarget() + + spec = DemoSpec( + model_id=OMNIDREAMS_MODEL_ID, + input_mode="replay", + scenario={ + "prompt": "drive", + "hdmap_video_paths": (tmp_path / "missing-hdmap.mp4",), + "first_frame_paths": (tmp_path / "missing-first.png",), + }, + output=Mp4OutputSpec(path=tmp_path / "demo.mp4", fps=30), + config=InferenceConfig( + model_id=OMNIDREAMS_MODEL_ID, + runtime_options={"pipeline_config": object()}, + ), + ) + + with pytest.raises(FileNotFoundError, match="missing hdmap_video_paths"): + run_replay_demo( + spec=spec, + adapter=adapter, + output_target_factory=output_factory, + ) + + assert output_factory_calls == 0 + + +def test_omnidreams_replay_cli_defaults_to_hf_example_data( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + hdmap = tmp_path / "hf-hdmap.mp4" + first_frame = tmp_path / "hf-first.png" + hdmap.write_bytes(b"fake") + first_frame.write_bytes(b"fake") + synced_uuids: list[str] = [] + + def fake_sync(uuid: str) -> tuple[tuple[Path, ...], tuple[Path, ...]]: + synced_uuids.append(uuid) + return (hdmap,), (first_frame,) + + monkeypatch.setattr( + spec_module, + "_ensure_hf_single_view_example_data_synced", + fake_sync, + ) + args = parse_args(["replay", "--output", str(tmp_path / "demo.mp4")]) + spec = _replay_spec(args) + + prepared = OmnidreamsDemoAdapter().prepare_scenario(spec) + + scenario = prepared.initial_inputs.global_conditioning["scenario"] + assert isinstance(scenario, OmnidreamsReplayScenario) + assert synced_uuids == ["239560dc-33d1-11ef-9720-00044bcbccac"] + assert scenario.hdmap_video_paths == (hdmap,) + assert scenario.first_frame_paths == (first_frame,) + assert scenario.camera_names == ("camera_front_wide_120fov",) + assert scenario.prompts == ( + str(getattr(OMNIDREAMS_RUNNERS[DEFAULT_OMNIDREAMS_PRESET], "prompt")), + ) + + +def test_omnidreams_replay_cli_can_disable_example_data(tmp_path: Path) -> None: + args = parse_args( + ["replay", "--no-example-data", "--output", str(tmp_path / "demo.mp4")] + ) + spec = _replay_spec(args) + + with pytest.raises(ValueError, match="requires hdmap_video_paths"): + OmnidreamsDemoAdapter().prepare_scenario(spec) + + +def test_omnidreams_replay_runtime_generates_video_step_result( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + import omnidreams.demo.replay as replay_module + + hdmap = tmp_path / "hdmap.mp4" + first_frame = tmp_path / "first.png" + hdmap.write_bytes(b"fake") + first_frame.write_bytes(b"fake") + pipeline = _FakeOmnidreamsPipeline() + monkeypatch.setattr( + replay_module, + "load_first_frame_tensor", + lambda *args, **kwargs: torch.zeros(1, 3, 2, 2), + ) + monkeypatch.setattr( + replay_module, + "_load_video", + lambda *args, **kwargs: torch.zeros(2, 3, 2, 2), + ) + + runtime = OmnidreamsReplayRuntime( + config=InferenceConfig(model_id=OMNIDREAMS_MODEL_ID, device="cpu"), + options=OmnidreamsReplayRuntimeOptions( + pipeline_config=object(), + pipeline_factory=lambda pipeline_config, device: pipeline, + ), + ) + scenario = OmnidreamsReplayScenario( + prompts=("drive",), + hdmap_video_paths=(hdmap,), + first_frame_paths=(first_frame,), + camera_names=("camera_front_wide_120fov",), + total_blocks=1, + pixel_height=2, + pixel_width=2, + fps=30, + ) + session = runtime.start_session( + InferenceInput(global_conditioning={"scenario": scenario}) + ) + + request = session.next_step_request() + assert request is not None + assert request.step_index == 0 + result = session.step(InferenceInput()) + + assert result.step_index == 0 + assert result.frame_count == 1 + assert isinstance(result.output, VideoStepResult) + assert result.output.layout == "bvtchw" + assert result.output.video_chunk.shape == (1, 1, 1, 3, 2, 2) + assert result.metrics["denoise_s"] == 0.25 + assert session.next_step_request() is None + assert pipeline.initialize_cache_calls == [ + { + "text": [["drive"]], + "image_shape": (1, 1, 1, 3, 2, 2), + "view_names": ["camera_front_wide_120fov"], + } + ] + runtime.close() + + +def test_omnidreams_webrtc_cli_builds_keyboard_driving_spec(tmp_path: Path) -> None: + args = parse_args( + [ + "webrtc", + "--host", + "127.0.0.1", + "--port", + "9090", + "--device", + "cuda:2", + "--seed", + "123", + "--scene-dir", + str(tmp_path / "scene"), + "--scene-uuid", + "scene-1", + "--scene-variant", + "rain", + "--camera-name", + "camera_front_wide_120fov", + "--fps", + "24", + "--video-height", + "32", + "--video-width", + "64", + "--warmup-chunks", + "0", + "--warmup-timeout-s", + "1.5", + "--client-liveness-timeout-s", + "2.5", + "--debug-serve-hdmaps", + "--prefer-sw-encoder", + ] + ) + + spec = _webrtc_spec(args, device="cuda:3") + + assert spec.model_id == OMNIDREAMS_MODEL_ID + assert spec.preset_id == DEFAULT_OMNIDREAMS_PRESET + assert spec.input_mode == "keyboard-driving" + assert isinstance(spec.scenario, OmnidreamsWebRTCScenario) + assert spec.scenario.scene_dir == tmp_path / "scene" + assert spec.scenario.scene_uuid == "scene-1" + assert spec.scenario.scene_variant == "rain" + assert spec.scenario.camera_name == "camera_front_wide_120fov" + assert spec.scenario.debug_serve_hdmaps is True + assert spec.scenario.prefer_sw_encoder is True + assert isinstance(spec.output, WebRTCOutputSpec) + assert spec.output.host == "127.0.0.1" + assert spec.output.port == 9090 + assert spec.output.fps == 24 + assert spec.output.video_width == 64 + assert spec.output.video_height == 32 + assert spec.output.warmup_chunks == 0 + assert spec.output.warmup_timeout_s == 1.5 + assert spec.output.client_liveness_timeout_s == 2.5 + assert spec.config is not None + assert spec.config.device == "cuda:3" + assert spec.config.runtime_options["seed"] == 123 + + +def test_omnidreams_webrtc_demo_uses_shared_manager_with_model_config() -> None: + pipeline_config = object() + adapter = OmnidreamsDemoAdapter(webrtc_runtime_factory=_FakeWebRTCRuntime) + spec = DemoSpec( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + input_mode="keyboard-driving", + scenario=OmnidreamsWebRTCScenario( + scene_uuid="scene-1", + scene_variant="rain", + camera_name="camera_front_wide_120fov", + debug_serve_hdmaps=True, + prefer_sw_encoder=True, + ), + output=WebRTCOutputSpec( + host="0.0.0.0", + port=8082, + fps=24, + video_width=64, + video_height=32, + warmup_chunks=0, + warmup_timeout_s=1.0, + ), + config=InferenceConfig( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + device="cuda:7", + runtime_options={"pipeline_config": pipeline_config, "seed": 123}, + ), + ) + + demo = build_webrtc_demo(spec=spec, adapter=adapter) + + assert isinstance(demo.runtime, _FakeWebRTCRuntime) + assert isinstance(demo.session_manager, OmnidreamsDemoWebRTCSessionManager) + assert demo.session_manager._runtime is demo.runtime + assert demo.session_manager.runtime_config is demo.runtime.config + assert demo.runtime_config is demo.runtime.config + assert demo.runtime_config.pipeline_config is pipeline_config + assert demo.runtime_config.pipeline_config_name == DEFAULT_OMNIDREAMS_PRESET + assert demo.runtime_config.scene_uuid == "scene-1" + assert demo.runtime_config.scene_variant == "rain" + assert demo.runtime_config.seed == 123 + assert demo.runtime_config.device == "cuda:7" + assert demo.runtime_config.video_width == 64 + assert demo.runtime_config.video_height == 32 + assert demo.runtime_config.fps == 24 + assert demo.runtime_config.debug_serve_hdmaps is True + assert demo.runtime_config.encoder_backend == "default" + assert demo.session_manager._model_name() == DEFAULT_OMNIDREAMS_PRESET + assert demo.host == "0.0.0.0" + assert demo.port == 8082 + + +def test_omnidreams_webrtc_demo_installs_model_routes( + monkeypatch: pytest.MonkeyPatch, +) -> None: + app_calls: list[dict[str, Any]] = [] + + def fake_create_packaged_webrtc_app(**kwargs: Any) -> web.Application: + app_calls.append(kwargs) + app = web.Application() + app[SESSION_MANAGER_KEY] = kwargs["session_manager"] + kwargs["configure_app"](app) + return app + + monkeypatch.setattr( + demo_webrtc_module, + "create_packaged_webrtc_app", + fake_create_packaged_webrtc_app, + ) + adapter = OmnidreamsDemoAdapter(webrtc_runtime_factory=_FakeWebRTCRuntime) + spec = DemoSpec( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + input_mode="keyboard-driving", + scenario=OmnidreamsWebRTCScenario(), + output=WebRTCOutputSpec( + host="0.0.0.0", + port=8082, + warmup_timeout_s=1.0, + preload_name="Test Omnidreams", + ), + config=InferenceConfig( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + runtime_options={"pipeline_config": object()}, + ), + ) + + demo = build_webrtc_demo(spec=spec, adapter=adapter, create_app=True) + + assert demo.app is not None + assert app_calls[0]["session_manager"] is demo.session_manager + assert app_calls[0]["request_session_url"] == ( + "http://127.0.0.1:8082/request_session" + ) + assert app_calls[0]["preload_name"] == "Test Omnidreams" + route_paths = {resource.canonical for resource in demo.app.router.resources()} + assert "/api/postprocess/options" in route_paths + assert "/api/session/input" in route_paths + + +def test_omnidreams_webrtc_demo_serves_through_shared_runner( + monkeypatch: pytest.MonkeyPatch, +) -> None: + server_calls: list[dict[str, Any]] = [] + + def fake_create_packaged_webrtc_app(**kwargs: Any) -> web.Application: + app = web.Application() + app[SESSION_MANAGER_KEY] = kwargs["session_manager"] + kwargs["configure_app"](app) + return app + + def fake_server_runner(**kwargs: Any) -> None: + server_calls.append(kwargs) + + monkeypatch.setattr( + demo_webrtc_module, + "create_packaged_webrtc_app", + fake_create_packaged_webrtc_app, + ) + adapter = OmnidreamsDemoAdapter(webrtc_runtime_factory=_FakeWebRTCRuntime) + spec = DemoSpec( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + input_mode="keyboard-driving", + scenario={"scene_uuid": "scene-1"}, + output=WebRTCOutputSpec( + host="0.0.0.0", + port=8082, + warmup_timeout_s=1.0, + ), + config=InferenceConfig( + model_id=OMNIDREAMS_MODEL_ID, + preset_id=DEFAULT_OMNIDREAMS_PRESET, + runtime_options={"pipeline_config": object()}, + ), + ) + + demo = cast( + WebRTCDemo, + serve_flashdreams_demo( + spec=spec, + adapter=adapter, + world_rank=0, + server_runner=fake_server_runner, + ), + ) + + assert len(server_calls) == 1 + assert server_calls[0]["world_rank"] == 0 + assert server_calls[0]["session_manager"] is demo.session_manager + assert server_calls[0]["app"] is demo.app + assert server_calls[0]["host"] == "0.0.0.0" + assert server_calls[0]["port"] == 8082 + assert isinstance(demo.session_manager, OmnidreamsDemoWebRTCSessionManager) + + +class _RecordingOutputTarget: + def open(self) -> None: + return None + + def write(self, result: StepResult) -> None: + del result + + def close(self) -> Sequence[OutputArtifact]: + return () + + +class _FakeOmnidreamsPipeline: + def __init__(self) -> None: + self.initialize_cache_calls: list[dict[str, Any]] = [] + self.released_encoders = False + + def initialize_cache( + self, + *, + text: list[list[str]], + image: torch.Tensor, + view_names: list[str], + ) -> object: + self.initialize_cache_calls.append( + { + "text": text, + "image_shape": tuple(image.shape), + "view_names": view_names, + } + ) + return object() + + def release_oneshot_encoders(self) -> None: + self.released_encoders = True + + def get_num_frames(self, autoregressive_index: int) -> int: + del autoregressive_index + return 1 + + def generate( + self, + *, + autoregressive_index: int, + cache: object, + hdmap: torch.Tensor, + ) -> torch.Tensor: + del cache, hdmap + return torch.full((1, 1, 1, 3, 2, 2), float(autoregressive_index)) + + def finalize(self, *, autoregressive_index: int, cache: object) -> dict[str, float]: + del autoregressive_index, cache + return {"denoise_s": 0.25} + + +class _FakeWebRTCRuntime: + def __init__(self, config: Any) -> None: + self.config = config + + async def initialize(self) -> None: + return None + + async def reset_for_new_session(self, *args: Any, **kwargs: Any) -> None: + return None + + def peek_steady_chunk_num_frames(self) -> int: + return 1 + + def peek_next_chunk_num_frames(self) -> int: + return 1 + + async def generate_chunk( + self, + *, + segments: list[Any], + frame_times: list[float], + ) -> Any: + del segments, frame_times + return None + + async def close(self) -> None: + return None + + def send_exit_signal(self) -> None: + return None + + def wait_for_termination(self) -> None: + return None diff --git a/integrations/omnidreams/tests/test_quality_regression.py b/integrations/omnidreams/tests/test_quality_regression.py index f12dd8842..d910e43b4 100644 --- a/integrations/omnidreams/tests/test_quality_regression.py +++ b/integrations/omnidreams/tests/test_quality_regression.py @@ -17,8 +17,6 @@ from typing import Any import pytest -from omnidreams.config import OMNIDREAMS_RUNNERS - from flashdreams.infra.config import derive_config from flashdreams.quality.clip_compare import ( ClipComparisonThresholds, @@ -28,6 +26,7 @@ parse_frame_indices, read_video_rgb, ) +from omnidreams.runner_config import OMNIDREAMS_RUNNERS pytestmark = pytest.mark.ci_gpu diff --git a/integrations/omnidreams/tests/test_recipe_configs.py b/integrations/omnidreams/tests/test_recipe_configs.py index 4de5e2ac4..3cedf96b4 100644 --- a/integrations/omnidreams/tests/test_recipe_configs.py +++ b/integrations/omnidreams/tests/test_recipe_configs.py @@ -31,10 +31,9 @@ import pytest import tomli as tomllib -from omnidreams import config as config_mod -from omnidreams.config import OMNIDREAMS_RUNNERS - from flashdreams.infra.runner import RunnerConfig +from omnidreams import runner_config as runner_config_mod +from omnidreams.runner_config import OMNIDREAMS_RUNNERS pytestmark = pytest.mark.ci_cpu @@ -87,10 +86,10 @@ def test_entry_points_match_module_literals() -> None: # Resolve the entry-point target the same way importlib.metadata # would, but skip the actual ``entry_points()`` call so the test # passes even when the plugin isn't pip-installed yet. - assert module_name == "omnidreams.config", ( + assert module_name == "omnidreams.runner_config", ( f"unexpected module in entry point {slug!r}: {module_name}" ) - cfg = cast(RunnerConfig, getattr(config_mod, attr)) + cfg = cast(RunnerConfig, getattr(runner_config_mod, attr)) assert cfg.runner_name == slug, ( f"entry point {slug!r} -> {attr} resolves to " f"runner_name={cfg.runner_name!r}" diff --git a/pyproject.toml b/pyproject.toml index 49b04c628..6ec3932d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -135,6 +135,7 @@ test = [ ] lint = [ "pre-commit>=4.3.0", + "ruff>=0.16.1", "sphinx>=7.0", "ty>=0.0.39", {include-group = "test"}, diff --git a/uv.lock b/uv.lock index a077bb380..dac4e769b 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,6 @@ version = 1 revision = 3 -requires-python = ">=3.10, <3.14" +requires-python = ">=3.10, <3.13" resolution-markers = [ "python_full_version >= '3.12' and sys_platform == 'win32'", "python_full_version == '3.11.*' and sys_platform == 'win32'", @@ -65,6 +65,7 @@ lint = [ { name = "pytest", specifier = ">=8.0" }, { name = "pytest-asyncio", specifier = ">=0.23" }, { name = "pytest-manual-marker", specifier = ">=2.0" }, + { name = "ruff", specifier = ">=0.16.1" }, { name = "sphinx", specifier = ">=7.0" }, { name = "tomli", specifier = ">=2.0" }, { name = "ty", specifier = ">=0.0.39" }, @@ -131,7 +132,7 @@ dependencies = [ { name = "frozenlist" }, { name = "multidict" }, { name = "propcache" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "typing-extensions" }, { name = "yarl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } @@ -190,29 +191,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3e/61/a0c0a8f327a9c52095cdd8e312391b00d3ed64ab6c72bb5c33d8ec251cf7/aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4", size = 452771, upload-time = "2026-06-07T21:07:09.669Z" }, { url = "https://files.pythonhosted.org/packages/df/d9/ea367c75f16ac9c6cdc8febb25e8318fa21a2b1bc8d6514d4b2d890bface/aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271", size = 479873, upload-time = "2026-06-07T21:07:11.538Z" }, { url = "https://files.pythonhosted.org/packages/03/64/8d96784a7851156db8a4c6c3f6f91042fdf39fb15a4cc38c8b3c14833c45/aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847", size = 448073, upload-time = "2026-06-07T21:07:13.637Z" }, - { url = "https://files.pythonhosted.org/packages/bc/97/bd137012dd97e1649162b099135a80e1fd59aaa807b2430fc448d1029aff/aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178", size = 506882, upload-time = "2026-06-07T21:07:15.501Z" }, - { url = "https://files.pythonhosted.org/packages/ef/79/e5cc690e9d922a66887ceeaca53a8ffd5a7b0be3816142b7abc433742d89/aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf", size = 515270, upload-time = "2026-06-07T21:07:17.53Z" }, - { url = "https://files.pythonhosted.org/packages/fe/22/a73ccbf9dbd6e26dda0b24d5fd5db7da92ee3383a79f47677ffb834c5c5b/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd", size = 485841, upload-time = "2026-06-07T21:07:19.555Z" }, - { url = "https://files.pythonhosted.org/packages/3b/b9/57ed8eaf596321c2ad747bd480fb1700dbd7177c60dfc9e4c187f629662e/aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe", size = 492088, upload-time = "2026-06-07T21:07:21.581Z" }, - { url = "https://files.pythonhosted.org/packages/78/c0/5ebe5270a7c140d7c6f79dcb018640225f14d406c149e4eec04a7d82fe71/aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4", size = 501564, upload-time = "2026-06-07T21:07:23.388Z" }, - { url = "https://files.pythonhosted.org/packages/75/7f/8cdaa24fc7983865e0915153b96a9ac5bcdd3548d64c5a27d17cecccad2d/aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876", size = 751998, upload-time = "2026-06-07T21:07:25.046Z" }, - { url = "https://files.pythonhosted.org/packages/b2/f4/c4227aacfacc5cb0cc2d119b65301d177912a6842cd64e120c47af76064f/aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da", size = 510918, upload-time = "2026-06-07T21:07:27.28Z" }, - { url = "https://files.pythonhosted.org/packages/ab/01/a2d5f96cd4e74424864d30bc0a7e44d0a12dacdcfa91b5b2d1bd3dca6bf3/aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6", size = 508657, upload-time = "2026-06-07T21:07:29.252Z" }, - { url = "https://files.pythonhosted.org/packages/e8/ed/3c0fb5c500fdd8e7ebc10d1889c04384fffa1a9163eac1356088ca9da1b1/aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96", size = 1757907, upload-time = "2026-06-07T21:07:31.03Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ab/d4c924d9bd5be3050c226612413ce68cb54c70d2c31b661bfc8d9a5b6a70/aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f", size = 1737565, upload-time = "2026-06-07T21:07:33.031Z" }, - { url = "https://files.pythonhosted.org/packages/19/2a/37326821ff779084020cdc33224d20b19f42f4183a500ff92022a739eda7/aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296", size = 1799018, upload-time = "2026-06-07T21:07:35.003Z" }, - { url = "https://files.pythonhosted.org/packages/b3/4f/6e947ba73e4ce09070761c05ed3a8ceb7c21f5e46798671d8b2aac0e4626/aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa", size = 1894416, upload-time = "2026-06-07T21:07:36.956Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6e/dbf1d0625dc711fb2851f4f3c3055c39ed58bae92082d8c627dbe6013736/aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451", size = 1783881, upload-time = "2026-06-07T21:07:39.063Z" }, - { url = "https://files.pythonhosted.org/packages/44/c2/5e25098a67268ed369483ae7d1a58bd0a13d03aab860d2a0e4a6eb25b046/aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c", size = 1587572, upload-time = "2026-06-07T21:07:41.058Z" }, - { url = "https://files.pythonhosted.org/packages/2a/bd/cf9cee17e140f942a3de73e658a543aa8fbf35a5fc67a9d2538d52d77f0b/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca", size = 1722137, upload-time = "2026-06-07T21:07:43.014Z" }, - { url = "https://files.pythonhosted.org/packages/89/6d/5684f8c59045c96f81a18cefbc1fbbd79d25b88f1c622f2a5c5c08fcb632/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09", size = 1755953, upload-time = "2026-06-07T21:07:45.933Z" }, - { url = "https://files.pythonhosted.org/packages/a8/40/35caf3170f8359760740a7d9aa0fff2e344bef98e1d1186f5a0f6dec17e6/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397", size = 1766479, upload-time = "2026-06-07T21:07:48.047Z" }, - { url = "https://files.pythonhosted.org/packages/6d/a1/b0c61e7a137f0d81de49a82023a6df73c3c16d6fefb0f8e4a93d21639002/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080", size = 1580077, upload-time = "2026-06-07T21:07:50.069Z" }, - { url = "https://files.pythonhosted.org/packages/0b/41/194ea4623693009fcefebef7aef63c141754f153e9cd0d39d3b9e36c175c/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345", size = 1791688, upload-time = "2026-06-07T21:07:52.106Z" }, - { url = "https://files.pythonhosted.org/packages/ba/45/4de841f005cfe1fd63e2a2fe011262c515e2a62aa6994b15947e7d717ac9/aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588", size = 1761094, upload-time = "2026-06-07T21:07:54.113Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ae/dbce10533d3896d544d5053939ed75b7dc31a1b0973d959b1b5ae21028d6/aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780", size = 452662, upload-time = "2026-06-07T21:07:56.06Z" }, - { url = "https://files.pythonhosted.org/packages/7b/d9/0bf1a19362c32f06229da5e7ddfcec91f93474d6307f7a2d3135e9c674dc/aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a", size = 479748, upload-time = "2026-06-07T21:07:58.319Z" }, - { url = "https://files.pythonhosted.org/packages/22/0a/62e7232dc9484fbec112ceb32efb6a624cc7994ec6e2b019286f17c4e8f2/aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8", size = 447723, upload-time = "2026-06-07T21:08:00.154Z" }, ] [[package]] @@ -252,7 +230,7 @@ version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -293,7 +271,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" } wheels = [ @@ -354,20 +332,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/ac/d90df7f1e3b97fc5554cf45076df5045f1e0a6adf13899e10121229b826c/av-16.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8cf065f9d438e1921dc31fc7aa045790b58aee71736897866420d80b5450f62a", size = 40817720, upload-time = "2026-01-11T09:57:39.039Z" }, { url = "https://files.pythonhosted.org/packages/80/6f/13c3a35f9dbcebafd03fe0c4cbd075d71ac8968ec849a3cfce406c35a9d2/av-16.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a345877a9d3cc0f08e2bc4ec163ee83176864b92587afb9d08dff50f37a9a829", size = 42267396, upload-time = "2026-01-11T09:57:42.115Z" }, { url = "https://files.pythonhosted.org/packages/c8/b9/275df9607f7fb44317ccb1d4be74827185c0d410f52b6e2cd770fe209118/av-16.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:f49243b1d27c91cd8c66fdba90a674e344eb8eb917264f36117bf2b6879118fd", size = 31752045, upload-time = "2026-01-11T09:57:45.106Z" }, - { url = "https://files.pythonhosted.org/packages/75/2a/63797a4dde34283dd8054219fcb29294ba1c25d68ba8c8c8a6ae53c62c45/av-16.1.0-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:ce2a1b3d8bf619f6c47a9f28cfa7518ff75ddd516c234a4ee351037b05e6a587", size = 26916715, upload-time = "2026-01-11T09:57:47.682Z" }, - { url = "https://files.pythonhosted.org/packages/d2/c4/0b49cf730d0ae8cda925402f18ae814aef351f5772d14da72dd87ff66448/av-16.1.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:408dbe6a2573ca58a855eb8cd854112b33ea598651902c36709f5f84c991ed8e", size = 21452167, upload-time = "2026-01-11T09:57:50.606Z" }, - { url = "https://files.pythonhosted.org/packages/51/23/408806503e8d5d840975aad5699b153aaa21eb6de41ade75248a79b7a37f/av-16.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:57f657f86652a160a8a01887aaab82282f9e629abf94c780bbdbb01595d6f0f7", size = 39215659, upload-time = "2026-01-11T09:57:53.757Z" }, - { url = "https://files.pythonhosted.org/packages/c4/19/a8528d5bba592b3903f44c28dab9cc653c95fcf7393f382d2751a1d1523e/av-16.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:adbad2b355c2ee4552cac59762809d791bda90586d134a33c6f13727fb86cb3a", size = 40874970, upload-time = "2026-01-11T09:57:56.802Z" }, - { url = "https://files.pythonhosted.org/packages/e8/24/2dbcdf0e929ad56b7df078e514e7bd4ca0d45cba798aff3c8caac097d2f7/av-16.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f42e1a68ec2aebd21f7eb6895be69efa6aa27eec1670536876399725bbda4b99", size = 40530345, upload-time = "2026-01-11T09:58:00.421Z" }, - { url = "https://files.pythonhosted.org/packages/54/27/ae91b41207f34e99602d1c72ab6ffd9c51d7c67e3fbcd4e3a6c0e54f882c/av-16.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58fe47aeaef0f100c40ec8a5de9abbd37f118d3ca03829a1009cf288e9aef67c", size = 41972163, upload-time = "2026-01-11T09:58:03.756Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7a/22158fb923b2a9a00dfab0e96ef2e8a1763a94dd89e666a5858412383d46/av-16.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:565093ebc93b2f4b76782589564869dadfa83af5b852edebedd8fee746457d06", size = 31729230, upload-time = "2026-01-11T09:58:07.254Z" }, - { url = "https://files.pythonhosted.org/packages/7f/f1/878f8687d801d6c4565d57ebec08449c46f75126ebca8e0fed6986599627/av-16.1.0-cp313-cp313t-macosx_11_0_x86_64.whl", hash = "sha256:574081a24edb98343fd9f473e21ae155bf61443d4ec9d7708987fa597d6b04b2", size = 27008769, upload-time = "2026-01-11T09:58:10.266Z" }, - { url = "https://files.pythonhosted.org/packages/30/f1/bd4ce8c8b5cbf1d43e27048e436cbc9de628d48ede088a1d0a993768eb86/av-16.1.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:9ab00ea29c25ebf2ea1d1e928d7babb3532d562481c5d96c0829212b70756ad0", size = 21590588, upload-time = "2026-01-11T09:58:12.629Z" }, - { url = "https://files.pythonhosted.org/packages/1d/dd/c81f6f9209201ff0b5d5bed6da6c6e641eef52d8fbc930d738c3f4f6f75d/av-16.1.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:a84a91188c1071f238a9523fd42dbe567fb2e2607b22b779851b2ce0eac1b560", size = 40638029, upload-time = "2026-01-11T09:58:15.399Z" }, - { url = "https://files.pythonhosted.org/packages/15/4d/07edff82b78d0459a6e807e01cd280d3180ce832efc1543de80d77676722/av-16.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:c2cd0de4dd022a7225ff224fde8e7971496d700be41c50adaaa26c07bb50bf97", size = 41970776, upload-time = "2026-01-11T09:58:19.075Z" }, - { url = "https://files.pythonhosted.org/packages/da/9d/1f48b354b82fa135d388477cd1b11b81bdd4384bd6a42a60808e2ec2d66b/av-16.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0816143530624a5a93bc5494f8c6eeaf77549b9366709c2ac8566c1e9bff6df5", size = 41764751, upload-time = "2026-01-11T09:58:22.788Z" }, - { url = "https://files.pythonhosted.org/packages/2f/c7/a509801e98db35ec552dd79da7bdbcff7104044bfeb4c7d196c1ce121593/av-16.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e3a28053af29644696d0c007e897d19b1197585834660a54773e12a40b16974c", size = 43034355, upload-time = "2026-01-11T09:58:26.125Z" }, - { url = "https://files.pythonhosted.org/packages/36/8b/e5f530d9e8f640da5f5c5f681a424c65f9dd171c871cd255d8a861785a6e/av-16.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e3e67144a202b95ed299d165232533989390a9ea3119d37eccec697dc6dbb0c", size = 31947047, upload-time = "2026-01-11T09:58:31.867Z" }, ] [[package]] @@ -484,18 +448,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, - { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { 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", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, - { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, - { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, ] [[package]] @@ -561,22 +513,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, - { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, - { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, - { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, - { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, - { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, - { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, - { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, - { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, - { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, - { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, - { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, - { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, - { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, - { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, ] @@ -644,26 +580,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480, upload-time = "2025-04-15T17:38:06.7Z" }, { url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489, upload-time = "2025-04-15T17:38:10.338Z" }, { url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042, upload-time = "2025-04-15T17:38:14.239Z" }, - { url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" }, - { url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" }, - { url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" }, - { url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" }, - { url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" }, - { url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" }, - { url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" }, - { url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" }, - { url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" }, - { url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" }, - { url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" }, - { url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" }, - { url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" }, - { url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" }, - { url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" }, - { url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" }, - { url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" }, - { url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" }, - { url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" }, - { url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" }, { url = "https://files.pythonhosted.org/packages/33/05/b26e3c6ecc05f349ee0013f0bb850a761016d89cec528a98193a48c34033/contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c", size = 265681, upload-time = "2025-04-15T17:44:59.314Z" }, { url = "https://files.pythonhosted.org/packages/2b/25/ac07d6ad12affa7d1ffed11b77417d0a6308170f44ff20fa1d5aa6333f03/contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16", size = 315101, upload-time = "2025-04-15T17:45:04.165Z" }, { url = "https://files.pythonhosted.org/packages/8f/4d/5bb3192bbe9d3f27e3061a6a8e7733c9120e203cb8515767d30973f71030/contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad", size = 220599, upload-time = "2025-04-15T17:45:08.456Z" }, @@ -709,28 +625,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, - { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, - { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, - { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, - { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, - { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, - { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, - { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, - { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, - { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, - { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, - { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, - { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, - { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, - { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, - { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, - { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, - { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, - { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, - { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, - { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, @@ -804,12 +698,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/45/557d4ed1fa54f0c7db8aee083229f624990d69f7d00f55477eed5c7e169a/cuda_bindings-12.9.7-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0666d3c082ef8f4b2d670950589373550e9f3bf564d635dd883f24a0b40402ff", size = 7071026, upload-time = "2026-05-27T18:44:13.356Z" }, { url = "https://files.pythonhosted.org/packages/91/97/e3c6e58ece26a053419ba0a18444b5443cfc64451bbf37f84e8143b8bdca/cuda_bindings-12.9.7-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c7ef48c5e13ae90f3b2ecfb72f8e99ac43c8f4c43e67e1325b8aae331453687", size = 7611059, upload-time = "2026-05-27T18:44:15.252Z" }, { url = "https://files.pythonhosted.org/packages/6d/39/afaa3de4d491a55af8961081e0b69c08d51bfbe471c359a7bddb4a28ca41/cuda_bindings-12.9.7-cp312-cp312-win_amd64.whl", hash = "sha256:3c089aaf4f5f570ec50244c68f5a2b00a2c9a8e01e04219fd2e36e340be0d88b", size = 7400841, upload-time = "2026-05-27T18:44:17.164Z" }, - { url = "https://files.pythonhosted.org/packages/eb/7b/f1575e41e1a17dc2f2a408b2e8e864c9324e41e3e23f6401e5efc54c152a/cuda_bindings-12.9.7-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:266379e4942051f544a8e7ea1a30ead8d7e8199b6b30fcdc8917cae2bf614e61", size = 6978549, upload-time = "2026-05-27T18:44:18.839Z" }, - { url = "https://files.pythonhosted.org/packages/9d/dc/62d62eb4f91eb721bcf46da51b13e9872ccd8fa7e60eb8ba7b7baeac72c6/cuda_bindings-12.9.7-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59cf4a37b0d662ba15037c9ceebe1a306ebf2c01a8235a09be13cd07094fdb74", size = 7457675, upload-time = "2026-05-27T18:44:20.637Z" }, - { url = "https://files.pythonhosted.org/packages/43/b2/753fe88151001d0dc23f56a8e119fe06b991b0d1a885fa02f9852b12f523/cuda_bindings-12.9.7-cp313-cp313-win_amd64.whl", hash = "sha256:5bd89dcb78475a6d8a4620ea94b74edf0cbbeacee6d1622d8f94452c1e8d3f15", size = 7360097, upload-time = "2026-05-27T18:44:22.405Z" }, - { url = "https://files.pythonhosted.org/packages/f9/77/94d9b85f26add6fe9c9cb7c4ec3b96bc598f7ea5cfbd7490cc0a36adf5be/cuda_bindings-12.9.7-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2dbcd4801954eb3508f4dc2fa0d0c8eb93eb3f45326fd61be2731418c371e7a0", size = 6870886, upload-time = "2026-05-27T18:44:24.164Z" }, - { url = "https://files.pythonhosted.org/packages/04/dd/3ec34b569e1b990b11276feba306bf8f446656cc38e8ed0f49b5facfeffa/cuda_bindings-12.9.7-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3747ea132642416786a8e31bf229032df3a7856911ae5426a7be53d032df183d", size = 7345663, upload-time = "2026-05-27T18:44:26.333Z" }, - { url = "https://files.pythonhosted.org/packages/b8/c8/d79a20ba396e7ab2dfdd4b72b62356972b25b88aee2ded49a70c797ddea1/cuda_bindings-12.9.7-cp313-cp313t-win_amd64.whl", hash = "sha256:64f7ade7a7a3b69001489753acc21706d9dbda32db8deb68a767a0a0aab30b68", size = 7780136, upload-time = "2026-05-27T18:44:28.121Z" }, ] [[package]] @@ -834,9 +722,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/67/5e7dba1ba576dd73da5dee894ca076ca5e959450dfff66d6d510a255d1f7/cuda_bindings-13.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7855c4868aabc0cfae28abbe83d56734bdfbd08f08fc234ac1912a12858bf49", size = 6025351, upload-time = "2026-05-29T23:11:49.685Z" }, { url = "https://files.pythonhosted.org/packages/39/2a/6d2e9047d1fb243dbaa364b01e0297534b9ed7fd27dba1c9f361519cf69b/cuda_bindings-13.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e32d08f71ebcdf00f0f41eab2eb37e8da94c8ed411cc9f7f7a019ce6b34abe3a", size = 6657965, upload-time = "2026-05-29T23:11:52.227Z" }, { url = "https://files.pythonhosted.org/packages/7c/95/872a0392122f1fb43fcb06869790ef3171f37beee9f7db8f441739113570/cuda_bindings-13.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:b134dd8c5c66ae4c4ad814f7aee88fd215353c077010cbc47e3b55ed35ec9eff", size = 5875099, upload-time = "2026-05-29T23:11:54.635Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6e/2394f8163360f8391f8f1b7e72d300a82724edb81a7b7084c799fbd4c91f/cuda_bindings-13.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9efb21c1ee64981e184b9e0ba5eb3179e5ba3d4b51665a6cb52b8ef3d01a7cbf", size = 5920504, upload-time = "2026-05-29T23:11:56.883Z" }, - { url = "https://files.pythonhosted.org/packages/34/c2/ef9b6a63f7dc432712a462c816662e662e00d38caa9b861c8c2588195d03/cuda_bindings-13.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2732904099e0a4d4db774a5fc6d91ee95fae065b4d2ecabb4968c5fe2406c9d7", size = 6476660, upload-time = "2026-05-29T23:11:59.188Z" }, - { url = "https://files.pythonhosted.org/packages/0c/2f/6a0dd496550c6fafbf6aeb1bf40242eeabb2fd138a43892aabb4be8224c2/cuda_bindings-13.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:18c8c167c8907b8f02531ca810534315c458dabef31f7965095619bf647b9202", size = 5830027, upload-time = "2026-05-29T23:12:01.205Z" }, ] [[package]] @@ -1087,6 +972,7 @@ dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, { name = "nvidia-ml-py" }, + { name = "pydantic" }, { name = "safetensors" }, { name = "torch", version = "2.11.0+cu128", source = { registry = "https://download.pytorch.org/whl/cu128" }, marker = "(sys_platform != 'win32' and extra == 'group-11-flashdreams-cuda12') or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, { name = "torch", version = "2.12.1", source = { registry = "https://pypi.org/simple" }, marker = "(sys_platform != 'win32' and extra == 'extra-11-flashdreams-dev') or (sys_platform != 'win32' and extra != 'group-11-flashdreams-cuda12') or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, @@ -1161,6 +1047,7 @@ requires-dist = [ { name = "nvidia-vfx", marker = "extra == 'rtx-postprocess'", specifier = "==0.1.0.1" }, { name = "opencv-python-headless", marker = "extra == 'examples'", specifier = ">=4.5" }, { name = "opencv-python-headless", marker = "extra == 'runners'", specifier = ">=4.5" }, + { name = "pydantic", specifier = ">=2,<3" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" }, { name = "pytest-manual-marker", marker = "extra == 'dev'", specifier = ">=2.0" }, { name = "safetensors", specifier = ">=0.4" }, @@ -1574,13 +1461,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/72/8f5d083ef3ea86263a49296a4247343b111077b479d172b66f1d2971cd28/flip_evaluator-1.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db5bd82d93c5be24e10134138cb54942fdce93fe771412a8b389e29e378cb59e", size = 906634, upload-time = "2025-11-07T15:33:16.866Z" }, { url = "https://files.pythonhosted.org/packages/53/bb/9a85a283efca7f57c6ba2c6457d299e4021984315e2ecf5a0d5fb13cc106/flip_evaluator-1.7-cp312-cp312-win32.whl", hash = "sha256:8a734f77b2f820110e67c78ad103cf62888cf26d9602e5fc0469551d9b81f0b8", size = 188882, upload-time = "2025-11-07T15:33:18.406Z" }, { url = "https://files.pythonhosted.org/packages/95/a6/fe3e220fc50783682662cc5fd9d1f86a4e9ee47d229c3079915bc226d0c9/flip_evaluator-1.7-cp312-cp312-win_amd64.whl", hash = "sha256:dc685bfc5acaab99adeb878b261c819637b2a0638bb7cbcffe9eb6a3d988c52b", size = 214363, upload-time = "2025-11-07T15:33:19.424Z" }, - { url = "https://files.pythonhosted.org/packages/25/86/e328522798cd53908ee875b69a3272306cc6229377fb2f70517fcc6820d9/flip_evaluator-1.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:76e689402877598b5f4a42d57d7109a4339381cd104317f361cefb103d0851b3", size = 189925, upload-time = "2025-11-07T15:33:20.51Z" }, - { url = "https://files.pythonhosted.org/packages/b2/bf/6d62779ed195adfda082f3cd7a91ebbe3a1cc9c1e936f6fd26283a248bdb/flip_evaluator-1.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f37f778e02f15607450f11f6d1b21a9b8c6817415cdc3441c3a7c55c33b5664", size = 444745, upload-time = "2025-11-07T15:33:21.498Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ed/fc88540c25b08aba2458835c26c8db54c6ea9c1dee058734492efe96eb1e/flip_evaluator-1.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63eff9eaf9a68a6f9c30a3714c8a1a83fb6182f18df2fbc9bc361634a6691f7", size = 415164, upload-time = "2025-11-07T15:33:22.531Z" }, - { url = "https://files.pythonhosted.org/packages/3b/4d/18923dc2e5262d2e34cc09aa51d3d2b977855922afc8ce333df2a10e9fc8/flip_evaluator-1.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1308484dfd89a90fef4d87db7ba26c18fbb4f7df36c7ed20c9369e1cb5b19689", size = 976486, upload-time = "2025-11-07T15:33:25.133Z" }, - { url = "https://files.pythonhosted.org/packages/9d/27/f552b286648c40bb5820b19c4a8200965abace4e17554ce098b33d7e4f28/flip_evaluator-1.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8fc68d919692ba147c6a3c6f8b2c41aa7d8aa578cad6ee86884019d90c99df66", size = 906636, upload-time = "2025-11-07T15:33:26.217Z" }, - { url = "https://files.pythonhosted.org/packages/da/e8/e8b84c26cabcfe939c9909b5414090506496015f3e5937fade4557467011/flip_evaluator-1.7-cp313-cp313-win32.whl", hash = "sha256:3735232d08f6128ff743e8405bf6c7666efbee6e0a6ee1b5e2f5aa0b64f9b090", size = 188882, upload-time = "2025-11-07T15:33:27.33Z" }, - { url = "https://files.pythonhosted.org/packages/b0/00/820a81e5d047298a622ca0538fede02b6ff09fbe85ad4bfa82649a92d919/flip_evaluator-1.7-cp313-cp313-win_amd64.whl", hash = "sha256:2081f715ea8190a5f58bc578b0cccd36a9a3f3cf78ad13fe6f86e5a75615bda7", size = 214374, upload-time = "2025-11-07T15:33:28.226Z" }, ] [[package]] @@ -1613,14 +1493,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f2/00/3bbab338c07c71fa56269953845e92c951a61457bbbb0f1022551ea266d9/fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78", size = 5133598, upload-time = "2026-05-14T12:03:25.168Z" }, { url = "https://files.pythonhosted.org/packages/62/f2/aa27c7f98db5b064883dadcc5283947e81e034de42e22a33675878d98b54/fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263", size = 2292575, upload-time = "2026-05-14T12:03:27.496Z" }, { url = "https://files.pythonhosted.org/packages/87/36/cccb9bc2a6ab63d1b2980374f0dca72ce95ae267c9b4cfe77455bb70d0d4/fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272", size = 2343211, upload-time = "2026-05-14T12:03:30.057Z" }, - { url = "https://files.pythonhosted.org/packages/0f/8d/d8fec3dcde2963f8c908fb315e5ff2cd0ac34f82394bbbf73a2aa5145ce3/fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd", size = 2876062, upload-time = "2026-05-14T12:03:32.554Z" }, - { url = "https://files.pythonhosted.org/packages/ef/71/d935dc54e4ff121bfdd11e08702db63a7e6f25af21d8a3d7b7212df53641/fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59", size = 2424594, upload-time = "2026-05-14T12:03:34.86Z" }, - { url = "https://files.pythonhosted.org/packages/8e/40/e76320afa1df918e146155ef239b1719ee266092e96f5423bfd075affba1/fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d", size = 5024840, upload-time = "2026-05-14T12:03:36.745Z" }, - { url = "https://files.pythonhosted.org/packages/ce/36/0b805d8c485f872f65a509cbe3b58a5d0d17bee855333b54a150c79d3061/fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68", size = 4975801, upload-time = "2026-05-14T12:03:38.833Z" }, - { url = "https://files.pythonhosted.org/packages/c8/26/2cee03d0aa083ab022da5c07aff9ed3f689da1defb81ad6917c9627896da/fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be", size = 4965009, upload-time = "2026-05-14T12:03:41.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/48/cc4b66d9058c0d0982c833fad10127c4b0e9324606aafa41382295ca4102/fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27", size = 5105892, upload-time = "2026-05-14T12:03:43.525Z" }, - { url = "https://files.pythonhosted.org/packages/d8/1f/a98a30a814b9ddef3a2e706025f90b9e0bc94890e6cb15254bc86547d11a/fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380", size = 2291313, upload-time = "2026-05-14T12:03:45.594Z" }, - { url = "https://files.pythonhosted.org/packages/92/46/5177b01f3b4abfdd4409f31cca4ab279c9343a26efbe9ec78c97fc612e02/fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b", size = 2342299, upload-time = "2026-05-14T12:03:47.414Z" }, { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" }, ] @@ -1678,38 +1550,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, - { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, - { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, - { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, - { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, - { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, - { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, - { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, - { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, - { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, - { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, - { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, - { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, - { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, - { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, - { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, - { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, - { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, - { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, - { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, - { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, - { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, - { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, - { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, ] @@ -1755,11 +1595,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/a9/a780cc66f86335a6019f557a8aaca8fbb970728f0efd2430d15ff1beae0e/google_crc32c-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14f87e04d613dfa218d6135e81b78272c3b904e2a7053b841481b38a7d901411", size = 33364, upload-time = "2025-12-16T00:40:22.96Z" }, { url = "https://files.pythonhosted.org/packages/21/3f/3457ea803db0198c9aaca2dd373750972ce28a26f00544b6b85088811939/google_crc32c-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb5c869c2923d56cb0c8e6bcdd73c009c36ae39b652dbe46a05eb4ef0ad01454", size = 33740, upload-time = "2025-12-16T00:40:23.96Z" }, { url = "https://files.pythonhosted.org/packages/df/c0/87c2073e0c72515bb8733d4eef7b21548e8d189f094b5dad20b0ecaf64f6/google_crc32c-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:3cc0c8912038065eafa603b238abf252e204accab2a704c63b9e14837a854962", size = 34437, upload-time = "2025-12-16T00:35:21.395Z" }, - { url = "https://files.pythonhosted.org/packages/d1/db/000f15b41724589b0e7bc24bc7a8967898d8d3bc8caf64c513d91ef1f6c0/google_crc32c-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:3ebb04528e83b2634857f43f9bb8ef5b2bbe7f10f140daeb01b58f972d04736b", size = 31297, upload-time = "2025-12-16T00:23:20.709Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0d/8ebed0c39c53a7e838e2a486da8abb0e52de135f1b376ae2f0b160eb4c1a/google_crc32c-1.8.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:450dc98429d3e33ed2926fc99ee81001928d63460f8538f21a5d6060912a8e27", size = 30867, upload-time = "2025-12-16T00:43:14.628Z" }, - { url = "https://files.pythonhosted.org/packages/ce/42/b468aec74a0354b34c8cbf748db20d6e350a68a2b0912e128cabee49806c/google_crc32c-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3b9776774b24ba76831609ffbabce8cdf6fa2bd5e9df37b594221c7e333a81fa", size = 33344, upload-time = "2025-12-16T00:40:24.742Z" }, - { url = "https://files.pythonhosted.org/packages/1c/e8/b33784d6fc77fb5062a8a7854e43e1e618b87d5ddf610a88025e4de6226e/google_crc32c-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:89c17d53d75562edfff86679244830599ee0a48efc216200691de8b02ab6b2b8", size = 33694, upload-time = "2025-12-16T00:40:25.505Z" }, - { url = "https://files.pythonhosted.org/packages/92/b1/d3cbd4d988afb3d8e4db94ca953df429ed6db7282ed0e700d25e6c7bfc8d/google_crc32c-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:57a50a9035b75643996fbf224d6661e386c7162d1dfdab9bc4ca790947d1007f", size = 34435, upload-time = "2025-12-16T00:35:22.107Z" }, { url = "https://files.pythonhosted.org/packages/52/c5/c171e4d8c44fec1422d801a6d2e5d7ddabd733eeda505c79730ee9607f07/google_crc32c-1.8.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:87fa445064e7db928226b2e6f0d5304ab4cd0339e664a4e9a25029f384d9bb93", size = 28615, upload-time = "2025-12-16T00:40:29.298Z" }, { url = "https://files.pythonhosted.org/packages/9c/97/7d75fe37a7a6ed171a2cf17117177e7aab7e6e0d115858741b41e9dd4254/google_crc32c-1.8.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f639065ea2042d5c034bf258a9f085eaa7af0cd250667c0635a3118e8f92c69c", size = 28800, upload-time = "2025-12-16T00:40:30.322Z" }, ] @@ -1803,16 +1638,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/25/7a/71437c7f3596e5246155c515852795a85a1a8d228190212432b13b97a95d/grpcio-1.81.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8ea1936c26b99999b27479853039a7f34713f56c49375ad52b38535ec93a796c", size = 7849660, upload-time = "2026-06-11T12:45:40.627Z" }, { url = "https://files.pythonhosted.org/packages/65/40/7debc0da45d2efebafb82da75644be347497fe4ee250514b8cd3b86ae8bf/grpcio-1.81.1-cp312-cp312-win32.whl", hash = "sha256:a185a04039df6cae8648bc8ab6d6fde7bf94f7188ecf7828e76ac52eef1e41d6", size = 4185819, upload-time = "2026-06-11T12:45:43.027Z" }, { url = "https://files.pythonhosted.org/packages/2e/b9/8fe3ba5ed462067774ebc1f9c7f26aa7ebcc280ddd476be107153de1339e/grpcio-1.81.1-cp312-cp312-win_amd64.whl", hash = "sha256:3ad74f8bb1a18963914c5452d289422830b39459e8776ebbcd207be1fbfb1d94", size = 4930461, upload-time = "2026-06-11T12:45:45.775Z" }, - { url = "https://files.pythonhosted.org/packages/7a/42/dcc2e4b600538ef18327c0839d56b7d3c3812337c5d710df5877dbb39b1e/grpcio-1.81.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:b10e1ff4756ed27d5a29d7fc79cfce7ef1ff56ad20025b89bac7cf79e09abbbe", size = 6054466, upload-time = "2026-06-11T12:45:48.43Z" }, - { url = "https://files.pythonhosted.org/packages/7b/4a/a36e03210183a8a7d4c80c3936acee679f4bd77d5861f369db47b2cc5f05/grpcio-1.81.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:819edbdcb42ab8598b494bcf0222684bbb7a3c772bd1b1f0be7e029a6063c28e", size = 12048795, upload-time = "2026-06-11T12:45:54.011Z" }, - { url = "https://files.pythonhosted.org/packages/b0/d5/d68e30b29098f63beab6fe501100fe82674ff142b32c672532da86a99b3a/grpcio-1.81.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c5bf2dc311127d91230cc79b92188c082634a06cf66c5234db49a43b910183b0", size = 6599094, upload-time = "2026-06-11T12:45:57.799Z" }, - { url = "https://files.pythonhosted.org/packages/3d/b3/e837954d279754f638a11cca5dcf6b24a005efb398984cefaf7735945a54/grpcio-1.81.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e8ca6a1fcdb2943c9cbc1804a1baf3acb6071d72a471591678ded84218006e14", size = 7307182, upload-time = "2026-06-11T12:46:00.568Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1e/b47957057e729adc6cdf519a47f8be2562b7140e280f1418443eb4022192/grpcio-1.81.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e64dd101d380a115cc5a0c7856788adb535f1a4e21fc543775602f8be95180ae", size = 6810962, upload-time = "2026-06-11T12:46:03.312Z" }, - { url = "https://files.pythonhosted.org/packages/40/26/569868e364e05b19ec8f969da53d230bcd89c962cd198f7c29943155c4d3/grpcio-1.81.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:98a07f9bf591e3a8919797bee1c53f026ba4acd587e5a4404c8e57c9ec36b2a5", size = 7415698, upload-time = "2026-06-11T12:46:06.005Z" }, - { url = "https://files.pythonhosted.org/packages/36/0c/5440a0582cb5653fc42a6e262eeb22700943313f8076f9dc927491b20a59/grpcio-1.81.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c261d74b1a945cf895a9d6eccd1685a8e837531beaab782da4d630a8d12deffb", size = 8407779, upload-time = "2026-06-11T12:46:08.84Z" }, - { url = "https://files.pythonhosted.org/packages/ff/aa/66fe9f39871d766987d869a03ee0842a026f499c7b1e62decb9e78a8088e/grpcio-1.81.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58ad1131c300d3c9b933802b3cc4dc69d380822935ba50b28703156ea826fbf7", size = 7844521, upload-time = "2026-06-11T12:46:12.171Z" }, - { url = "https://files.pythonhosted.org/packages/f0/9e/69bb7194861bcd28fb3193261d4f9c3831b4446993f002cf59068943e7ab/grpcio-1.81.1-cp313-cp313-win32.whl", hash = "sha256:78e29211f26da2fdd0e9c6d2b79f489476140cf7029b6a64808ade7ca4156a42", size = 4182786, upload-time = "2026-06-11T12:46:15.192Z" }, - { url = "https://files.pythonhosted.org/packages/0d/20/3da8bb0d637feccdc3e1e419bb511ce93651ce7d54164f95de22cc0b8b34/grpcio-1.81.1-cp313-cp313-win_amd64.whl", hash = "sha256:edb59506291b647a30884b1d51a599d605f40b20af4a7dc3d33786a47a31de60", size = 4928648, upload-time = "2026-06-11T12:46:17.823Z" }, ] [[package]] @@ -1856,16 +1681,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b5/67baeba7366162652cdc1dbd962289accde07241bc8f42f6f02b305efcc6/grpcio_tools-1.81.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:724ecb69af63d2f6d4ccea3e6fa0ca110ed9c5824d48c2f887c631bbb03c1c3c", size = 3370797, upload-time = "2026-06-11T12:50:21.501Z" }, { url = "https://files.pythonhosted.org/packages/f2/5d/34f2dce2125ccb107e32b57f5a9c1257edcc0793b0d2fef1e8b13a6bac3c/grpcio_tools-1.81.1-cp312-cp312-win32.whl", hash = "sha256:895a6782cec86beac71ccebb4b9848259c6f04a3028b8e42fa8d40cfe5146593", size = 1008453, upload-time = "2026-06-11T12:50:23.358Z" }, { url = "https://files.pythonhosted.org/packages/8a/be/09da8256ec8d2a5ce8a1acc51cbbc4ca52a462d78ed3412778440a56502e/grpcio_tools-1.81.1-cp312-cp312-win_amd64.whl", hash = "sha256:0265fd1386b7458302f79542558345880d484f8fa92ae196c0c0268242c5f23a", size = 1174857, upload-time = "2026-06-11T12:50:25.685Z" }, - { url = "https://files.pythonhosted.org/packages/76/90/5faa8b26e03495e5117f93bef8293cbada4af136362745dad7d1813ef0b0/grpcio_tools-1.81.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:3d604b4fd114b79ebb9f865bf3e04fd3ae93c704e1fad96f7fd03b0865c263b7", size = 2586071, upload-time = "2026-06-11T12:50:28.4Z" }, - { url = "https://files.pythonhosted.org/packages/e8/9a/85dc589fa6ae2439451eaa81a1578de31e29c676980d38bef7549b8a1f45/grpcio_tools-1.81.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:3389e705460efa3f3758141ba5520e6743b131c9576197c944fb9cbe49048126", size = 5813299, upload-time = "2026-06-11T12:50:31.295Z" }, - { url = "https://files.pythonhosted.org/packages/77/fd/c53994e58a837e6eefe48f53eb3492afc04f2b8af255df4adb37d14378f8/grpcio_tools-1.81.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8a17d8ceeb6a855fadf39f5171c80a382d97c4db98d5943eca553497fdebf84b", size = 2634668, upload-time = "2026-06-11T12:50:33.938Z" }, - { url = "https://files.pythonhosted.org/packages/34/32/de988e86688686a2117e7ce6ce9eff4f638c929bb55b0afe60d6fbd2e45c/grpcio_tools-1.81.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:43baf71dc60fd653062da2e95e95c73b35dd130be8f9fa3d544c3af3f808a290", size = 2957930, upload-time = "2026-06-11T12:50:36.726Z" }, - { url = "https://files.pythonhosted.org/packages/72/97/3f18a0ea32b5f809d21961dbd0bc382b589a4c3d501e3d67c345d5456ed3/grpcio_tools-1.81.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:136e90906af0df51ad929713244ba812d0dbb1844b4f467d5d86bdb054698f90", size = 2697760, upload-time = "2026-06-11T12:50:39.108Z" }, - { url = "https://files.pythonhosted.org/packages/49/c0/dbf5cbc877290ff7504a59959a8af4fdcfdaa1e84237948405ccf1aa82a6/grpcio_tools-1.81.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd6c3bf3ea6a61eb58c54368d72ada591f2a270f3a31a32e8536e773337e76d9", size = 3151456, upload-time = "2026-06-11T12:50:41.983Z" }, - { url = "https://files.pythonhosted.org/packages/de/ea/16fe2dc83140a59e5c0a0b9dc2693dd36bfaa6bd835724b4ec66a68eab7b/grpcio_tools-1.81.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c306c307f8f74cddc4056fdbb6f1da55de087a21120efbd02bd915daa5a52fd", size = 3710469, upload-time = "2026-06-11T12:50:44.596Z" }, - { url = "https://files.pythonhosted.org/packages/22/7d/df987d7d81e7ad2f7516d9e9d56ff29c54dbc6d8587e425688dca9a28e49/grpcio_tools-1.81.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bdbdc927be2e0ea13c32564a72ee31d712a716fb6f8c0d53d37a77d8277c272c", size = 3370488, upload-time = "2026-06-11T12:50:47.199Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c5/5a63444d694ea47bf670138208f71830cc1759c402c8818092b28ab2dc5f/grpcio_tools-1.81.1-cp313-cp313-win32.whl", hash = "sha256:9d383724bcd67244b6def9e9164c640ee9380c0b7534ee7545a6fb0022a59afe", size = 1008229, upload-time = "2026-06-11T12:50:49.527Z" }, - { url = "https://files.pythonhosted.org/packages/00/75/3945e26d5c94ae6ed9be5caef73d4d66c47dc8cfdd7b4995efaf942754e0/grpcio_tools-1.81.1-cp313-cp313-win_amd64.whl", hash = "sha256:f3eb15849979ca7bb864ce81a74d68b0f225a7f111ed3fe212bfc08cf9812b10", size = 1174523, upload-time = "2026-06-11T12:50:51.755Z" }, ] [[package]] @@ -1883,14 +1698,6 @@ version = "1.5.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/4b/2d/57fd21d84d93efb4bd0b962383790e19dd1bc053501b4264c97903b4e83e/hf_xet-1.5.1.tar.gz", hash = "sha256:51ef4500dab3764b41135ee1381a4b62ce56fc54d4c92b719b59e597d6df5bf6", size = 876636, upload-time = "2026-06-08T23:02:53.897Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/ee/dd9ba7beae1005e54131b7d45263cc74c8a066d47d354e6d58ae9445a388/hf_xet-1.5.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:dbf48c0d02cf0b2e568944330c60d9120c272dabe013bd892d48e25bc6797577", size = 4069485, upload-time = "2026-06-08T23:02:13.193Z" }, - { url = "https://files.pythonhosted.org/packages/b6/bc/9cae6cfeb4e03070874e73e5c97c66eb90369d3206b6a2b1ef5f96520888/hf_xet-1.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78e4e5192ad2b674c2e1160b651cb9134db974f8ae1835bdfbfb0166b894a43", size = 3838493, upload-time = "2026-06-08T23:02:15.282Z" }, - { url = "https://files.pythonhosted.org/packages/ba/b4/d5c01e0eb6d9f2ca2dacd84d0d1b71e6cfbb2ef3208c968528e010e9b3d7/hf_xet-1.5.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6f7a04a8ad962422e225bc49fbbac99dc1806764b1f3e54dbd154bffa7593947", size = 4505658, upload-time = "2026-06-08T23:02:17.196Z" }, - { url = "https://files.pythonhosted.org/packages/76/c5/29a7598c0c6383c523dc22186d577f4e04267a626cd95ae60f67c00bfe66/hf_xet-1.5.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:d48199c2bf4f8df0adc55d31d1368b6ec0e4d4f45bc86b08038089c23db0bed8", size = 4292822, upload-time = "2026-06-08T23:02:18.608Z" }, - { url = "https://files.pythonhosted.org/packages/04/9a/dceaf6ca69390126b86ea825fb354b93d01163199070b7bd849225de9468/hf_xet-1.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:97f212a88d14bbf573619a74b7fecb238de77d08fc702e54dec6f78276ca3283", size = 4491255, upload-time = "2026-06-08T23:02:20.124Z" }, - { url = "https://files.pythonhosted.org/packages/48/a7/e5a7afaacf6c1791fdbeeac42951fb81c3d2bc482992b115dedcc86d963e/hf_xet-1.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f61e3665892a6c8c5e765395838b8ddf36185da835253d4bc4509a81e49fb342", size = 4711062, upload-time = "2026-06-08T23:02:21.863Z" }, - { url = "https://files.pythonhosted.org/packages/53/49/2802f8433c9742ce281bddc1e65c02c32268ca3098d66828b05e12e45ee2/hf_xet-1.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f4ad3ebd4c32dd2b27099d69dc7b2df821e30767e46fb6ee6a0713778243b8ff", size = 4017205, upload-time = "2026-06-08T23:02:23.495Z" }, - { url = "https://files.pythonhosted.org/packages/9e/5a/50c71195b9fb883659f596e7252faf4c18c58e753a9013bdbf9bac5d2250/hf_xet-1.5.1-cp313-cp313t-win_arm64.whl", hash = "sha256:8298485c1e36e7e67cbd01eeb1376619b7af43d4f1ec245caae306f890a8a32d", size = 3845426, upload-time = "2026-06-08T23:02:25.124Z" }, { url = "https://files.pythonhosted.org/packages/7a/d8/5e54cf37434759d1f4f2ba9b66077ff9d4c4e1f37b6bd7975da5c40d94ab/hf_xet-1.5.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6abd35c3221eff63836618ddfb954dcf84798603f71d8e33e3ed7b04acfdbe6e", size = 4077794, upload-time = "2026-06-08T23:02:40.656Z" }, { url = "https://files.pythonhosted.org/packages/35/94/4b2ecfbad8f8b04701a23aefb62f540b9137d058b7e1dbef16a32676f0e9/hf_xet-1.5.1-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:94e761bbd266bf4c03cee73753916062665ce8365aa40ed321f45afcb934b41e", size = 3845354, upload-time = "2026-06-08T23:02:42.702Z" }, { url = "https://files.pythonhosted.org/packages/de/cc/f99f4bc7295023d7bd9ebbfd51f75cc530ca262c1227666268b8208f4b77/hf_xet-1.5.1-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:892e3a3a3aecc12aded8b93cf4f9cd059282c7de0732f7d55026f3abdf474350", size = 4514864, upload-time = "2026-06-08T23:02:44.497Z" }, @@ -2189,35 +1996,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947, upload-time = "2026-03-09T13:13:43.343Z" }, { url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384", size = 73569, upload-time = "2026-03-09T13:13:45.792Z" }, { url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7", size = 64997, upload-time = "2026-03-09T13:13:46.878Z" }, - { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166, upload-time = "2026-03-09T13:13:48.032Z" }, - { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395, upload-time = "2026-03-09T13:13:49.365Z" }, - { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065, upload-time = "2026-03-09T13:13:50.562Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903, upload-time = "2026-03-09T13:13:52.084Z" }, - { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751, upload-time = "2026-03-09T13:13:54.673Z" }, - { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793, upload-time = "2026-03-09T13:13:56.287Z" }, - { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041, upload-time = "2026-03-09T13:13:58.269Z" }, - { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292, upload-time = "2026-03-09T13:13:59.871Z" }, - { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865, upload-time = "2026-03-09T13:14:01.401Z" }, - { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369, upload-time = "2026-03-09T13:14:02.972Z" }, - { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989, upload-time = "2026-03-09T13:14:04.503Z" }, - { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645, upload-time = "2026-03-09T13:14:06.106Z" }, - { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237, upload-time = "2026-03-09T13:14:08.891Z" }, - { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573, upload-time = "2026-03-09T13:14:12.327Z" }, - { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998, upload-time = "2026-03-09T13:14:13.469Z" }, - { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700, upload-time = "2026-03-09T13:14:14.636Z" }, - { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537, upload-time = "2026-03-09T13:14:15.808Z" }, - { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514, upload-time = "2026-03-09T13:14:18.035Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848, upload-time = "2026-03-09T13:14:19.745Z" }, - { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542, upload-time = "2026-03-09T13:14:21.54Z" }, - { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447, upload-time = "2026-03-09T13:14:23.205Z" }, - { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918, upload-time = "2026-03-09T13:14:24.74Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856, upload-time = "2026-03-09T13:14:26.597Z" }, - { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580, upload-time = "2026-03-09T13:14:28.237Z" }, - { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018, upload-time = "2026-03-09T13:14:30.018Z" }, - { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804, upload-time = "2026-03-09T13:14:32.888Z" }, - { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482, upload-time = "2026-03-09T13:14:34.971Z" }, - { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328, upload-time = "2026-03-09T13:14:36.816Z" }, - { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410, upload-time = "2026-03-09T13:14:38.695Z" }, { url = "https://files.pythonhosted.org/packages/1c/fa/2910df836372d8761bb6eff7d8bdcb1613b5c2e03f260efe7abe34d388a7/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797", size = 130262, upload-time = "2026-03-09T13:15:35.629Z" }, { url = "https://files.pythonhosted.org/packages/0f/41/c5f71f9f00aabcc71fee8b7475e3f64747282580c2fe748961ba29b18385/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203", size = 138036, upload-time = "2026-03-09T13:15:36.894Z" }, { url = "https://files.pythonhosted.org/packages/fa/06/7399a607f434119c6e1fdc8ec89a8d51ccccadf3341dee4ead6bd14caaf5/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7", size = 194295, upload-time = "2026-03-09T13:15:38.22Z" }, @@ -2276,7 +2054,7 @@ dev = [ { name = "pytest" }, ] video-codec = [ - { name = "pynvvideocodec", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "pynvvideocodec" }, ] [package.metadata] @@ -2370,28 +2148,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, - { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, ] [[package]] @@ -2435,20 +2191,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/c2/541e4d09d87bb6b5830fc28b4c887a9a8cf4e1c6cee698a8c05552ae2003/matplotlib-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d75d11c949914165976c621b2324f9ef162af7ebf4b057ddf95dd1dba7e5edcf", size = 9670966, upload-time = "2026-04-24T00:12:32.131Z" }, { url = "https://files.pythonhosted.org/packages/04/a1/4571fc46e7702de8d0c2dc54ad1b2f8e29328dea3ee90831181f7353d93c/matplotlib-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6", size = 8217462, upload-time = "2026-04-24T00:12:35.226Z" }, { url = "https://files.pythonhosted.org/packages/4b/d0/2269edb12aa30c13c8bcc9382892e39943ce1d28aab4ec296e0381798e81/matplotlib-3.10.9-cp312-cp312-win_arm64.whl", hash = "sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42", size = 8136688, upload-time = "2026-04-24T00:12:37.442Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d3/8d4f6afbecb49fc04e060a57c0fce39ea51cc163a6bd87303ccd698e4fa6/matplotlib-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b580440f1ff81a0e34122051a3dfabb7e4b7f9e380629929bde0eff9af72165f", size = 8320331, upload-time = "2026-04-24T00:12:39.688Z" }, - { url = "https://files.pythonhosted.org/packages/63/d9/9e14bc7564bf92d5ffa801ae5fac819ce74b925dfb55e3ebde61a3bbad3e/matplotlib-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1b745c489cd1a77a0dc1120a05dc87af9798faebc913601feb8c73d89bf2d1e", size = 8216461, upload-time = "2026-04-24T00:12:42.494Z" }, - { url = "https://files.pythonhosted.org/packages/8a/17/4402d0d14ccf1dfc70932600b68097fbbf9c898a4871d2cbbe79c7801a32/matplotlib-3.10.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8f3bcac1ca5ed000a6f4337d47ba67dfddf37ed6a46c15fd7f014997f7bf865f", size = 8790091, upload-time = "2026-04-24T00:12:44.789Z" }, - { url = "https://files.pythonhosted.org/packages/3e/0b/322aeec06dd9b91411f92028b37d447342770a24392aa4813e317064dad5/matplotlib-3.10.9-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a8d66a55def891c33147ba3ba9bfcabf0b526a43764c818acbb4525e5ed0838", size = 9605027, upload-time = "2026-04-24T00:12:47.583Z" }, - { url = "https://files.pythonhosted.org/packages/74/88/5f13482f55e7b00bcfc09838b093c2456e1379978d2a146844aae05350ad/matplotlib-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d843374407c4017a6403b59c6c81606773d136f3259d5b6da3131bc814542cc2", size = 9671269, upload-time = "2026-04-24T00:12:50.878Z" }, - { url = "https://files.pythonhosted.org/packages/c5/e0/0840fd2f93da988ec660b8ad1984abe9f25d2aed22a5e394ff1c68c88307/matplotlib-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:f4399f64b3e94cd500195490972ae1ee81170df1636fa15364d157d5bdd7b921", size = 8217588, upload-time = "2026-04-24T00:12:53.784Z" }, - { url = "https://files.pythonhosted.org/packages/47/b9/d706d06dd605c49b9f83a2aed8c13e3e5db70697d7a80b7e3d7915de6b17/matplotlib-3.10.9-cp313-cp313-win_arm64.whl", hash = "sha256:ba7b3b8ef09eab7df0e86e9ae086faa433efbfbdb46afcb3aa16aabf779469a8", size = 8136913, upload-time = "2026-04-24T00:12:56.501Z" }, - { url = "https://files.pythonhosted.org/packages/9b/45/6e32d96978264c8ca8c4b1010adb955a1a49cfaf314e212bbc8908f04a61/matplotlib-3.10.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:09218df8a93712bd6ea133e83a153c755448cf7868316c531cffcc43f69d1cc9", size = 8368019, upload-time = "2026-04-24T00:12:58.896Z" }, - { url = "https://files.pythonhosted.org/packages/86/0a/c8e3d3bba245f0f7fc424937f8ff7ef77291a36af3edb97ccd78aa93d84f/matplotlib-3.10.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:82368699727bfb7b0182e1aa13082e3c08e092fa1a25d3e1fd92405bff96f6d4", size = 8264645, upload-time = "2026-04-24T00:13:01.406Z" }, - { url = "https://files.pythonhosted.org/packages/3d/aa/5bf5a14fe4fed73a4209a155606f8096ff797aad89c6c35179026571133e/matplotlib-3.10.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3225f4e1edcb8c86c884ddf79ebe20ecd0a67d30188f279897554ccd8fded4dc", size = 8802194, upload-time = "2026-04-24T00:13:03.702Z" }, - { url = "https://files.pythonhosted.org/packages/dd/5e/b4be852d6bba6fd15893fadf91ff26ae49cb91aac789e95dde9d342e664f/matplotlib-3.10.9-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de2445a0c6690d21b7eb6ce071cebad6d40a2e9bdf10d039074a96ba19797b99", size = 9622684, upload-time = "2026-04-24T00:13:06.647Z" }, - { url = "https://files.pythonhosted.org/packages/4c/3d/ed428c971139112ef730f62770654d609467346d09d4b62617e1afd68a5a/matplotlib-3.10.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b2b9516251cb89ff618d757daec0e2ed1bf21248013844a853d87ef85ab3081d", size = 9680790, upload-time = "2026-04-24T00:13:10.009Z" }, - { url = "https://files.pythonhosted.org/packages/e7/09/052e884aaf2b985c63cb79f715f1d5b6a3eaa7de78f6a52b9dbc077d5b53/matplotlib-3.10.9-cp313-cp313t-win_amd64.whl", hash = "sha256:e9fae004b941b23ff2edcf1567a857ed77bafc8086ffa258190462328434faf8", size = 8287571, upload-time = "2026-04-24T00:13:13.087Z" }, - { url = "https://files.pythonhosted.org/packages/f4/38/ae27288e788c35a4250491422f3db7750366fc8c97d6f36fbdecfc1f5518/matplotlib-3.10.9-cp313-cp313t-win_arm64.whl", hash = "sha256:6b63d9c7c769b88ab81e10dc86e4e0607cf56817b9f9e6cf24b2a5f1693b8e38", size = 8188292, upload-time = "2026-04-24T00:13:15.546Z" }, { url = "https://files.pythonhosted.org/packages/2c/2b/0e92ad0ac446633f928a1563db4aa8add407e1924faf0ded5b95b35afb27/matplotlib-3.10.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1872fb212a05b729e649754a72d5da61d03e0554d76e80303b6f83d1d2c0552b", size = 8293058, upload-time = "2026-04-24T00:13:56.339Z" }, { url = "https://files.pythonhosted.org/packages/4b/23/74682fd369f5299ceda438fea2a0662e6383b85c9383fb9cdfcf04713e07/matplotlib-3.10.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:985f2238880e2e69093f588f5fe2e46771747febf0649f3cf7f7b7480875317f", size = 8186627, upload-time = "2026-04-24T00:13:58.623Z" }, { url = "https://files.pythonhosted.org/packages/ca/e8/368aab88f3c4cd8992800f31abfe0670c3e47540ba20a97e9fdbcde594b3/matplotlib-3.10.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6640f75af2c6148293caa0a2b39dd806a492dd66c8a8b04035813e33d0fd2585", size = 8764117, upload-time = "2026-04-24T00:14:01.684Z" }, @@ -2494,20 +2236,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/85/c2/db15da2bbdf9e3ca66df7db8e2c33a1dfed67be24a24d2c878efaaff01d6/matplotlib-3.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94f5000f67ca9faa300863ea17f8bce9175cb67b88bec4bc7780502d53dd7c9e", size = 10923899, upload-time = "2026-06-12T02:28:00.223Z" }, { url = "https://files.pythonhosted.org/packages/e5/2f/a58a4443a4d052a4ea77557478336aefc26c7981f6408d37adba763aa758/matplotlib-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6f1ef39f3d0f9e2463303013094992cdbe0f85f43bc54155bc472b2042768e", size = 9329528, upload-time = "2026-06-12T02:28:02.27Z" }, { url = "https://files.pythonhosted.org/packages/61/0f/4b669589d47733b97ab9df4b58d6fc1e68acb5ea42a928dc7cbdd6bf5871/matplotlib-3.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:9dd11fb612ce7bc60b1de5b4fc87ff959d22317b5de42aabf392f66f97af22eb", size = 9003413, upload-time = "2026-06-12T02:28:04.49Z" }, - { url = "https://files.pythonhosted.org/packages/55/41/aa47f156b061d14c98b906f76c428507397708ec63ff94f410ae1752b426/matplotlib-3.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce3b839b34ae1f430b4616893a2945a2999debaa7e94e7e29a2a8bbf286f7b5", size = 9450532, upload-time = "2026-06-12T02:28:06.769Z" }, - { url = "https://files.pythonhosted.org/packages/8c/4f/5a9eb0375e81413953febf8af7b012a6b6357f53438a15c4f5ad86c6bbb5/matplotlib-3.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:373db8f91214e8ccaf35ac833cc1dd59dd961e148bbd55dd027141591dde1313", size = 9279760, upload-time = "2026-06-12T02:28:09.152Z" }, - { url = "https://files.pythonhosted.org/packages/a4/c0/1117d53077e3ac3152503a84e9cf7a5c239576805ee71276e80c2aaa7471/matplotlib-3.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be152b7570324dc8d01574cc9474dd2d803237acf528bcbb5b211fa347461a09", size = 10031623, upload-time = "2026-06-12T02:28:11.26Z" }, - { url = "https://files.pythonhosted.org/packages/92/7e/e937138daffad65b71bf831a377809dcbc830fb4f31a31e067dc1faa2575/matplotlib-3.11.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:126f256df600652d7e4b394cf3164ff75210a00038f287c95a012a6f58d0e83f", size = 10839372, upload-time = "2026-06-12T02:28:14.102Z" }, - { url = "https://files.pythonhosted.org/packages/1d/c2/438ecc197ffb8023b6b9922915542f2172f5fd45b76703b0b4fc47322243/matplotlib-3.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:03acfeddf87b0dddb11b081ef7740ad445a3ca8bcb6b8e3011b08f2cf802b75c", size = 10924099, upload-time = "2026-06-12T02:28:16.383Z" }, - { url = "https://files.pythonhosted.org/packages/40/2e/395883da416f378b3ed2c9f3e843ac477eae1ce731b671b79adaa6f0bacd/matplotlib-3.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:ab3722f04f3ff34c23b5012c5873d2894174e06c3822fcdac3610965a5ac7d06", size = 9329727, upload-time = "2026-06-12T02:28:18.581Z" }, - { url = "https://files.pythonhosted.org/packages/61/82/2c388956abf8bf392dfb5b8917c502f1082df6a941b781ab8c8e5ba2474b/matplotlib-3.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:c945824670fb8915b4ac879e5e61f3c58e0913022f70a0de4c082b17372f8771", size = 9003506, upload-time = "2026-06-12T02:28:20.474Z" }, - { url = "https://files.pythonhosted.org/packages/c8/c1/34454baa44da7975ada82e9aea37105ec47059514dc967d3be14426ba8dc/matplotlib-3.11.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3489c3dc487669b4a980bc3068f87856de7a1564248d3f6c629efb2a58b03f24", size = 9499838, upload-time = "2026-06-12T02:28:22.713Z" }, - { url = "https://files.pythonhosted.org/packages/b1/c3/98fe79a398cf232219f090163a7fa7e6766e9f2e0ad26df54d6f8934d8ee/matplotlib-3.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6a98f5476ce784a50ce09998f4ae1e6a9f25043cef8a480c98949902eda74620", size = 9332298, upload-time = "2026-06-12T02:28:24.796Z" }, - { url = "https://files.pythonhosted.org/packages/95/e4/b4b7c33151e74e5c802f3cde1ba807ebfc38401e329b44e215a5888dd76d/matplotlib-3.11.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:565af866fd63e4bd3f987d580afe27c44c2552a3b3305f4ecbb85133601ea6f3", size = 10045491, upload-time = "2026-06-12T02:28:27.141Z" }, - { url = "https://files.pythonhosted.org/packages/71/28/394548efd68354110c1a1be11fe6b6e559e06d1a23da35908a0e316c55a9/matplotlib-3.11.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6b3e64dea5062c570f04358e2711859f3531b459f29516274fbad889079e4f3", size = 10857059, upload-time = "2026-06-12T02:28:29.222Z" }, - { url = "https://files.pythonhosted.org/packages/c8/44/e7922e6e2a4d63bdfbc9dc4a53e3850ab438d46cf42e6779bb15ec92c948/matplotlib-3.11.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:942b37c5db1899610bd1543ce8e13e4ecff9a4633e7f63bb6aa9205d2644ebd1", size = 10939576, upload-time = "2026-06-12T02:28:31.66Z" }, - { url = "https://files.pythonhosted.org/packages/3d/be/b1ca96003a441d619b727fee21d671fdff7a5ce2f1bb797b2521aa2f679a/matplotlib-3.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c08e649a6313e1291e713623b97a38e5bb4aa580b2a100a94a3309bc6b9c8eb3", size = 9379519, upload-time = "2026-06-12T02:28:33.888Z" }, - { url = "https://files.pythonhosted.org/packages/e3/72/4bf3b91821c34596dd6a7bdac5836d94f744144c8208939ef49d8ec43f7e/matplotlib-3.11.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2746cd2c113742ff6ce37a864c5ac5fd7aa644568f445e66166e457ac78e40e0", size = 9055456, upload-time = "2026-06-12T02:28:35.878Z" }, { url = "https://files.pythonhosted.org/packages/0f/c2/f5da6cd37ed6871f5c9b3c0507ddb69f14d6c36fac4541e4e0c60cb8cdfc/matplotlib-3.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:81ae77077a1e16d37a5b61096ccb07c8d90a99b518fa8256b8f21578932f2f62", size = 9434094, upload-time = "2026-06-12T02:29:09.135Z" }, { url = "https://files.pythonhosted.org/packages/f8/07/56f66906e0f87a0c6d0d0acbd34dbc9432b1931d8f26ef618bd6f92932a9/matplotlib-3.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ddef37840695f5eef65f9f070fe2d2f510f584c2156203f9f622a5b0584efffd", size = 9262183, upload-time = "2026-06-12T02:29:11.283Z" }, { url = "https://files.pythonhosted.org/packages/0c/d8/c4ecab06b7ea36a570c4f3bd2d48d1799fd5d9174470e45c2194199431e7/matplotlib-3.11.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cf662e5ac5707658cb931e19972c4bd99f7b4f8b7bf79d3c821d239fa6b71e64", size = 10015653, upload-time = "2026-06-12T02:29:13.251Z" }, @@ -2589,16 +2317,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/cb/28ce52eb94390dda42599c98ea0204d74799e4d8047a0eb559b6fd648056/ml_dtypes-0.5.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ad459e99793fa6e13bd5b7e6792c8f9190b4e5a1b45c63aba14a4d0a7f1d5ff", size = 5009002, upload-time = "2025-11-17T22:31:52.001Z" }, { url = "https://files.pythonhosted.org/packages/f5/f0/0cfadd537c5470378b1b32bd859cf2824972174b51b873c9d95cfd7475a5/ml_dtypes-0.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:c1a953995cccb9e25a4ae19e34316671e4e2edaebe4cf538229b1fc7109087b7", size = 212222, upload-time = "2025-11-17T22:31:53.742Z" }, { url = "https://files.pythonhosted.org/packages/16/2e/9acc86985bfad8f2c2d30291b27cd2bb4c74cea08695bd540906ed744249/ml_dtypes-0.5.4-cp312-cp312-win_arm64.whl", hash = "sha256:9bad06436568442575beb2d03389aa7456c690a5b05892c471215bfd8cf39460", size = 160793, upload-time = "2025-11-17T22:31:55.358Z" }, - { url = "https://files.pythonhosted.org/packages/d9/a1/4008f14bbc616cfb1ac5b39ea485f9c63031c4634ab3f4cf72e7541f816a/ml_dtypes-0.5.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c760d85a2f82e2bed75867079188c9d18dae2ee77c25a54d60e9cc79be1bc48", size = 676888, upload-time = "2025-11-17T22:31:56.907Z" }, - { url = "https://files.pythonhosted.org/packages/d3/b7/dff378afc2b0d5a7d6cd9d3209b60474d9819d1189d347521e1688a60a53/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce756d3a10d0c4067172804c9cc276ba9cc0ff47af9078ad439b075d1abdc29b", size = 5036993, upload-time = "2025-11-17T22:31:58.497Z" }, - { url = "https://files.pythonhosted.org/packages/eb/33/40cd74219417e78b97c47802037cf2d87b91973e18bb968a7da48a96ea44/ml_dtypes-0.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:533ce891ba774eabf607172254f2e7260ba5f57bdd64030c9a4fcfbd99815d0d", size = 5010956, upload-time = "2025-11-17T22:31:59.931Z" }, - { url = "https://files.pythonhosted.org/packages/e1/8b/200088c6859d8221454825959df35b5244fa9bdf263fd0249ac5fb75e281/ml_dtypes-0.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:f21c9219ef48ca5ee78402d5cc831bd58ea27ce89beda894428bc67a52da5328", size = 212224, upload-time = "2025-11-17T22:32:01.349Z" }, - { url = "https://files.pythonhosted.org/packages/8f/75/dfc3775cb36367816e678f69a7843f6f03bd4e2bcd79941e01ea960a068e/ml_dtypes-0.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:35f29491a3e478407f7047b8a4834e4640a77d2737e0b294d049746507af5175", size = 160798, upload-time = "2025-11-17T22:32:02.864Z" }, - { url = "https://files.pythonhosted.org/packages/4f/74/e9ddb35fd1dd43b1106c20ced3f53c2e8e7fc7598c15638e9f80677f81d4/ml_dtypes-0.5.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:304ad47faa395415b9ccbcc06a0350800bc50eda70f0e45326796e27c62f18b6", size = 702083, upload-time = "2025-11-17T22:32:04.08Z" }, - { url = "https://files.pythonhosted.org/packages/74/f5/667060b0aed1aa63166b22897fdf16dca9eb704e6b4bbf86848d5a181aa7/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a0df4223b514d799b8a1629c65ddc351b3efa833ccf7f8ea0cf654a61d1e35d", size = 5354111, upload-time = "2025-11-17T22:32:05.546Z" }, - { url = "https://files.pythonhosted.org/packages/40/49/0f8c498a28c0efa5f5c95a9e374c83ec1385ca41d0e85e7cf40e5d519a21/ml_dtypes-0.5.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531eff30e4d368cb6255bc2328d070e35836aa4f282a0fb5f3a0cd7260257298", size = 5366453, upload-time = "2025-11-17T22:32:07.115Z" }, - { url = "https://files.pythonhosted.org/packages/8c/27/12607423d0a9c6bbbcc780ad19f1f6baa2b68b18ce4bddcdc122c4c68dc9/ml_dtypes-0.5.4-cp313-cp313t-win_amd64.whl", hash = "sha256:cb73dccfc991691c444acc8c0012bee8f2470da826a92e3a20bb333b1a7894e6", size = 225612, upload-time = "2025-11-17T22:32:08.615Z" }, - { url = "https://files.pythonhosted.org/packages/e5/80/5a5929e92c72936d5b19872c5fb8fc09327c1da67b3b68c6a13139e77e20/ml_dtypes-0.5.4-cp313-cp313t-win_arm64.whl", hash = "sha256:3bbbe120b915090d9dd1375e4684dd17a20a2491ef25d640a908281da85e73f1", size = 164145, upload-time = "2025-11-17T22:32:09.782Z" }, ] [[package]] @@ -2689,42 +2407,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ca/a4/840f5b97339e27846c46307f2530a2805d9d537d8b8bd416af031cad7fa0/multidict-6.7.1-cp312-cp312-win32.whl", hash = "sha256:28ca5ce2fd9716631133d0e9a9b9a745ad7f60bac2bccafb56aa380fc0b6c511", size = 41887, upload-time = "2026-01-26T02:44:14.245Z" }, { url = "https://files.pythonhosted.org/packages/80/31/0b2517913687895f5904325c2069d6a3b78f66cc641a86a2baf75a05dcbb/multidict-6.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcee94dfbd638784645b066074b338bc9cc155d4b4bffa4adce1615c5a426c19", size = 46053, upload-time = "2026-01-26T02:44:15.371Z" }, { url = "https://files.pythonhosted.org/packages/0c/5b/aba28e4ee4006ae4c7df8d327d31025d760ffa992ea23812a601d226e682/multidict-6.7.1-cp312-cp312-win_arm64.whl", hash = "sha256:ba0a9fb644d0c1a2194cf7ffb043bd852cea63a57f66fbd33959f7dae18517bf", size = 43307, upload-time = "2026-01-26T02:44:16.852Z" }, - { url = "https://files.pythonhosted.org/packages/f2/22/929c141d6c0dba87d3e1d38fbdf1ba8baba86b7776469f2bc2d3227a1e67/multidict-6.7.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2b41f5fed0ed563624f1c17630cb9941cf2309d4df00e494b551b5f3e3d67a23", size = 76174, upload-time = "2026-01-26T02:44:18.509Z" }, - { url = "https://files.pythonhosted.org/packages/c7/75/bc704ae15fee974f8fccd871305e254754167dce5f9e42d88a2def741a1d/multidict-6.7.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84e61e3af5463c19b67ced91f6c634effb89ef8bfc5ca0267f954451ed4bb6a2", size = 45116, upload-time = "2026-01-26T02:44:19.745Z" }, - { url = "https://files.pythonhosted.org/packages/79/76/55cd7186f498ed080a18440c9013011eb548f77ae1b297206d030eb1180a/multidict-6.7.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:935434b9853c7c112eee7ac891bc4cb86455aa631269ae35442cb316790c1445", size = 43524, upload-time = "2026-01-26T02:44:21.571Z" }, - { url = "https://files.pythonhosted.org/packages/e9/3c/414842ef8d5a1628d68edee29ba0e5bcf235dbfb3ccd3ea303a7fe8c72ff/multidict-6.7.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:432feb25a1cb67fe82a9680b4d65fb542e4635cb3166cd9c01560651ad60f177", size = 249368, upload-time = "2026-01-26T02:44:22.803Z" }, - { url = "https://files.pythonhosted.org/packages/f6/32/befed7f74c458b4a525e60519fe8d87eef72bb1e99924fa2b0f9d97a221e/multidict-6.7.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e82d14e3c948952a1a85503817e038cba5905a3352de76b9a465075d072fba23", size = 256952, upload-time = "2026-01-26T02:44:24.306Z" }, - { url = "https://files.pythonhosted.org/packages/03/d6/c878a44ba877f366630c860fdf74bfb203c33778f12b6ac274936853c451/multidict-6.7.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4cfb48c6ea66c83bcaaf7e4dfa7ec1b6bbcf751b7db85a328902796dfde4c060", size = 240317, upload-time = "2026-01-26T02:44:25.772Z" }, - { url = "https://files.pythonhosted.org/packages/68/49/57421b4d7ad2e9e60e25922b08ceb37e077b90444bde6ead629095327a6f/multidict-6.7.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d540e51b7e8e170174555edecddbd5538105443754539193e3e1061864d444d", size = 267132, upload-time = "2026-01-26T02:44:27.648Z" }, - { url = "https://files.pythonhosted.org/packages/b7/fe/ec0edd52ddbcea2a2e89e174f0206444a61440b40f39704e64dc807a70bd/multidict-6.7.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:273d23f4b40f3dce4d6c8a821c741a86dec62cded82e1175ba3d99be128147ed", size = 268140, upload-time = "2026-01-26T02:44:29.588Z" }, - { url = "https://files.pythonhosted.org/packages/b0/73/6e1b01cbeb458807aa0831742232dbdd1fa92bfa33f52a3f176b4ff3dc11/multidict-6.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d624335fd4fa1c08a53f8b4be7676ebde19cd092b3895c421045ca87895b429", size = 254277, upload-time = "2026-01-26T02:44:30.902Z" }, - { url = "https://files.pythonhosted.org/packages/6a/b2/5fb8c124d7561a4974c342bc8c778b471ebbeb3cc17df696f034a7e9afe7/multidict-6.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:12fad252f8b267cc75b66e8fc51b3079604e8d43a75428ffe193cd9e2195dfd6", size = 252291, upload-time = "2026-01-26T02:44:32.31Z" }, - { url = "https://files.pythonhosted.org/packages/5a/96/51d4e4e06bcce92577fcd488e22600bd38e4fd59c20cb49434d054903bd2/multidict-6.7.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:03ede2a6ffbe8ef936b92cb4529f27f42be7f56afcdab5ab739cd5f27fb1cbf9", size = 250156, upload-time = "2026-01-26T02:44:33.734Z" }, - { url = "https://files.pythonhosted.org/packages/db/6b/420e173eec5fba721a50e2a9f89eda89d9c98fded1124f8d5c675f7a0c0f/multidict-6.7.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:90efbcf47dbe33dcf643a1e400d67d59abeac5db07dc3f27d6bdeae497a2198c", size = 249742, upload-time = "2026-01-26T02:44:35.222Z" }, - { url = "https://files.pythonhosted.org/packages/44/a3/ec5b5bd98f306bc2aa297b8c6f11a46714a56b1e6ef5ebda50a4f5d7c5fb/multidict-6.7.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c4b9bfc148f5a91be9244d6264c53035c8a0dcd2f51f1c3c6e30e30ebaa1c84", size = 262221, upload-time = "2026-01-26T02:44:36.604Z" }, - { url = "https://files.pythonhosted.org/packages/cd/f7/e8c0d0da0cd1e28d10e624604e1a36bcc3353aaebdfdc3a43c72bc683a12/multidict-6.7.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:401c5a650f3add2472d1d288c26deebc540f99e2fb83e9525007a74cd2116f1d", size = 258664, upload-time = "2026-01-26T02:44:38.008Z" }, - { url = "https://files.pythonhosted.org/packages/52/da/151a44e8016dd33feed44f730bd856a66257c1ee7aed4f44b649fb7edeb3/multidict-6.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:97891f3b1b3ffbded884e2916cacf3c6fc87b66bb0dde46f7357404750559f33", size = 249490, upload-time = "2026-01-26T02:44:39.386Z" }, - { url = "https://files.pythonhosted.org/packages/87/af/a3b86bf9630b732897f6fc3f4c4714b90aa4361983ccbdcd6c0339b21b0c/multidict-6.7.1-cp313-cp313-win32.whl", hash = "sha256:e1c5988359516095535c4301af38d8a8838534158f649c05dd1050222321bcb3", size = 41695, upload-time = "2026-01-26T02:44:41.318Z" }, - { url = "https://files.pythonhosted.org/packages/b2/35/e994121b0e90e46134673422dd564623f93304614f5d11886b1b3e06f503/multidict-6.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:960c83bf01a95b12b08fd54324a4eb1d5b52c88932b5cba5d6e712bb3ed12eb5", size = 45884, upload-time = "2026-01-26T02:44:42.488Z" }, - { url = "https://files.pythonhosted.org/packages/ca/61/42d3e5dbf661242a69c97ea363f2d7b46c567da8eadef8890022be6e2ab0/multidict-6.7.1-cp313-cp313-win_arm64.whl", hash = "sha256:563fe25c678aaba333d5399408f5ec3c383ca5b663e7f774dd179a520b8144df", size = 43122, upload-time = "2026-01-26T02:44:43.664Z" }, - { url = "https://files.pythonhosted.org/packages/6d/b3/e6b21c6c4f314bb956016b0b3ef2162590a529b84cb831c257519e7fde44/multidict-6.7.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c76c4bec1538375dad9d452d246ca5368ad6e1c9039dadcf007ae59c70619ea1", size = 83175, upload-time = "2026-01-26T02:44:44.894Z" }, - { url = "https://files.pythonhosted.org/packages/fb/76/23ecd2abfe0957b234f6c960f4ade497f55f2c16aeb684d4ecdbf1c95791/multidict-6.7.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:57b46b24b5d5ebcc978da4ec23a819a9402b4228b8a90d9c656422b4bdd8a963", size = 48460, upload-time = "2026-01-26T02:44:46.106Z" }, - { url = "https://files.pythonhosted.org/packages/c4/57/a0ed92b23f3a042c36bc4227b72b97eca803f5f1801c1ab77c8a212d455e/multidict-6.7.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e954b24433c768ce78ab7929e84ccf3422e46deb45a4dc9f93438f8217fa2d34", size = 46930, upload-time = "2026-01-26T02:44:47.278Z" }, - { url = "https://files.pythonhosted.org/packages/b5/66/02ec7ace29162e447f6382c495dc95826bf931d3818799bbef11e8f7df1a/multidict-6.7.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3bd231490fa7217cc832528e1cd8752a96f0125ddd2b5749390f7c3ec8721b65", size = 242582, upload-time = "2026-01-26T02:44:48.604Z" }, - { url = "https://files.pythonhosted.org/packages/58/18/64f5a795e7677670e872673aca234162514696274597b3708b2c0d276cce/multidict-6.7.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:253282d70d67885a15c8a7716f3a73edf2d635793ceda8173b9ecc21f2fb8292", size = 250031, upload-time = "2026-01-26T02:44:50.544Z" }, - { url = "https://files.pythonhosted.org/packages/c8/ed/e192291dbbe51a8290c5686f482084d31bcd9d09af24f63358c3d42fd284/multidict-6.7.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b4c48648d7649c9335cf1927a8b87fa692de3dcb15faa676c6a6f1f1aabda43", size = 228596, upload-time = "2026-01-26T02:44:51.951Z" }, - { url = "https://files.pythonhosted.org/packages/1e/7e/3562a15a60cf747397e7f2180b0a11dc0c38d9175a650e75fa1b4d325e15/multidict-6.7.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98bc624954ec4d2c7cb074b8eefc2b5d0ce7d482e410df446414355d158fe4ca", size = 257492, upload-time = "2026-01-26T02:44:53.902Z" }, - { url = "https://files.pythonhosted.org/packages/24/02/7d0f9eae92b5249bb50ac1595b295f10e263dd0078ebb55115c31e0eaccd/multidict-6.7.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b99af4d9eec0b49927b4402bcbb58dea89d3e0db8806a4086117019939ad3dd", size = 255899, upload-time = "2026-01-26T02:44:55.316Z" }, - { url = "https://files.pythonhosted.org/packages/00/e3/9b60ed9e23e64c73a5cde95269ef1330678e9c6e34dd4eb6b431b85b5a10/multidict-6.7.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aac4f16b472d5b7dc6f66a0d49dd57b0e0902090be16594dc9ebfd3d17c47e7", size = 247970, upload-time = "2026-01-26T02:44:56.783Z" }, - { url = "https://files.pythonhosted.org/packages/3e/06/538e58a63ed5cfb0bd4517e346b91da32fde409d839720f664e9a4ae4f9d/multidict-6.7.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:21f830fe223215dffd51f538e78c172ed7c7f60c9b96a2bf05c4848ad49921c3", size = 245060, upload-time = "2026-01-26T02:44:58.195Z" }, - { url = "https://files.pythonhosted.org/packages/b2/2f/d743a3045a97c895d401e9bd29aaa09b94f5cbdf1bd561609e5a6c431c70/multidict-6.7.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f5dd81c45b05518b9aa4da4aa74e1c93d715efa234fd3e8a179df611cc85e5f4", size = 235888, upload-time = "2026-01-26T02:44:59.57Z" }, - { url = "https://files.pythonhosted.org/packages/38/83/5a325cac191ab28b63c52f14f1131f3b0a55ba3b9aa65a6d0bf2a9b921a0/multidict-6.7.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:eb304767bca2bb92fb9c5bd33cedc95baee5bb5f6c88e63706533a1c06ad08c8", size = 243554, upload-time = "2026-01-26T02:45:01.054Z" }, - { url = "https://files.pythonhosted.org/packages/20/1f/9d2327086bd15da2725ef6aae624208e2ef828ed99892b17f60c344e57ed/multidict-6.7.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c9035dde0f916702850ef66460bc4239d89d08df4d02023a5926e7446724212c", size = 252341, upload-time = "2026-01-26T02:45:02.484Z" }, - { url = "https://files.pythonhosted.org/packages/e8/2c/2a1aa0280cf579d0f6eed8ee5211c4f1730bd7e06c636ba2ee6aafda302e/multidict-6.7.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:af959b9beeb66c822380f222f0e0a1889331597e81f1ded7f374f3ecb0fd6c52", size = 246391, upload-time = "2026-01-26T02:45:03.862Z" }, - { url = "https://files.pythonhosted.org/packages/e5/03/7ca022ffc36c5a3f6e03b179a5ceb829be9da5783e6fe395f347c0794680/multidict-6.7.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:41f2952231456154ee479651491e94118229844dd7226541788be783be2b5108", size = 243422, upload-time = "2026-01-26T02:45:05.296Z" }, - { url = "https://files.pythonhosted.org/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32", size = 47770, upload-time = "2026-01-26T02:45:06.754Z" }, - { url = "https://files.pythonhosted.org/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8", size = 53109, upload-time = "2026-01-26T02:45:08.044Z" }, - { url = "https://files.pythonhosted.org/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118", size = 45573, upload-time = "2026-01-26T02:45:09.349Z" }, { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, ] @@ -2876,26 +2558,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, - { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, - { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, - { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, - { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, - { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, - { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, - { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, - { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, - { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, - { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, - { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, - { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, - { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, - { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, - { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, - { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, - { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, - { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, { 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", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, @@ -2936,27 +2598,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f6/81/e1b27545deedce7f4a0b348618c6b62d74e36a4dc9ccd42f3eb2f85eee32/numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45", size = 5962825, upload-time = "2026-05-18T23:34:20.3Z" }, { url = "https://files.pythonhosted.org/packages/ab/ca/feab00bd44aa5fe1ad2c18f08b4d3bb92e26484b0b1d1443897809ed528c/numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751", size = 12321687, upload-time = "2026-05-18T23:34:23.095Z" }, { url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" }, - { url = "https://files.pythonhosted.org/packages/fb/82/bdab26d7438c6791ca31b7c024ca37c1eab8b726ba236129005cd4a06e45/numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0", size = 16684648, upload-time = "2026-05-18T23:34:29.41Z" }, - { url = "https://files.pythonhosted.org/packages/1b/30/a80189bcc7f5e4258b3fbc3968d909d1756f54d023299ecc39ad6fdb9ef8/numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb", size = 14693902, upload-time = "2026-05-18T23:34:33.013Z" }, - { url = "https://files.pythonhosted.org/packages/97/12/70b5d0d7c15e1ebb8a6a84a8caa1d19e181d84fb58bb6d70aca29099dec1/numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f", size = 5198992, upload-time = "2026-05-18T23:34:36.132Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8c/ebd2a8f8a83541f8d38cc5667e8c2b69cecfd30da6e45693e8158857d44b/numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3", size = 6546944, upload-time = "2026-05-18T23:34:38.484Z" }, - { url = "https://files.pythonhosted.org/packages/bb/c5/7b863a97a91671a0338f4253bd3b5a3d3852f0692dae91711c9f4a10e787/numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b", size = 15669392, upload-time = "2026-05-18T23:34:41.257Z" }, - { url = "https://files.pythonhosted.org/packages/a5/9d/3584b9984ca4c047aea75214ce1a4c4c73d849bd71b604264b7f5653f8a8/numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089", size = 16633220, upload-time = "2026-05-18T23:34:45.075Z" }, - { url = "https://files.pythonhosted.org/packages/05/ae/7c67fba23bd98caec7c99261f3a16072ade14813486b0282cb29846de832/numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a", size = 17020800, upload-time = "2026-05-18T23:34:49.065Z" }, - { url = "https://files.pythonhosted.org/packages/d9/5d/3b6725cb31d983c5e66916f5d36f6d7e5521129e4c4404d64f918292a5b6/numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605", size = 18357600, upload-time = "2026-05-18T23:34:52.709Z" }, - { url = "https://files.pythonhosted.org/packages/f7/da/2ccc6c2fe8898dee01d90c75c5f5f914a23daf99e3e0f59516a08760c8b5/numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91", size = 5961134, upload-time = "2026-05-18T23:34:55.618Z" }, - { url = "https://files.pythonhosted.org/packages/b5/cd/9cc4dc876fb065d5c220aae4d5e14826b2715331bb7618ce1fb07a679d99/numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359", size = 12318598, upload-time = "2026-05-18T23:34:58.928Z" }, - { url = "https://files.pythonhosted.org/packages/39/1e/c0bcba1f8694116485fe28fd1be698c278fcda4141c5b0e53a2aed8b12a8/numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778", size = 10222272, upload-time = "2026-05-18T23:35:02.167Z" }, - { url = "https://files.pythonhosted.org/packages/63/6d/cc5619247c8f4204e507f5883528372e4ac4bb189e579fb859a12e480b1f/numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1", size = 14821197, upload-time = "2026-05-18T23:35:05.468Z" }, - { url = "https://files.pythonhosted.org/packages/00/58/f1c39161c87d9e9bed660f1ed4bafc0e403d5ec9650b6dd77aead07d489b/numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe", size = 5326287, upload-time = "2026-05-18T23:35:08.693Z" }, - { url = "https://files.pythonhosted.org/packages/af/57/3917ab0fd97f271a8694513581b8a36c655f111c446852c302f04ccdb6fc/numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997", size = 6646763, upload-time = "2026-05-18T23:35:11.459Z" }, - { url = "https://files.pythonhosted.org/packages/eb/0f/037e64c494b67581ae18193d770adef354c41f3f2c8ebf865602d949bf8f/numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20", size = 15728070, upload-time = "2026-05-18T23:35:14.79Z" }, - { url = "https://files.pythonhosted.org/packages/21/a6/5d2bae9c9542eb4df16dc9c46dc79c186e9bad53805dfa5399a6023c6db0/numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d", size = 16681752, upload-time = "2026-05-18T23:35:18.836Z" }, - { url = "https://files.pythonhosted.org/packages/92/14/23d1dfb410ae362cd59ce53e936b1513d545eb40db3949ced632e19a459e/numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67", size = 17086024, upload-time = "2026-05-18T23:35:22.52Z" }, - { url = "https://files.pythonhosted.org/packages/4b/6e/23595a2c642cdf3bc567877064bdd7f91c8b0038a4453cf2daf7248eafe9/numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd", size = 18403398, upload-time = "2026-05-18T23:35:26.398Z" }, - { url = "https://files.pythonhosted.org/packages/8a/90/0ac3bc947217e66dec77e7cbc6a1979d1af70b6461b82f620d3bccd5e4c8/numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab", size = 6084971, upload-time = "2026-05-18T23:35:29.387Z" }, - { url = "https://files.pythonhosted.org/packages/77/71/5673e351671a1d2bd6063b91b44f70c0affea7d1516fa7a6572941ba4aa1/numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75", size = 12458532, upload-time = "2026-05-18T23:35:32.175Z" }, - { url = "https://files.pythonhosted.org/packages/3f/88/19d3503c5046e688f049274b27a3ef3d771152fa80d3ba3d01a3dff61abe/numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd", size = 10291881, upload-time = "2026-05-18T23:35:35.465Z" }, { url = "https://files.pythonhosted.org/packages/de/12/b422cc84439adc0d00de605bf4a308890ae5c26f2c71fbd73e5d08fbb0dd/numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662", size = 16847511, upload-time = "2026-05-18T23:36:50.673Z" }, { url = "https://files.pythonhosted.org/packages/44/53/f481bef68011740f8849418d82db07230e825013f31f4eef5ba5b805316a/numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7", size = 14889064, upload-time = "2026-05-18T23:36:53.879Z" }, { url = "https://files.pythonhosted.org/packages/7f/57/42ed575c10ced8af951d426bc4e1f8aff16fd851db33f067036215a7f860/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f", size = 5394157, upload-time = "2026-05-18T23:36:57.194Z" }, @@ -3145,9 +2786,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1a/3f/523fb08d9b7be15242ade6e2a641900d05c0e9cfffab8260de37a04ac0d2/nvidia_cudnn_frontend-1.22.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f64fb4e0a45b7a8bb126f91a71d8afc03facf14b82dade51744ca48cf20d2974", size = 2722597, upload-time = "2026-04-10T17:33:54.366Z" }, { url = "https://files.pythonhosted.org/packages/34/b7/35c87c334d553bd45809ec957b53f3d7dd13c5a407e853c9eea29fcc5b3c/nvidia_cudnn_frontend-1.22.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:933275df405053001888875ee75d2138b20dc4e8bf4057461b1c74ca68b0e270", size = 2863367, upload-time = "2026-04-10T17:29:22.838Z" }, { url = "https://files.pythonhosted.org/packages/4f/42/af975c8937a4c331b1215a0b2bdd2a742d792c6f777f919fd70480d63762/nvidia_cudnn_frontend-1.22.1-cp312-cp312-win_amd64.whl", hash = "sha256:2da1c277f008ee64273a48a5cb8d07efbb6d6774fdc08bd889476cce93b2f69a", size = 2310595, upload-time = "2026-04-10T17:37:24.776Z" }, - { url = "https://files.pythonhosted.org/packages/29/d3/d698b020ced27b75f1e29862f0bc26759da96fc743570a094632c0dd14a9/nvidia_cudnn_frontend-1.22.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bc0a0ec8004998a56f222cef618243bbee779930cdf3fe1f4a7604b2b412388", size = 2722225, upload-time = "2026-04-10T17:34:42.315Z" }, - { url = "https://files.pythonhosted.org/packages/2b/04/b7b66e3a0a7b036aca0f9704b335e663609359d0e3bdd7097f6d5ccdb40a/nvidia_cudnn_frontend-1.22.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b5295f8018cd92119968d948d25b0d2d834afd552627b47450759880dfe32110", size = 2863434, upload-time = "2026-04-10T17:29:55.721Z" }, - { url = "https://files.pythonhosted.org/packages/54/8c/e9da7bbdf197397d13bb418027951e6181d0bb74c70c648fd97376bc2ed7/nvidia_cudnn_frontend-1.22.1-cp313-cp313-win_amd64.whl", hash = "sha256:7ea7887facf23d5363159073b0080cc09185e73be16ae797831d89f09b96b0f4", size = 2310490, upload-time = "2026-04-10T17:37:47.625Z" }, ] [[package]] @@ -3537,19 +3175,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" }, { url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" }, { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, - { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, - { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, - { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, - { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, - { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, - { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, - { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, - { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, - { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, - { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, - { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, - { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, - { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, ] [[package]] @@ -3585,21 +3210,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f8/45/830bb57f533a4604b355e07edcb8ea18cf88b5f94e5fca92f27052d7c597/pandas-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8894dc474d648fe7b6ff0ca9b0bd73950d19952bc1a6534540762c5d79d305c", size = 11950889, upload-time = "2026-05-11T18:52:50.905Z" }, { url = "https://files.pythonhosted.org/packages/b9/c5/fc1b368f303087d20e8c9bf3d6ceb186263cfac0ade735cd938538bea839/pandas-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:c7be265b62cef88e253a941e4698604973736dcfe242fdb5198f0f7bc473cdcc", size = 9755463, upload-time = "2026-05-11T18:52:53.386Z" }, { url = "https://files.pythonhosted.org/packages/86/bd/fda8f9705b1b09c6ebe14bfc0fa0e4ec8584d54ea673628f157ff55131af/pandas-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:557409bc4178e70ee8d9ddb494798e51ebf6ea59330f6be22c51bab2a7db6c49", size = 9066158, upload-time = "2026-05-11T18:52:56.038Z" }, - { url = "https://files.pythonhosted.org/packages/c5/90/62d8302883c44308c477e222c3daf7c813a34c8e96985882fbd53d964352/pandas-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:67b3b64c11910cfa29f4e94a14d3bff9ee693b6fc76055e7cad549cee0aec5fa", size = 10331071, upload-time = "2026-05-11T18:52:58.838Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ae/6a6493c783a101f165e4356953ba3c74d6f77f0042fa7d753da9dfbb640c/pandas-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39436b377d56d2a2e52d0395bdbee171f01068e99af5250509aceeb929f765c7", size = 9875690, upload-time = "2026-05-11T18:53:01.431Z" }, - { url = "https://files.pythonhosted.org/packages/62/7c/5df8e9f56c69a2769fbe9382a5ef8f2658c007e376434e1e2cbb57ad895f/pandas-3.0.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4be06d68f9ddcfc645b87534911da79a8fbffc7573c80e0edcf42a5020624d8", size = 10381634, upload-time = "2026-05-11T18:53:04.393Z" }, - { url = "https://files.pythonhosted.org/packages/99/68/1237369725aa617bb358263d535803e3053fdbc593513ec5ed9c9896b5b6/pandas-3.0.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4eeb6830daf35a71cc09649bd823e2b542dac246cdee9614c6e4bd65028cd6a", size = 10891243, upload-time = "2026-05-11T18:53:07.643Z" }, - { url = "https://files.pythonhosted.org/packages/25/93/77d108e8af7222b4a503ebde0e30215b1c2e4f8e53a526431890f22d5586/pandas-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1928e07221f82db493cd4af1e23c1bfca524a19a4699887975bff68f49a72bfb", size = 11388659, upload-time = "2026-05-11T18:53:10.634Z" }, - { url = "https://files.pythonhosted.org/packages/d0/bd/eff5b4399f332ac386c853f6cd2bd3fa2ca0061b9f36ecd9c4d7c4265649/pandas-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51b1fe551acb77dac643c6fda86084d8d446c10fe64b06a9cc29c4cc8540e7f2", size = 11942880, upload-time = "2026-05-11T18:53:13.536Z" }, - { url = "https://files.pythonhosted.org/packages/2c/20/559ace4200982c3887d0b86bfd0d856a2143ef8ddab63cc07934951a964c/pandas-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:a82d532a3351d435432cd913edbccaf8b8e01d4dd0e5ced5a8d2e8ecd94c7e44", size = 9757091, upload-time = "2026-05-11T18:53:16.306Z" }, - { url = "https://files.pythonhosted.org/packages/3a/66/69055a09fe200f29f922a3eeec4804611900b95f52d932ece3393c3c0c19/pandas-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:275c14e0fce14a2ec20eee474aecd305478ea3c1e6f6a9d8fe219a165542717e", size = 9057282, upload-time = "2026-05-11T18:53:18.768Z" }, - { url = "https://files.pythonhosted.org/packages/57/0e/efe801b0e6811e8e650cd21b7f2608e30f08a7067e2bf6e8752b0d56ee3c/pandas-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:46997386d528eb40376ecd6b033cf4a8a1e5282580f68f43de875b78cba2199d", size = 10767016, upload-time = "2026-05-11T18:53:21.227Z" }, - { url = "https://files.pythonhosted.org/packages/ea/dc/eb55135a1d5f0f0519f28da1f609a206d2cad1f9c35c32d51e38dd7261ae/pandas-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261e308dfb22448384b7580cf719d2f998fe2966c92893c3e77d14008af1f066", size = 10420210, upload-time = "2026-05-11T18:53:23.982Z" }, - { url = "https://files.pythonhosted.org/packages/c6/3e/b1d5d955ce33ffecb407465a60bc32769d74fcf68224b7ae67ae11d4dea4/pandas-3.0.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd1a5d1def6a46002e964510bdc67c368aa0951df5d1d9f8365336f5a1f490cd", size = 10336126, upload-time = "2026-05-11T18:53:26.731Z" }, - { url = "https://files.pythonhosted.org/packages/f5/76/a01261711ab60a22d71b862f0de20e4c504bf80457270ad8cb42110f6abc/pandas-3.0.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d72828c20c6d6e83e1e22a6a3b47b326b71664112fa9705dcbccfd7a39b62085", size = 10728051, upload-time = "2026-05-11T18:53:29.125Z" }, - { url = "https://files.pythonhosted.org/packages/e9/21/ea191195e587b18cf682e97f433f81b2d0fbe341380e80a3e0d6e4403c8e/pandas-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d26cbe1fcfc12e8fd900e2454163e466b2d3af84f7c75481df7683ffc073d870", size = 11350796, upload-time = "2026-05-11T18:53:32.056Z" }, - { url = "https://files.pythonhosted.org/packages/64/69/f0eaaf54939f0e8c6768fd06be9af2cef9b36048b96dfb9e1b2c685a807e/pandas-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3e91cec1879ada0624fc3dc9953c5cbd60208e59c0db28f540c5d6d47502422f", size = 11799741, upload-time = "2026-05-11T18:53:34.985Z" }, - { url = "https://files.pythonhosted.org/packages/45/a4/865e0e510cae5fc2194de4db28be638952de942571ba9125934fd9c01d47/pandas-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:08d789b41f87e0905880e293cedf6197ce71fe67cc081358b1e148a491b9bd13", size = 10499958, upload-time = "2026-05-11T18:53:37.857Z" }, ] [[package]] @@ -3662,31 +3272,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, - { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, - { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, - { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, - { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, - { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, - { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, - { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, - { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, - { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, - { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, - { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, - { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, - { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, - { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, - { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, - { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, - { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, - { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, - { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, - { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, - { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, - { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, - { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, - { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" }, { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" }, { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" }, @@ -3811,40 +3396,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/74/66bd798b5b3be70aa1b391f5cc9d6a0a5532d7fd3b19ec0b213e72e6ad9d/propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031", size = 39018, upload-time = "2026-05-08T21:00:31.622Z" }, { url = "https://files.pythonhosted.org/packages/61/7c/5c0d34aa3024694d6dcb9271cdbdd08c4e47c1c0ad95ec7e7bc74cdea145/propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42", size = 42322, upload-time = "2026-05-08T21:00:32.918Z" }, { url = "https://files.pythonhosted.org/packages/4d/91/875812f1a3feb20ceba818ef39fbe4d92f1081e04ac815c822496d0d038b/propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84", size = 38172, upload-time = "2026-05-08T21:00:35.124Z" }, - { url = "https://files.pythonhosted.org/packages/c5/09/f049e45385503fe67db75a6b6186a7b9f0c3930366dc960522c312a825b1/propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a", size = 94457, upload-time = "2026-05-08T21:00:36.355Z" }, - { url = "https://files.pythonhosted.org/packages/6b/65/83d1d05655baf63113731bd5a1008435e14f8d1e5a06cbe4ec5b23ad7a31/propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117", size = 53835, upload-time = "2026-05-08T21:00:38.072Z" }, - { url = "https://files.pythonhosted.org/packages/a9/12/a6ba6482bb5ea3260c000c9b20881c95fa11c6b30173715668259f844ed7/propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098", size = 54545, upload-time = "2026-05-08T21:00:39.319Z" }, - { url = "https://files.pythonhosted.org/packages/a9/19/7fa086f5764c59ec8a8e157cd93aa8497acc00aba9dcdec56bfffb32602d/propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4", size = 59886, upload-time = "2026-05-08T21:00:40.621Z" }, - { url = "https://files.pythonhosted.org/packages/a1/e4/5d7663dc8235956c8f5281698a3af1d351d8820341ddd890f59d9a9127f2/propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e", size = 63261, upload-time = "2026-05-08T21:00:41.775Z" }, - { url = "https://files.pythonhosted.org/packages/4a/4a/15a03adee24d6350da4292caeac44c34c033d2afe5e87eb370f38854560f/propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7", size = 64184, upload-time = "2026-05-08T21:00:43.018Z" }, - { url = "https://files.pythonhosted.org/packages/8b/c6/979176efdaa3d239e36d503d5af63a0a773b36662ed8f52e5b6a6d9fd40e/propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d", size = 61534, upload-time = "2026-05-08T21:00:44.507Z" }, - { url = "https://files.pythonhosted.org/packages/c8/22/63e8cd1bae4c2d2be6493b6b7d10566ddafad88137cfbc99964a1119853c/propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a", size = 61500, upload-time = "2026-05-08T21:00:45.796Z" }, - { url = "https://files.pythonhosted.org/packages/60/5a/28e5d9acbac1cc9ccb67045e8c1b943aa8d79fdf39c93bd73cacd68008ea/propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2", size = 59994, upload-time = "2026-05-08T21:00:47.093Z" }, - { url = "https://files.pythonhosted.org/packages/f3/40/db650677f554a95b9c01a7c9d93d629e93a15562f5deb4573c9ee136fed2/propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa", size = 56884, upload-time = "2026-05-08T21:00:48.376Z" }, - { url = "https://files.pythonhosted.org/packages/80/45/70b39b89516ff8b96bf732fa6fded8cef20f293cb1508690101c3c07ec51/propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853", size = 63464, upload-time = "2026-05-08T21:00:49.954Z" }, - { url = "https://files.pythonhosted.org/packages/f9/e2/fa59d3a89eac5534293124af4f1d0d0ada091ce4a0ab4610ce03fd2bdd8d/propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a", size = 61588, upload-time = "2026-05-08T21:00:51.281Z" }, - { url = "https://files.pythonhosted.org/packages/0b/97/efb547a55c4bc7381cfb202d6a2239ac621045277bc1ea5dfd3a7f0516c0/propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704", size = 64667, upload-time = "2026-05-08T21:00:52.602Z" }, - { url = "https://files.pythonhosted.org/packages/92/56/f5c7d9b4b7595d5127da38974d791b2153f3d1eae6c674af3583ace92ad3/propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4", size = 62463, upload-time = "2026-05-08T21:00:54.303Z" }, - { url = "https://files.pythonhosted.org/packages/bd/3b/484a3a65fc9f9f60c41dcd17b428bace5389544e2c680994534a20755066/propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d", size = 38621, upload-time = "2026-05-08T21:00:55.808Z" }, - { url = "https://files.pythonhosted.org/packages/1c/fd/3f0f10dba4dabad3bf53102be007abf55481067952bde0fdddff439e7c61/propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757", size = 41649, upload-time = "2026-05-08T21:00:57.061Z" }, - { url = "https://files.pythonhosted.org/packages/90/ec/6ce619cc32bb500a482f811f9cd509368b4e58e638d13f2c68f370d6b475/propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f", size = 37636, upload-time = "2026-05-08T21:00:58.646Z" }, - { url = "https://files.pythonhosted.org/packages/1b/82/c1d268bbbf2ef981c5bf0fbbe746db617c66e3bcefe431a1aa8943fbe23a/propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d", size = 98872, upload-time = "2026-05-08T21:00:59.889Z" }, - { url = "https://files.pythonhosted.org/packages/f4/d4/52c871e73e864e6b34c0e2d58ac1ec5ccd149497ddc7ad2137ae98323a35/propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa", size = 56257, upload-time = "2026-05-08T21:01:01.195Z" }, - { url = "https://files.pythonhosted.org/packages/67/f0/9b90ca2a210b3d09bcfcd96ecd0f55545c091535abce2a45de2775cfd357/propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94", size = 56696, upload-time = "2026-05-08T21:01:02.941Z" }, - { url = "https://files.pythonhosted.org/packages/9d/0e/6e9d4ba07c8e56e21ddec1e75f12148142b21ca83a51871babce095334f4/propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164", size = 62378, upload-time = "2026-05-08T21:01:04.475Z" }, - { url = "https://files.pythonhosted.org/packages/65/19/c10badaa463dde8a27ce884f8ee2ec37e6035b7c9f5ff0c8f74f06f08dac/propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f", size = 65283, upload-time = "2026-05-08T21:01:05.959Z" }, - { url = "https://files.pythonhosted.org/packages/b0/b6/93bea99ca80e19cef6512a8580e5b7857bbe09422d9daa7fd4ef5723306c/propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c", size = 66616, upload-time = "2026-05-08T21:01:07.228Z" }, - { url = "https://files.pythonhosted.org/packages/83/e4/5c7462e50625f051f37fb38b8224f7639f667184bbd34424ec83819bb1b7/propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc", size = 63773, upload-time = "2026-05-08T21:01:08.514Z" }, - { url = "https://files.pythonhosted.org/packages/ca/b6/99238894047b13c823be25027e736626cd414a52a5e30d2c3347c2733529/propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f", size = 63664, upload-time = "2026-05-08T21:01:09.874Z" }, - { url = "https://files.pythonhosted.org/packages/85/1e/a3a1a63116a2b8edb415a8bb9a6f0c34bd03830b1e18e8ce2904e1dc1cf4/propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb", size = 62643, upload-time = "2026-05-08T21:01:11.132Z" }, - { url = "https://files.pythonhosted.org/packages/e4/03/893cf147de2fc6543c5eaa07ad833170e7e2a2385725bbebe8c0503723bb/propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751", size = 59595, upload-time = "2026-05-08T21:01:12.387Z" }, - { url = "https://files.pythonhosted.org/packages/86/3b/04c1a2e12c57766568ba75ba72b3bf2042818d4c1425fab6fc07155c7cff/propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836", size = 65711, upload-time = "2026-05-08T21:01:13.676Z" }, - { url = "https://files.pythonhosted.org/packages/1c/34/80f8d0099f8d6bacc4de1624c85672681c8cd1149ca2da0e38fd120b817f/propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f", size = 64247, upload-time = "2026-05-08T21:01:14.936Z" }, - { url = "https://files.pythonhosted.org/packages/f3/1a/8b08f3a5f1037e9e370c55883ceeeee0f6dd0416fb2d2d67b8bfc91f2a79/propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55", size = 67102, upload-time = "2026-05-08T21:01:16.281Z" }, - { url = "https://files.pythonhosted.org/packages/34/68/8bdb7bb7756d76e005490649d10e4a8369e610c74d619f71e1aedf889e9c/propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568", size = 64964, upload-time = "2026-05-08T21:01:17.57Z" }, - { url = "https://files.pythonhosted.org/packages/0a/aa/50fb0b5d3968b61a510926ff8b8465f1d6e976b3ab74496d7a4b9fc42515/propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191", size = 42546, upload-time = "2026-05-08T21:01:18.946Z" }, - { url = "https://files.pythonhosted.org/packages/ae/4c/0ddbae64321bd4a95bcbfc19307238016b5b1fee645c84626c8d539e5b74/propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7", size = 46330, upload-time = "2026-05-08T21:01:20.162Z" }, - { url = "https://files.pythonhosted.org/packages/00/d9/9cddc8efb78d8af264c5ec9f6d10b62f57c515feda8d321595f56010fb23/propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96", size = 40521, upload-time = "2026-05-08T21:01:21.399Z" }, { url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" }, ] @@ -3869,12 +3420,6 @@ version = "7.2.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, - { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, - { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, - { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, - { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, @@ -3930,20 +3475,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/e8/f88ce625fe8babaae64e8db2d417c7653adb3019b08aae85c5ed787dc816/pyarrow-24.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b13dedfe76a0ad2d1d859b0811b53827a4e9d93a0bcb05cf59333ab4980cc7e", size = 49376032, upload-time = "2026-04-21T10:47:48.967Z" }, { url = "https://files.pythonhosted.org/packages/36/7a/82c363caa145fff88fb475da50d3bf52bb024f61917be5424c3392eaf878/pyarrow-24.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:25ea65d868eb04015cd18e6df2fbe98f07e5bda2abefabcb88fce39a947716f6", size = 51929490, upload-time = "2026-04-21T10:47:55.981Z" }, { url = "https://files.pythonhosted.org/packages/66/1c/e3e72c8014ad2743ca64a701652c733cc5cbcee15c0463a32a8c55518d9e/pyarrow-24.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826", size = 27355660, upload-time = "2026-04-21T10:48:01.718Z" }, - { url = "https://files.pythonhosted.org/packages/6f/d3/a1abf004482026ddc17f4503db227787fa3cfe41ec5091ff20e4fea55e57/pyarrow-24.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:02b001b3ed4723caa44f6cd1af2d5c86aa2cf9971dacc2ffa55b21237713dfba", size = 34976759, upload-time = "2026-04-21T10:48:07.258Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4a/34f0a36d28a2dd32225301b79daad44e243dc1a2bb77d43b60749be255c4/pyarrow-24.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:04920d6a71aabd08a0417709efce97d45ea8e6fb733d9ca9ecffb13c67839f68", size = 36658471, upload-time = "2026-04-21T10:48:13.347Z" }, - { url = "https://files.pythonhosted.org/packages/1f/78/543b94712ae8bb1a6023bcc1acf1a740fbff8286747c289cd9468fced2a5/pyarrow-24.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:a964266397740257f16f7bb2e4f08a0c81454004beab8ff59dd531b73610e9f2", size = 45675981, upload-time = "2026-04-21T10:48:20.201Z" }, - { url = "https://files.pythonhosted.org/packages/84/9f/8fb7c222b100d314137fa40ec050de56cd8c6d957d1cfff685ce72f15b17/pyarrow-24.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6f066b179d68c413374294bc1735f68475457c933258df594443bb9d88ddc2a0", size = 48859172, upload-time = "2026-04-21T10:48:27.541Z" }, - { url = "https://files.pythonhosted.org/packages/a7/d3/1ea72538e6c8b3b475ed78d1049a2c518e655761ea50fe1171fc855fcab7/pyarrow-24.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1183baeb14c5f587b1ec52831e665718ce632caab84b7cd6b85fd44f96114495", size = 49385733, upload-time = "2026-04-21T10:48:34.7Z" }, - { url = "https://files.pythonhosted.org/packages/c3/be/c3d8b06a1ba35f2260f8e1f771abbee7d5e345c0937aab90675706b1690a/pyarrow-24.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:806f24b4085453c197a5078218d1ee08783ebbba271badd153d1ae22a3ee804f", size = 51934335, upload-time = "2026-04-21T10:48:42.099Z" }, - { url = "https://files.pythonhosted.org/packages/9c/62/89e07a1e7329d2cde3e3c6994ba0839a24977a2beda8be6005ea3d860b99/pyarrow-24.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:e4505fc6583f7b05ab854934896bcac8253b04ac1171a77dfb73efef92076d91", size = 27271748, upload-time = "2026-04-21T10:49:42.532Z" }, - { url = "https://files.pythonhosted.org/packages/17/1a/cff3a59f80b5b1658549d46611b67163f65e0664431c076ad728bf9d5af4/pyarrow-24.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:1a4e45017efbf115032e4475ee876d525e0e36c742214fbe405332480ecd6275", size = 35238554, upload-time = "2026-04-21T10:48:48.526Z" }, - { url = "https://files.pythonhosted.org/packages/a8/99/cce0f42a327bfef2c420fb6078a3eb834826e5d6697bf3009fe11d2ad051/pyarrow-24.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:7986f1fa71cee060ad00758bcc79d3a93bab8559bf978fab9e53472a2e25a17b", size = 36782301, upload-time = "2026-04-21T10:48:55.181Z" }, - { url = "https://files.pythonhosted.org/packages/2a/66/8e560d5ff6793ca29aca213c53eec0dd482dd46cb93b2819e5aab52e4252/pyarrow-24.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:d3e0b61e8efb24ed38898e5cdc5fffa9124be480008d401a1f8071500494ae42", size = 45721929, upload-time = "2026-04-21T10:49:03.676Z" }, - { url = "https://files.pythonhosted.org/packages/27/0c/a26e25505d030716e078d9f16eb74973cbf0b33b672884e9f9da1c83b871/pyarrow-24.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:55a3bc1e3df3b5567b7d27ef551b2283f0c68a5e86f1cd56abc569da4f31335b", size = 48825365, upload-time = "2026-04-21T10:49:11.714Z" }, - { url = "https://files.pythonhosted.org/packages/5f/eb/771f9ecb0c65e73fe9dccdd1717901b9594f08c4515d000c7c62df573811/pyarrow-24.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:641f795b361874ac9da5294f8f443dfdbee355cf2bd9e3b8d97aaac2306b9b37", size = 49451819, upload-time = "2026-04-21T10:49:21.474Z" }, - { url = "https://files.pythonhosted.org/packages/48/da/61ae89a88732f5a785646f3ec6125dbb640fa98a540eb2b9889caa561403/pyarrow-24.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8adc8e6ce5fccf5dc707046ae4914fd537def529709cc0d285d37a7f9cd442ca", size = 51909252, upload-time = "2026-04-21T10:49:31.164Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1a/8dd5cafab7b66573fa91c03d06d213356ad4edd71813aa75e08ce2b3a844/pyarrow-24.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:9b18371ad2f44044b81a8d23bc2d8a9b6a6226dca775e8e16cfee640473d6c5d", size = 27388127, upload-time = "2026-04-21T10:49:37.334Z" }, ] [[package]] @@ -3960,10 +3491,10 @@ name = "pydantic" version = "2.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "annotated-types", marker = "sys_platform != 'win32'" }, - { name = "pydantic-core", marker = "sys_platform != 'win32'" }, - { name = "typing-extensions", marker = "sys_platform != 'win32'" }, - { name = "typing-inspection", marker = "sys_platform != 'win32'" }, + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, ] sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ @@ -3975,7 +3506,7 @@ name = "pydantic-core" version = "2.46.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform != 'win32'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } wheels = [ @@ -4023,21 +3554,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, - { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, - { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, - { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, - { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, - { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, - { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, - { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, - { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, - { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, - { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, - { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, - { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, - { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, - { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, @@ -4142,7 +3658,7 @@ version = "26.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/74/b7/da07bae88f5a9506b4def6f2f4903cf4c3b8831e560dba8fa18ca08f758f/pyopenssl-26.3.0.tar.gz", hash = "sha256:589de7fae1c9ea670d18422ed00fc04da787bbde8e1454aea872aa57b49ad341", size = 182024, upload-time = "2026-06-12T20:28:07.458Z" } wheels = [ @@ -4183,7 +3699,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "backports-asyncio-runner", marker = "python_full_version < '3.11' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, { name = "pytest" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } wheels = [ @@ -4280,16 +3796,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, - { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, - { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, - { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, - { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, - { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, - { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, - { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, - { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, - { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, ] [[package]] @@ -4360,38 +3866,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c3/1c/bdcc98f9a4af4fdd166c74941174619ccff4726d3ce32faa8e9a2ecd38dd/regex-2026.5.9-cp312-cp312-win32.whl", hash = "sha256:164eba9b755ea6f244b0d881196fbc1fac09714e9782c9e2732b813142033c8e", size = 266699, upload-time = "2026-05-09T23:12:59.14Z" }, { url = "https://files.pythonhosted.org/packages/78/87/240d36864f9e48ace85f72e79ced97ceb7f27ce87739a947dcb834b4e6bc/regex-2026.5.9-cp312-cp312-win_amd64.whl", hash = "sha256:86f40a5d6444db30a125c9c9177e6b25dad981cbc37451fd838f145e6edac92e", size = 277783, upload-time = "2026-05-09T23:13:00.789Z" }, { url = "https://files.pythonhosted.org/packages/4f/b5/7b30f312b0669dff5beebe5b0989dc2d1a312b1a44fab852199c387a5b96/regex-2026.5.9-cp312-cp312-win_arm64.whl", hash = "sha256:96f5f58b54a063d7ea9dca08e1cf57bfe10499c4d579ee672da284f57f5f0070", size = 270513, upload-time = "2026-05-09T23:13:02.426Z" }, - { url = "https://files.pythonhosted.org/packages/aa/da/797e91ecec6f84135da778ddce78c20e0af5d2a15c26f87a81bc3eadb6db/regex-2026.5.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d626b84406444b165fc0ba981604edea39f0588ff1f92baa23fe50799ea9afdb", size = 490303, upload-time = "2026-05-09T23:13:04.382Z" }, - { url = "https://files.pythonhosted.org/packages/44/da/bf30abaaa737b58f4a4b8c4a03659e02fd92092c822e0197ed9e0daab917/regex-2026.5.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d7bdc0ab8f3dd7e1b4f9ab88634e13374669db86bb3c72e8292f07ae313f539f", size = 292019, upload-time = "2026-05-09T23:13:06.022Z" }, - { url = "https://files.pythonhosted.org/packages/2d/e7/d0eaf5713828417b9e5648cf81fa9bacd4961f6ab98c380c2034f8716e35/regex-2026.5.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a8820737949116ffff55fe18f9fc644530063ba6ebfcb8314239416e78f1347c", size = 289468, upload-time = "2026-05-09T23:13:08.214Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9b/b3fdd62b003baa1a9b593cd8c8699c9651c2e80cc21a5c715707983c42d7/regex-2026.5.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0fbdbac82cb3e4450d0ccde7d7a35607f4cb2dd9fba4b8b69bfaf8c9fa6aed", size = 796749, upload-time = "2026-05-09T23:13:10.573Z" }, - { url = "https://files.pythonhosted.org/packages/d4/30/66ab84588765f5b4b271a9ca09ef7ce2b87caa95176ec3d2ad65d7bc4902/regex-2026.5.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:57e8915c7986aa33d25e4d3629cef711cd2863f2961b10409f0c04cb8b7d9020", size = 865445, upload-time = "2026-05-09T23:13:12.523Z" }, - { url = "https://files.pythonhosted.org/packages/1a/89/f05169e8588aac365f35ffc7f3bc3184f095ef4cfded7cfaa3c7fd5dbd89/regex-2026.5.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508f56a89ba9cb26e4168cbc37dbd60a28d82430a9e18ad1d25fe0883c314ca2", size = 912322, upload-time = "2026-05-09T23:13:14.281Z" }, - { url = "https://files.pythonhosted.org/packages/30/e1/c93444052cf41581f3c884ab3fb5823daf0992f11cd4388d4275ca610558/regex-2026.5.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d189041f15691cfa2b6c4290448ec221244d225b3f5fe9e7771b34ffcdf6e2", size = 801269, upload-time = "2026-05-09T23:13:16.569Z" }, - { url = "https://files.pythonhosted.org/packages/50/fe/0cf96b882f540e62e8b9956599798203d599c44cf4c77917ca27400ff69b/regex-2026.5.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e82db382b44d0111b22601c509c89f64434816c9e0eef9d1989cda8cc6ff1c04", size = 777085, upload-time = "2026-05-09T23:13:18.675Z" }, - { url = "https://files.pythonhosted.org/packages/23/5c/d78d4924e7fc875557b9e9b768423925fdfaac5549d06da7810019a9bd26/regex-2026.5.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2acfb48634f64996b57f90f39afa692ff362162722581921fe92239a59960f3c", size = 785153, upload-time = "2026-05-09T23:13:20.525Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e0/5214774090e7b4524dcea3e3c4aa74141d43043f8beb49c1599db1c8b53a/regex-2026.5.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d29eebfc9525db68cad3c97eedd7f754fa265aa5cd0cf4f863b2421e1b48fc9f", size = 860164, upload-time = "2026-05-09T23:13:22.263Z" }, - { url = "https://files.pythonhosted.org/packages/6e/e1/4a57a83350319b1271f0d7a249b8672513ed928b237a741631270de6caea/regex-2026.5.9-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:debb893095e944091c16e641a6e33c1b0f4cb61ab945ec5afbf53ce7068834d8", size = 765731, upload-time = "2026-05-09T23:13:24.277Z" }, - { url = "https://files.pythonhosted.org/packages/12/f4/499e74a20c156fc75836ee04a72a38d1a063978f600937f9760467beb1b0/regex-2026.5.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d659eee77986549c9ea45b861c7567e44d6287c3dc9a4565478853f7b9fe2ff6", size = 852062, upload-time = "2026-05-09T23:13:26.125Z" }, - { url = "https://files.pythonhosted.org/packages/5b/92/7eebc0d0a01e78629695f342ba17e0deaff8fb45e79cc0d7b98287da6e3e/regex-2026.5.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2efa205e6d98b24d1f3ab395c11aa15cdf10935bca283d0285e0499c284fba21", size = 789577, upload-time = "2026-05-09T23:13:27.814Z" }, - { url = "https://files.pythonhosted.org/packages/05/a4/018e71f7d2ad48c1ebe6d3ae0026f9b7cb4802fd15c7cc02fdf724355102/regex-2026.5.9-cp313-cp313-win32.whl", hash = "sha256:f3844f134e834076677dd369976e9f5068679fcb8e50102fdf6b7ac96a3ec127", size = 266691, upload-time = "2026-05-09T23:13:29.549Z" }, - { url = "https://files.pythonhosted.org/packages/e6/1d/861a93719fb9ee7dbfc3761b3797b7a3e112a5d42c6129459d2d741be9b5/regex-2026.5.9-cp313-cp313-win_amd64.whl", hash = "sha256:3527bb4942d2c14552155406cdedd906567456821848aed1cb4933a391bf5eca", size = 277747, upload-time = "2026-05-09T23:13:31.859Z" }, - { url = "https://files.pythonhosted.org/packages/d9/c6/0a2436ae4da1ba76e51cb98943c6838a9a721faa40ebe2dce07694ae34e3/regex-2026.5.9-cp313-cp313-win_arm64.whl", hash = "sha256:56a33f191f17d8c417f99945ebdc1e691d3af9605d86ec68c7e54a57e3e17af6", size = 270500, upload-time = "2026-05-09T23:13:33.525Z" }, - { url = "https://files.pythonhosted.org/packages/e8/e9/d21346f7b60ed58789371358ed66b09d00f832e1bd7c06e55d9da5679882/regex-2026.5.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:01f28d868834624c934b8d2e0aa1c8341337e37831f4a012f18a5afcba4cbaf3", size = 494172, upload-time = "2026-05-09T23:13:35.935Z" }, - { url = "https://files.pythonhosted.org/packages/c4/43/fd1177a2032037c681baecdb3422ee4e1424aec4e4f470ef47793d325274/regex-2026.5.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:48036f6374aaa79eb3b754ec29c61d1c6b1606749d705a13f8854fa2539671f6", size = 293952, upload-time = "2026-05-09T23:13:38.307Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7d/9fbf919768368d3f8a4f6c692cf2aa61e482b2b81ec6a298ace4cbf02480/regex-2026.5.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b96350aa424e79d4fd6b567b344dcbe2b2d6bfc48dfe7717587e1fa6d43da6ff", size = 292314, upload-time = "2026-05-09T23:13:40.353Z" }, - { url = "https://files.pythonhosted.org/packages/e2/6c/e41bfeecb589716843e7c4df09ba46ff2a42961457afece19059d85caeef/regex-2026.5.9-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f3af7a4903c5c04a11a196a5aa75cdd7dd3f8508132f9fb3259d9f5908e3b88", size = 811681, upload-time = "2026-05-09T23:13:42.543Z" }, - { url = "https://files.pythonhosted.org/packages/87/83/a5c1c525fba0aa656e88ad0face0b1829788ef4c2fb6b26df58aa1151b84/regex-2026.5.9-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7e87577720152d2caae19fe2baaf1f8d5ca12091e9e229f03915c37d1e4b9178", size = 871135, upload-time = "2026-05-09T23:13:44.326Z" }, - { url = "https://files.pythonhosted.org/packages/18/d4/80882e799e440dd878b0979cbebf8fa4d54624a332c83037c7a701649e3f/regex-2026.5.9-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c8b9b9d294cfea3cd19c718ade7cc93492b2c4991abd9a68d0b3477ae6d8e100", size = 917265, upload-time = "2026-05-09T23:13:47.295Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ff/8db60211e2286e396aad7dc7725356c502bff0901ea05bd6cdc2e1a042b9/regex-2026.5.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:728d8bfd28a8845c8b6bc5dc7ce010453d206396786c0765c2740cb65f37791e", size = 816311, upload-time = "2026-05-09T23:13:49.885Z" }, - { url = "https://files.pythonhosted.org/packages/4c/47/742ef579c61730f8d268e5cf1f9ce0e37e2ea041ad0f5644724f2378e463/regex-2026.5.9-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7e30b874d341fac767d7df5a0870540541c2c054b80cfaac116e8d367a8a7ff2", size = 785498, upload-time = "2026-05-09T23:13:52.25Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ab/cb0999802dcb0fb95b1ab005e8d4163d8afdd67efc2cb6b6630ac13f8cb1/regex-2026.5.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fd190e88a895a8901325fad284a3f74ea52b1da8525b76cc811fa9b1edf0ce2b", size = 801348, upload-time = "2026-05-09T23:13:54.127Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/8ca59a24c55bc34d166eefaf3717bd77772f329fdbf984d86581e0a3571c/regex-2026.5.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:8e76e8161ad00694cfce6767d5dea860c6391ac5b83e5c3a39661e696f11fc7e", size = 866493, upload-time = "2026-05-09T23:13:56.067Z" }, - { url = "https://files.pythonhosted.org/packages/8d/3d/30f2ae62cef3278bb5bb821f467277a55fb73f01032cf85997e15e8289a8/regex-2026.5.9-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ddda5340e6c01a293027dd46232fa79eaff1b48058ce7a98f572b6445b088041", size = 772811, upload-time = "2026-05-09T23:13:57.867Z" }, - { url = "https://files.pythonhosted.org/packages/d8/ae/7d2089bcd78ad0c0161bc684339df50032acb438a7bd3305e7ddb1193cec/regex-2026.5.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:205109e96b3cf5adf8f4cd62bedde9487feb282b9497a3535451e5a24cd706a0", size = 856584, upload-time = "2026-05-09T23:13:59.679Z" }, - { url = "https://files.pythonhosted.org/packages/a9/29/92ff47f75990131ea4f24ba17819e5a9d141e10819807e09addd73409af6/regex-2026.5.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dfbe4579b9f08036aa7d101d1835437a20783574ac66327e6b29b4018a138081", size = 803453, upload-time = "2026-05-09T23:14:01.978Z" }, - { url = "https://files.pythonhosted.org/packages/04/99/eff29f1037dcab36702c9ee5d6858cf1ce2336ea8ea2987f64245b99ea5e/regex-2026.5.9-cp313-cp313t-win32.whl", hash = "sha256:ed2c9e8068b614c574d8d30e543d617cf5379b0535d46f97ef00e904745a08b5", size = 269951, upload-time = "2026-05-09T23:14:03.661Z" }, - { url = "https://files.pythonhosted.org/packages/0e/9d/8870b8981d27b22cda77bb26a5ac7ebfa9c7d9e0dea195a834a82380e748/regex-2026.5.9-cp313-cp313t-win_amd64.whl", hash = "sha256:b46b0f094dc1d3b90356c85a0bd2c9bafc4a6a190b9d6f8ddd5a033b6e088ed4", size = 281240, upload-time = "2026-05-09T23:14:05.56Z" }, - { url = "https://files.pythonhosted.org/packages/72/b1/3379415e8f135c13ac551353397cc4fe97b4978f3cac73c5fcbcded548b8/regex-2026.5.9-cp313-cp313t-win_arm64.whl", hash = "sha256:872acc074bd29ffc9913ecdfedf6ea77502312ca44a4aa0d3779089c6069d8de", size = 272383, upload-time = "2026-05-09T23:14:07.843Z" }, ] [[package]] @@ -4432,6 +3906,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl", hash = "sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7", size = 7676, upload-time = "2025-12-17T18:25:33.098Z" }, ] +[[package]] +name = "ruff" +version = "0.16.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/25/7113f6d5498888c5fb7db34081cba7d5971c4cb1bfb26819966eee68f003/ruff-0.16.1.tar.gz", hash = "sha256:fedad7c801dabd3fb9741d76aca39246e6ddd9ca446a015875207bf19f1e6bc7", size = 4877500, upload-time = "2026-07-30T19:37:01.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/bd/694da69368e0973de65df2ddc73ab18d43c469d5963d9b150911de6bc513/ruff-0.16.1-py3-none-linux_armv6l.whl", hash = "sha256:58edb313b88f0c5460a26adf5f39a37a3be789494a15e3e411e35fa78b89f9a0", size = 10839126, upload-time = "2026-07-30T19:36:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f0/b626e5d5bd0dd9576263658ef12885e2288afd1029a48e26ffed65ec1ac1/ruff-0.16.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fde5a99e2f97479af66edd6622c6d5a2a7592c77cf4153d9e4428f5eeb55b60c", size = 11070253, upload-time = "2026-07-30T19:36:17.14Z" }, + { url = "https://files.pythonhosted.org/packages/83/63/f40acfb6b35b88623e71684942b552c3edd96035f5d98f313815f7b277de/ruff-0.16.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e0d4c20532fca4f7fa609369161d968dd28f65d83dabbd61d8e9c7edbf7001f6", size = 10561425, upload-time = "2026-07-30T19:36:20.04Z" }, + { url = "https://files.pythonhosted.org/packages/aa/dd/14ec0e9c2b4d315547dd38765004b4863e354e1b52cb308272215d9f6f6d/ruff-0.16.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30affbcedf59ad5703d9c91f82266e02b47739f797e1a7b6e158e5526a6dae38", size = 10948879, upload-time = "2026-07-30T19:36:22.476Z" }, + { url = "https://files.pythonhosted.org/packages/33/e9/9d870cbae575030fdef595f04b4b97573c525b5497cce4f4498cf2f85446/ruff-0.16.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24e9c631573cbca9d20f1283f8f479b2afa4a8503504822bd71a293889f16743", size = 10643691, upload-time = "2026-07-30T19:36:24.914Z" }, + { url = "https://files.pythonhosted.org/packages/c4/09/12743d544e2173f53ecd27217c65f90d2bc0f8424a66a60339e56bbc0457/ruff-0.16.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b41bdd48fb420987a9b5212e4957c26ad4abce401fa9ea9d4d85843727945f4f", size = 11435354, upload-time = "2026-07-30T19:36:28.447Z" }, + { url = "https://files.pythonhosted.org/packages/7f/89/a1652b2daee52083c9554a6333b678a8b01d0400f976827bb87857f9449a/ruff-0.16.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b0d1e1393b7648079e13669de1c1f4fde06d4583e84d8fd5c1551e0a77a2aa75", size = 12259033, upload-time = "2026-07-30T19:36:31.326Z" }, + { url = "https://files.pythonhosted.org/packages/16/96/ecdcb8c54ee7b123b487f807eb014e6e019155a0b81dfb669acd52f28ce3/ruff-0.16.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07bf434b1c95f4e093be4532068ef4fcf00924eb2ade8796075980902d6fd54a", size = 11667981, upload-time = "2026-07-30T19:36:34.394Z" }, + { url = "https://files.pythonhosted.org/packages/cd/90/c52e12e0d862e9572f2a33aa227409143520abe53111e9a6babbac7b4af8/ruff-0.16.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39897739f112253ee4fdd2e8aa9a4f9ded99fb2be367d5f31dfa4ded6025584c", size = 11468183, upload-time = "2026-07-30T19:36:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6b/4ffb7ad1d83eb16cf8cbb3c8815d3f11c88460fd162d4b372a2059be1c2a/ruff-0.16.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:82ae3c0c0d74daf17b968a10b7b3bb3ef297ab7de0c1f749646b25e690ccb150", size = 11470071, upload-time = "2026-07-30T19:36:39.91Z" }, + { url = "https://files.pythonhosted.org/packages/9c/72/32ae7db4c0b5e32ab611787caa19d1546800676d79f7483b7100a3561bf4/ruff-0.16.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4d5f2ed10f8242d83fc08d521301089364e3375375705356f20c0e31606ef3ef", size = 10919503, upload-time = "2026-07-30T19:36:42.65Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ca/3d901ba6ad6fc38da39c3448fc6c59ac945679293a17c3ceb6d6c1cba13e/ruff-0.16.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a4665b309891f83f3e3c25447935f1213e9abbd4b5640af7a1f2def9f8d413c1", size = 10649861, upload-time = "2026-07-30T19:36:45.18Z" }, + { url = "https://files.pythonhosted.org/packages/92/79/894ef1ced26552d5f8c9cf6d85b0687840e1128c55aeab7b9c2d54a0d880/ruff-0.16.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26e9ca5c9bc3971f20d3cf18a957f52ffd6a5f6564ff15c4912a144dcac22494", size = 11148137, upload-time = "2026-07-30T19:36:47.936Z" }, + { url = "https://files.pythonhosted.org/packages/2d/69/3609a09fa1cb46cc28b762363e440a354204e5dff01bd0c8d7437874d6b9/ruff-0.16.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:67e1e1e3fa4f0c82f0e36d4cd61e661f6e7a6196cb1aa92fe0828fa7b8f257cd", size = 11559211, upload-time = "2026-07-30T19:36:50.448Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/fb22af2fd78a736e241fabf67e30ce1799a64244026377a49e133af90762/ruff-0.16.1-py3-none-win32.whl", hash = "sha256:d31765e131295b8445caf301e3e8a85b34d1b9b211b4109b7ba457888b051806", size = 10838258, upload-time = "2026-07-30T19:36:53.298Z" }, + { url = "https://files.pythonhosted.org/packages/d4/35/e57fd9fb5d423961df087a00b12d42c0a830288dc2f3b45ecca299158b4f/ruff-0.16.1-py3-none-win_amd64.whl", hash = "sha256:09b05e8b90c2cb06ad63464350e7a45e8e44a2dfe52072ebfba6666ca8d3f596", size = 11961111, upload-time = "2026-07-30T19:36:56.107Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/240ea004bf6dc4feb40e9832f2205a476a47dd5b8a3f8211a5fc5f95e20e/ruff-0.16.1-py3-none-win_arm64.whl", hash = "sha256:dbaadaac38c70239f056d306b7476f246b0bf000fa6b3876402acbf5b227eaf8", size = 11309414, upload-time = "2026-07-30T19:36:58.79Z" }, +] + [[package]] name = "s3transfer" version = "0.19.0" @@ -4508,24 +4007,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e", size = 36885140, upload-time = "2025-05-08T16:06:39.249Z" }, { url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539", size = 39710549, upload-time = "2025-05-08T16:06:45.729Z" }, { url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed", size = 40966184, upload-time = "2025-05-08T16:06:52.623Z" }, - { url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", size = 38728256, upload-time = "2025-05-08T16:06:58.696Z" }, - { url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", size = 30109540, upload-time = "2025-05-08T16:07:04.209Z" }, - { url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", size = 22383115, upload-time = "2025-05-08T16:07:08.998Z" }, - { url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", size = 25163884, upload-time = "2025-05-08T16:07:14.091Z" }, - { url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", size = 35174018, upload-time = "2025-05-08T16:07:19.427Z" }, - { url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", size = 37269716, upload-time = "2025-05-08T16:07:25.712Z" }, - { url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", size = 36872342, upload-time = "2025-05-08T16:07:31.468Z" }, - { url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126", size = 39670869, upload-time = "2025-05-08T16:07:38.002Z" }, - { url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", size = 40988851, upload-time = "2025-05-08T16:08:33.671Z" }, - { url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", size = 38863011, upload-time = "2025-05-08T16:07:44.039Z" }, - { url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", size = 30266407, upload-time = "2025-05-08T16:07:49.891Z" }, - { url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", size = 22540030, upload-time = "2025-05-08T16:07:54.121Z" }, - { url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", size = 25218709, upload-time = "2025-05-08T16:07:58.506Z" }, - { url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", size = 34809045, upload-time = "2025-05-08T16:08:03.929Z" }, - { url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", size = 36703062, upload-time = "2025-05-08T16:08:09.558Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", size = 36393132, upload-time = "2025-05-08T16:08:15.34Z" }, - { url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", size = 38979503, upload-time = "2025-05-08T16:08:21.513Z" }, - { url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", size = 40308097, upload-time = "2025-05-08T16:08:27.627Z" }, ] [[package]] @@ -4561,26 +4042,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/65/94/7698add8f276dbab7a9de9fb6b0e02fc13ee61d51c7c3f85ac28b65e1239/scipy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea", size = 37625856, upload-time = "2026-02-23T00:19:00.307Z" }, { url = "https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87", size = 36549682, upload-time = "2026-02-23T00:19:07.67Z" }, { url = "https://files.pythonhosted.org/packages/bc/98/fe9ae9ffb3b54b62559f52dedaebe204b408db8109a8c66fdd04869e6424/scipy-1.17.1-cp312-cp312-win_arm64.whl", hash = "sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3", size = 24547340, upload-time = "2026-02-23T00:19:12.024Z" }, - { url = "https://files.pythonhosted.org/packages/76/27/07ee1b57b65e92645f219b37148a7e7928b82e2b5dbeccecb4dff7c64f0b/scipy-1.17.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c", size = 31590199, upload-time = "2026-02-23T00:19:17.192Z" }, - { url = "https://files.pythonhosted.org/packages/ec/ae/db19f8ab842e9b724bf5dbb7db29302a91f1e55bc4d04b1025d6d605a2c5/scipy-1.17.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f", size = 28154001, upload-time = "2026-02-23T00:19:22.241Z" }, - { url = "https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d", size = 20325719, upload-time = "2026-02-23T00:19:26.329Z" }, - { url = "https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b", size = 22683595, upload-time = "2026-02-23T00:19:30.304Z" }, - { url = "https://files.pythonhosted.org/packages/b4/e0/e58fbde4a1a594c8be8114eb4aac1a55bcd6587047efc18a61eb1f5c0d30/scipy-1.17.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6", size = 32896429, upload-time = "2026-02-23T00:19:35.536Z" }, - { url = "https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464", size = 35203952, upload-time = "2026-02-23T00:19:42.259Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a5/9afd17de24f657fdfe4df9a3f1ea049b39aef7c06000c13db1530d81ccca/scipy-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950", size = 34979063, upload-time = "2026-02-23T00:19:47.547Z" }, - { url = "https://files.pythonhosted.org/packages/8b/13/88b1d2384b424bf7c924f2038c1c409f8d88bb2a8d49d097861dd64a57b2/scipy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369", size = 37598449, upload-time = "2026-02-23T00:19:53.238Z" }, - { url = "https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448", size = 36510943, upload-time = "2026-02-23T00:20:50.89Z" }, - { url = "https://files.pythonhosted.org/packages/2a/fd/3be73c564e2a01e690e19cc618811540ba5354c67c8680dce3281123fb79/scipy-1.17.1-cp313-cp313-win_arm64.whl", hash = "sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87", size = 24545621, upload-time = "2026-02-23T00:20:55.871Z" }, - { url = "https://files.pythonhosted.org/packages/6f/6b/17787db8b8114933a66f9dcc479a8272e4b4da75fe03b0c282f7b0ade8cd/scipy-1.17.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a", size = 31936708, upload-time = "2026-02-23T00:19:58.694Z" }, - { url = "https://files.pythonhosted.org/packages/38/2e/524405c2b6392765ab1e2b722a41d5da33dc5c7b7278184a8ad29b6cb206/scipy-1.17.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0", size = 28570135, upload-time = "2026-02-23T00:20:03.934Z" }, - { url = "https://files.pythonhosted.org/packages/fd/c3/5bd7199f4ea8556c0c8e39f04ccb014ac37d1468e6cfa6a95c6b3562b76e/scipy-1.17.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce", size = 20741977, upload-time = "2026-02-23T00:20:07.935Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b8/8ccd9b766ad14c78386599708eb745f6b44f08400a5fd0ade7cf89b6fc93/scipy-1.17.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6", size = 23029601, upload-time = "2026-02-23T00:20:12.161Z" }, - { url = "https://files.pythonhosted.org/packages/6d/a0/3cb6f4d2fb3e17428ad2880333cac878909ad1a89f678527b5328b93c1d4/scipy-1.17.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e", size = 33019667, upload-time = "2026-02-23T00:20:17.208Z" }, - { url = "https://files.pythonhosted.org/packages/f3/c3/2d834a5ac7bf3a0c806ad1508efc02dda3c8c61472a56132d7894c312dea/scipy-1.17.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475", size = 35264159, upload-time = "2026-02-23T00:20:23.087Z" }, - { url = "https://files.pythonhosted.org/packages/4d/77/d3ed4becfdbd217c52062fafe35a72388d1bd82c2d0ba5ca19d6fcc93e11/scipy-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50", size = 35102771, upload-time = "2026-02-23T00:20:28.636Z" }, - { url = "https://files.pythonhosted.org/packages/bd/12/d19da97efde68ca1ee5538bb261d5d2c062f0c055575128f11a2730e3ac1/scipy-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca", size = 37665910, upload-time = "2026-02-23T00:20:34.743Z" }, - { url = "https://files.pythonhosted.org/packages/06/1c/1172a88d507a4baaf72c5a09bb6c018fe2ae0ab622e5830b703a46cc9e44/scipy-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c", size = 36562980, upload-time = "2026-02-23T00:20:40.575Z" }, - { url = "https://files.pythonhosted.org/packages/70/b0/eb757336e5a76dfa7911f63252e3b7d1de00935d7705cf772db5b45ec238/scipy-1.17.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49", size = 24856543, upload-time = "2026-02-23T00:20:45.313Z" }, ] [[package]] @@ -4606,16 +4067,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/ca/210d4759c7210bb7d269437421959b39a33434e2776b60c5cb8a763bb30a/scipy-1.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a55985d54c769c872e64b7f4c8a81cc30ef700cc04296abbbf3705439c126de", size = 37421717, upload-time = "2026-06-19T15:00:05.102Z" }, { url = "https://files.pythonhosted.org/packages/2b/54/9a9edb45345bd6744da5ddfb6628e5d5185920494c6a67ec45b6381004cb/scipy-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:71ccc8faa2dd16ac310233203474a8b5cb67f10dedd54a3116d34943f4b19132", size = 36597428, upload-time = "2026-06-19T15:00:08.112Z" }, { url = "https://files.pythonhosted.org/packages/99/0e/33f32a2a58987e26aec0f7df252cbbad1e90ae77bdbc76f40dd4ed0cf0ea/scipy-1.18.0-cp312-cp312-win_arm64.whl", hash = "sha256:d88363fd9d8fbd3511bd273f1a49efb2a540773ddf92a91d57498ce7dd7f3e76", size = 24351481, upload-time = "2026-06-19T15:00:11.103Z" }, - { url = "https://files.pythonhosted.org/packages/05/52/9c0136c2de7ae0779b7b366447766cec6d9f0702c56bb8ffeb04c8fd3af4/scipy-1.18.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:09143f676d157d9f546d663504ef9c1becb819824f1afc018814176411942446", size = 31036107, upload-time = "2026-06-19T15:00:14.03Z" }, - { url = "https://files.pythonhosted.org/packages/02/73/0291a64843270f4efb86cdcf2ee0f2048631b65ec6b405398b2b4dbf11bf/scipy-1.18.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:5efe260f69417b97ddae455bfb5a95e8359f7f66ad7fa9522a60feb66f169520", size = 28663303, upload-time = "2026-06-19T15:00:16.819Z" }, - { url = "https://files.pythonhosted.org/packages/d3/0f/10ffa0b697a572f4e0d48b92a88895d366422f019f723e7e14a84c050dac/scipy-1.18.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:68363b7eaacd8b5dd426df56d782cc156468ac79a127a1b87ca597d6e2e82197", size = 20404960, upload-time = "2026-06-19T15:00:19.635Z" }, - { url = "https://files.pythonhosted.org/packages/7e/d2/e896cea21ba8edd6c81d4c55b1ffcc717e79698dcbebf9641b4cfb4c6622/scipy-1.18.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:c5557d8be5da8e41353fcd4d21491fdbab83b062fc579e94dc09a7c8ab4f669b", size = 23034074, upload-time = "2026-06-19T15:00:22.107Z" }, - { url = "https://files.pythonhosted.org/packages/ea/b2/e83ea34279a52c03374477c74006256ec78df65fc877baa4617d6de1d202/scipy-1.18.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0d13bca67c096d89fb95ced0d8921807300fce0275643aef9533cc63a0773468", size = 33942038, upload-time = "2026-06-19T15:00:24.964Z" }, - { url = "https://files.pythonhosted.org/packages/f6/af/e8fe5fb136f51e2b01678b92cb4106d10d8cd68ec147ead2e7cb0ac75398/scipy-1.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a46f9273dbd0eb1cefba61c9b8648b4dfe3cbc14a080176f9a73e44b8336dc7f", size = 35266390, upload-time = "2026-06-19T15:00:28.059Z" }, - { url = "https://files.pythonhosted.org/packages/3a/49/2c5cbb907b56695fc67517811d1db234dfd83381a84814ec220aded2794d/scipy-1.18.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5aba46108853ddfc77906b6557aac839d2b52e900c1d72a1180adaaab58d265f", size = 35551324, upload-time = "2026-06-19T15:00:31.014Z" }, - { url = "https://files.pythonhosted.org/packages/bb/73/eda39f7a2d306ff0ffc574afd13c0bbb6d10a603d9a413998ee269487a80/scipy-1.18.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b6f758e35f12757b5d95c00bc6de2438e229c2664b7a92e96f205959d9f2dfa4", size = 37404785, upload-time = "2026-06-19T15:00:34.072Z" }, - { url = "https://files.pythonhosted.org/packages/b7/d2/ae881ee28d014f38e0ccbfd974a06a919ba9af34f1f74bf42b5301891d63/scipy-1.18.0-cp313-cp313-win_amd64.whl", hash = "sha256:1afac4a847207c7ff8efd321734a50b06d0280b3b2a2c0fc2f413101747ad7c7", size = 36554943, upload-time = "2026-06-19T15:00:36.903Z" }, - { url = "https://files.pythonhosted.org/packages/70/3a/21154e2d54eb3639c6bf4dbae2e531c68356bfe95990daa30df33b30d556/scipy-1.18.0-cp313-cp313-win_arm64.whl", hash = "sha256:c5dbddf60e58c2312316d097271a8e73d40eaf2eabfa4d95ed7d3695bbf2ce7b", size = 24350911, upload-time = "2026-06-19T15:00:40.062Z" }, ] [[package]] @@ -4645,20 +4096,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b6/2d/37e3da037318a70066ded0d51bc2a7f35491ae6338dd993d5eb1503fc3b5/sentencepiece-0.2.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c8a168b040bc61681293f79a949b5d911c8e25086f4260285b8d97ab5f1195da", size = 1397736, upload-time = "2026-07-12T08:38:35.771Z" }, { url = "https://files.pythonhosted.org/packages/8d/11/753fca2e6b109be3ab7867abf357dfe48677fe726ae5a5363d0b54ca9450/sentencepiece-0.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:7c6e7bf684dc12145bfa685d3060beaea55139134ba848289bee514ed42e7383", size = 1248030, upload-time = "2026-07-12T08:38:37.604Z" }, { url = "https://files.pythonhosted.org/packages/e2/0a/70efbe861ca182d7d4b6e1a20f58e043400848fa9f2915229f082e221648/sentencepiece-0.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:76ff5814db72e7462dece042d7593cdf102b8ec82c2b1cc201a2add34ee3050d", size = 1187325, upload-time = "2026-07-12T08:38:39.348Z" }, - { url = "https://files.pythonhosted.org/packages/b9/a3/b3b05095c174d6e80d37d5ddc2f57c2c56237333e7bbd6079cf3243c2a8a/sentencepiece-0.2.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:77c3ce990b23441e5ecfa5bce181fd6f408b564aeb6d7e1d1e7de9c5612501c8", size = 2188346, upload-time = "2026-07-12T08:38:41.089Z" }, - { url = "https://files.pythonhosted.org/packages/ca/f3/72ebc4acb10a06bcf7503fbc6091c8f5db68300f6aac4356c09e6c76e0e1/sentencepiece-0.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fd523c4992041faa5c2b3cde62253d11a96c30d73a34afe48a486e8e2254cd1c", size = 1441434, upload-time = "2026-07-12T08:38:42.56Z" }, - { url = "https://files.pythonhosted.org/packages/34/db/f9ea1a6844b4fa5dfe2312095cd866a1f724cd0905054ab9d5991778ba50/sentencepiece-0.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:201a8e0f55501a76e08dbf2c54bc45f4642b379271e89c667d517bfbc2191f2a", size = 1347267, upload-time = "2026-07-12T08:38:44.389Z" }, - { url = "https://files.pythonhosted.org/packages/32/4f/31c1073314ad94466bca37d29581761d70110237ee3d46b0efece59a8c1e/sentencepiece-0.2.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8eed98514bffe5ecac37f493f91869c351fbb05629328bfdbc08502c6c094dc0", size = 1324980, upload-time = "2026-07-12T08:38:46.304Z" }, - { url = "https://files.pythonhosted.org/packages/59/b4/a0356fa04d6a14337a6e0e443556785a0422c53ec58baae6b9568120eb0f/sentencepiece-0.2.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64b656f025355cf8c51abe9fbe3848540756c6d7ca5e6791b1afa664bc24c7cb", size = 1397593, upload-time = "2026-07-12T08:38:48.302Z" }, - { url = "https://files.pythonhosted.org/packages/09/fa/d2d6369257fd2f0de616b1c7110b73fab409ef61b14f1b9e0010ed325914/sentencepiece-0.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:74f0ee601047c0c12a783088b51be4e6214a62ecd9e02278c477433cd16e0ed9", size = 1247987, upload-time = "2026-07-12T08:38:50.15Z" }, - { url = "https://files.pythonhosted.org/packages/17/ee/2bb594da6fd95e32f29057f1aa7fa996701b8980090923c2d8711fdc0a24/sentencepiece-0.2.2-cp313-cp313-win_arm64.whl", hash = "sha256:b23fe17779834d3c27aaf2edac9486d04cca1a7deb8f5facda35150ac6263a91", size = 1187250, upload-time = "2026-07-12T08:38:52.246Z" }, - { url = "https://files.pythonhosted.org/packages/58/9c/dfc82846460e7a712310f5613f23d8b553cabb4e2e648663c11d8382af56/sentencepiece-0.2.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:72b7825b331b1b7e7c45be2e674b3e3c65af608fa376bad2d851b20aaf0cdc78", size = 2223080, upload-time = "2026-07-12T08:38:54.391Z" }, - { url = "https://files.pythonhosted.org/packages/8d/4e/3ff12cebe6d31662d9ceeabfb282de20bd0d6098fa282b4a3b8305abc7e8/sentencepiece-0.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d795c4ac689a57f9d4ba2288126ec7901d389ad5827d2f8b8533c883974fe563", size = 1458511, upload-time = "2026-07-12T08:38:56.811Z" }, - { url = "https://files.pythonhosted.org/packages/59/5a/16d51d05360be4cee3ebfe4837c184054c4eed16cabaeb3b039524e9a000/sentencepiece-0.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ab3f1ae98970b5590e2209341522718900ba19bcc2c207ffaa6bd417ad960c5", size = 1361138, upload-time = "2026-07-12T08:38:58.808Z" }, - { url = "https://files.pythonhosted.org/packages/0f/af/c30ee2a9f99d51db9844acaa8fa0b611a97c2fa7116646fa43db3300b187/sentencepiece-0.2.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ec27c152a1f1b24bc9168b55a5880f3c16e2334e697da6f55a1046a22405a3d", size = 1328625, upload-time = "2026-07-12T08:39:00.849Z" }, - { url = "https://files.pythonhosted.org/packages/3e/1a/4c6b39d03f5ba8439509adbd5a23c9538088a3cb679e7a47b911e8442bc6/sentencepiece-0.2.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59d6588712101ccfcae9b03692be3aaae1514c2078666d7b05f15ba3a702e41b", size = 1398595, upload-time = "2026-07-12T08:39:02.86Z" }, - { url = "https://files.pythonhosted.org/packages/0f/bc/9eedddcec1fd57bc70200fa3ebf792d18fa63527a5369581cd416c81f97f/sentencepiece-0.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:89625fb43765cccaa1443b9adb61f283e5fe4cb1536728205d06bada730caa53", size = 1259346, upload-time = "2026-07-12T08:39:04.559Z" }, - { url = "https://files.pythonhosted.org/packages/41/15/7e74c8533848866ff560b29f7d8719921b76c4ec7149592d6d28e0deee75/sentencepiece-0.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:4f0603267cd15b92b68c2c0e852a441507614b70dc7773659baa6b8c214a91fd", size = 1196596, upload-time = "2026-07-12T08:39:06.454Z" }, ] [[package]] @@ -4704,22 +4141,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/a0/704c7292f7014c7e74ec84eddb7b109e1fbae74a16deae9c1504b1d15565/shapely-2.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:980c777c612514c0cf99bc8a9de6d286f5e186dcaf9091252fcd444e5638193d", size = 4152714, upload-time = "2025-09-24T13:50:39.9Z" }, { url = "https://files.pythonhosted.org/packages/53/46/319c9dc788884ad0785242543cdffac0e6530e4d0deb6c4862bc4143dcf3/shapely-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9111274b88e4d7b54a95218e243282709b330ef52b7b86bc6aaf4f805306f454", size = 1542745, upload-time = "2025-09-24T13:50:41.414Z" }, { url = "https://files.pythonhosted.org/packages/ec/bf/cb6c1c505cb31e818e900b9312d514f381fbfa5c4363edfce0fcc4f8c1a4/shapely-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:743044b4cfb34f9a67205cee9279feaf60ba7d02e69febc2afc609047cb49179", size = 1722861, upload-time = "2025-09-24T13:50:43.35Z" }, - { url = "https://files.pythonhosted.org/packages/c3/90/98ef257c23c46425dc4d1d31005ad7c8d649fe423a38b917db02c30f1f5a/shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8", size = 1832644, upload-time = "2025-09-24T13:50:44.886Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ab/0bee5a830d209adcd3a01f2d4b70e587cdd9fd7380d5198c064091005af8/shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a", size = 1642887, upload-time = "2025-09-24T13:50:46.735Z" }, - { url = "https://files.pythonhosted.org/packages/2d/5e/7d7f54ba960c13302584c73704d8c4d15404a51024631adb60b126a4ae88/shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e", size = 2970931, upload-time = "2025-09-24T13:50:48.374Z" }, - { url = "https://files.pythonhosted.org/packages/f2/a2/83fc37e2a58090e3d2ff79175a95493c664bcd0b653dd75cb9134645a4e5/shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6", size = 3082855, upload-time = "2025-09-24T13:50:50.037Z" }, - { url = "https://files.pythonhosted.org/packages/44/2b/578faf235a5b09f16b5f02833c53822294d7f21b242f8e2d0cf03fb64321/shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af", size = 3979960, upload-time = "2025-09-24T13:50:51.74Z" }, - { url = "https://files.pythonhosted.org/packages/4d/04/167f096386120f692cc4ca02f75a17b961858997a95e67a3cb6a7bbd6b53/shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd", size = 4142851, upload-time = "2025-09-24T13:50:53.49Z" }, - { url = "https://files.pythonhosted.org/packages/48/74/fb402c5a6235d1c65a97348b48cdedb75fb19eca2b1d66d04969fc1c6091/shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350", size = 1541890, upload-time = "2025-09-24T13:50:55.337Z" }, - { url = "https://files.pythonhosted.org/packages/41/47/3647fe7ad990af60ad98b889657a976042c9988c2807cf322a9d6685f462/shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715", size = 1722151, upload-time = "2025-09-24T13:50:57.153Z" }, - { url = "https://files.pythonhosted.org/packages/3c/49/63953754faa51ffe7d8189bfbe9ca34def29f8c0e34c67cbe2a2795f269d/shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40", size = 1834130, upload-time = "2025-09-24T13:50:58.49Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ee/dce001c1984052970ff60eb4727164892fb2d08052c575042a47f5a9e88f/shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b", size = 1642802, upload-time = "2025-09-24T13:50:59.871Z" }, - { url = "https://files.pythonhosted.org/packages/da/e7/fc4e9a19929522877fa602f705706b96e78376afb7fad09cad5b9af1553c/shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801", size = 3018460, upload-time = "2025-09-24T13:51:02.08Z" }, - { url = "https://files.pythonhosted.org/packages/a1/18/7519a25db21847b525696883ddc8e6a0ecaa36159ea88e0fef11466384d0/shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0", size = 3095223, upload-time = "2025-09-24T13:51:04.472Z" }, - { url = "https://files.pythonhosted.org/packages/48/de/b59a620b1f3a129c3fecc2737104a0a7e04e79335bd3b0a1f1609744cf17/shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c", size = 4030760, upload-time = "2025-09-24T13:51:06.455Z" }, - { url = "https://files.pythonhosted.org/packages/96/b3/c6655ee7232b417562bae192ae0d3ceaadb1cc0ffc2088a2ddf415456cc2/shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99", size = 4170078, upload-time = "2025-09-24T13:51:08.584Z" }, - { url = "https://files.pythonhosted.org/packages/a0/8e/605c76808d73503c9333af8f6cbe7e1354d2d238bda5f88eea36bfe0f42a/shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf", size = 1559178, upload-time = "2025-09-24T13:51:10.73Z" }, - { url = "https://files.pythonhosted.org/packages/36/f7/d317eb232352a1f1444d11002d477e54514a4a6045536d49d0c59783c0da/shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c", size = 1739756, upload-time = "2025-09-24T13:51:12.105Z" }, ] [[package]] @@ -4762,10 +4183,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/bc/446357c229692f51885f4c5f3894af3aff37ccaafebc4f24066c2b9b5b80/slangpy-0.42.0-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:4e2f76d3709ee2152f54620a27ab45fbb459db392c03b2d492382f675bfccc2a", size = 82123007, upload-time = "2026-05-28T22:40:30.815Z" }, { url = "https://files.pythonhosted.org/packages/cd/d1/d9822a2c38dc583850608650e6d3304f6cf6e03a1335ba21078440790a68/slangpy-0.42.0-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:8dbc36b32c1c1fc8dffa70d63ddf0ab538c473ba072f802c8d7730530bea7a7c", size = 83670144, upload-time = "2026-05-28T22:40:37.618Z" }, { url = "https://files.pythonhosted.org/packages/b7/b8/94d067236898b5bec62a7ae682c296ba2310ebf9aa894bb32de9a4cfd478/slangpy-0.42.0-cp312-cp312-win_amd64.whl", hash = "sha256:82e212b7b195aeafb23ab43a43069980e3be0952f91869b65b5b4288bad9129d", size = 78280523, upload-time = "2026-05-28T22:40:44.154Z" }, - { url = "https://files.pythonhosted.org/packages/15/3c/44f8d8c20b83e10dc2dffc45d9a93adc3e6d037ec1b72756e8dfeec9cd7d/slangpy-0.42.0-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:c070359285acf177fb7f4ca6cbd29c6c7f37a9b036f42f436353aa773c08e665", size = 37738648, upload-time = "2026-05-28T22:40:48.454Z" }, - { url = "https://files.pythonhosted.org/packages/da/23/6427597cd186477c6020124883eb1f5d7e15ae4e46bb7ee60125fbc30979/slangpy-0.42.0-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:07a8a5bb32e5644ea0226e40db5c773f1218c901883e70d2f7b20ceef433f724", size = 82125926, upload-time = "2026-05-28T22:40:54.468Z" }, - { url = "https://files.pythonhosted.org/packages/9f/b1/cbde95d04d94d2c3f0241b54354f5e792e64a1c1643b4424a2ccb80f2788/slangpy-0.42.0-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:4c26022765a414925efde972e26ca3f99458435879c1133c6bbe2e962a6c2c16", size = 83670289, upload-time = "2026-05-28T22:41:00.771Z" }, - { url = "https://files.pythonhosted.org/packages/83/9e/e57c578d8a576ddfea74f2f11d561d2ceca6b4fd92fa1341dc3d93a6b7f8/slangpy-0.42.0-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a32184bce8a8c507adbfedf5b49694f55543223c019a3c540ffe4a7df1730", size = 78280954, upload-time = "2026-05-28T22:41:06.903Z" }, ] [[package]] @@ -5050,7 +4467,7 @@ version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, - { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-11-flashdreams-dev' and extra == 'group-11-flashdreams-cuda12') or (extra == 'group-11-flashdreams-cuda12' and extra == 'group-11-flashdreams-cuda13')" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } wheels = [ @@ -5123,15 +4540,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, - { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, - { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, - { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, - { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, - { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, - { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, - { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, - { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] @@ -5171,12 +4579,6 @@ wheels = [ { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9c8f38efee365cb9d334de8a83ce52fc7e5fc9e5a7b0853285efa1b69e00b0f2", upload-time = "2026-04-27T17:41:30Z" }, { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d252cf975fb18c94a85336323ad425f473df56dab35a44b00399bd70c7a3b997", upload-time = "2026-04-27T17:42:06Z" }, { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp312-cp312-win_amd64.whl", hash = "sha256:7c78215c3af4f62e63f2b2e360f1722fc719b0853c7ac22666483d9810613a4c", upload-time = "2026-04-27T17:43:49Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:7db3580106bba044da5b8950f3fb8fe5f31999eaab3f6a3aa2ac5d202c3684d2", upload-time = "2026-04-27T17:45:35Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:db964b33c55035a72ab3e2162287af8f1cc276039c65d015740cc88c26dcedf7", upload-time = "2026-04-27T17:46:18Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp313-cp313-win_amd64.whl", hash = "sha256:6f367e62fd81b75cdf23ca4b75ced834d2db2cf98d1588ac935bde345de9de23", upload-time = "2026-04-27T17:48:09Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd1cf1005c5fe419194ee294b7b584ba5ad0f2fb1778b3fe5a7b9c3f4617ddbc", upload-time = "2026-04-27T17:50:01Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:74b628dbc71603977b09f4e140792c6e997081a35ef3421555f3f6e201b81210", upload-time = "2026-04-27T17:50:42Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torch-2.11.0%2Bcu128-cp313-cp313t-win_amd64.whl", hash = "sha256:c2a5984deba8e001d166bf9cb83b8351f63a28b009e1a2fa0e4bbf08c90b259b", upload-time = "2026-04-27T17:52:32Z" }, ] [[package]] @@ -5219,10 +4621,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/00/4210d76ca7424981f04033ebe7e48816ab83287a62538747a58825db770c/torch-2.12.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2de4e19b88a481482c6c75291f2d6a52eda3ce51f311b29aa9b68499c830c07c", size = 426382721, upload-time = "2026-06-17T21:06:41.842Z" }, { url = "https://files.pythonhosted.org/packages/76/1f/bc9f5a5aa569307076365f25afcebacb22e9c754b1bcfbaaa146627c7fda/torch-2.12.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:649e4ced014ba646f76f8cb9c9726735a6323eb321b7919f942790a923f90921", size = 532261322, upload-time = "2026-06-17T21:06:06.673Z" }, { url = "https://files.pythonhosted.org/packages/9e/49/c549461daa008159d006a76a991fbc2f26fa8bac27a4030c858463dcb20f/torch-2.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:e86550597877fb272ddc52db2f85b82cb601ea7bd932576a0340152cae2200b3", size = 122988095, upload-time = "2026-06-17T21:07:44.9Z" }, - { url = "https://files.pythonhosted.org/packages/ff/4a/0300261818e1560d72cc160ac826005507e8b7ca0a35788b591436d05b4a/torch-2.12.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:c75e93173c700bccd6bfcc4a9d19ce242ab6dacd1f1781483027a16239b9e650", size = 87992358, upload-time = "2026-06-17T21:07:40.299Z" }, - { url = "https://files.pythonhosted.org/packages/30/a7/874a5ca05e8f159211dca7921060f7057acc1adb26431e119fd150623efc/torch-2.12.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:fcb61ccd20784b62bdd78ec84238a5cfb383b4994902e03bac95505ab360884c", size = 426386134, upload-time = "2026-06-17T21:07:31.481Z" }, - { url = "https://files.pythonhosted.org/packages/e1/75/20bb8fe9c1ad6538cce8cd0391b51927ae5af0b17ed1eab44b8824465dc1/torch-2.12.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f4afc8083dff08719edbea346644476e3cec0cf40ebe256be0ee5d5b7c7e8c0d", size = 532268019, upload-time = "2026-06-17T21:05:37.925Z" }, - { url = "https://files.pythonhosted.org/packages/d1/fa/824ddb662af55b2eabc0dbb7b57c7c0b1bcd93693754a2b8509ec4d16490/torch-2.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:f92609e3b3ce72f25e2eb780d043ced2480c1a86c47c852604fc7a9108648386", size = 122987777, upload-time = "2026-06-17T21:07:09.49Z" }, ] [[package]] @@ -5255,9 +4653,6 @@ wheels = [ { url = "https://download-r2.pytorch.org/whl/cu130/torch-2.12.1%2Bcu130-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2d3e87d41ffb340ddf8c99e2a690a29feea9f5271459dd57621cd11317a434f2", upload-time = "2026-06-18T02:38:10Z" }, { url = "https://download-r2.pytorch.org/whl/cu130/torch-2.12.1%2Bcu130-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4bafc356fbb622e2756179406825c3a56c17b401196435a1487c5b40c657706c", upload-time = "2026-06-18T02:38:36Z" }, { url = "https://download-r2.pytorch.org/whl/cu130/torch-2.12.1%2Bcu130-cp312-cp312-win_amd64.whl", hash = "sha256:52c5da6a0898d5d3473c02bd304b7a3bc0b72e351c6f3bfa0783e45ef9f4cd61", upload-time = "2026-06-18T02:39:58Z" }, - { url = "https://download-r2.pytorch.org/whl/cu130/torch-2.12.1%2Bcu130-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:2a2bb858316615b90b14ff27d0c732d5af85d066f5ee7bf81fad2c9215839be7", upload-time = "2026-06-18T02:41:12Z" }, - { url = "https://download-r2.pytorch.org/whl/cu130/torch-2.12.1%2Bcu130-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:d5e1840442d2182957b3d2f778cc325c90fa5cb42aa8b1ac949f029e9bdd7f06", upload-time = "2026-06-18T02:41:44Z" }, - { url = "https://download-r2.pytorch.org/whl/cu130/torch-2.12.1%2Bcu130-cp313-cp313-win_amd64.whl", hash = "sha256:76dd848312a40d29499614b714a4318841734ff309ad922f2365868395b6b054", upload-time = "2026-06-18T02:43:02Z" }, ] [[package]] @@ -5285,12 +4680,6 @@ wheels = [ { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:63e35234aed13b6edda37056f417b5c281249669db631e706811917af36b21d7", upload-time = "2026-04-09T23:21:35Z" }, { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ccf26b4b659cfce6f2208cb8326071d51c70219a34856dfdf468d1e19af52c0d", upload-time = "2026-03-23T15:36:22Z" }, { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp312-cp312-win_amd64.whl", hash = "sha256:8c0d1c4fbb2c9a4d5d41d0aaa87da20e525bcb2a154ce405725b0be59456804b", upload-time = "2026-04-09T23:21:36Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c4a9cacd521f2a4df0bcd9d8e96704771b928f478f1f3067e4085bb53a1da298", upload-time = "2026-04-09T23:21:37Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:cb1f6184a7ba30fba40580e1a01a6604a86c55e79fdda187f40116ee680441ec", upload-time = "2026-03-23T15:36:22Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp313-cp313-win_amd64.whl", hash = "sha256:0232cb219927a52d6c98ff202f32d1cdf4802c2195a85fc1f1a0c1b0b4983a4d", upload-time = "2026-04-09T23:21:38Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:e594732552a8c2fee2ace9c6475c6c6904fc44ccca622ee6765a89a045416a44", upload-time = "2026-04-09T23:21:38Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6168abc019803ac9e97efce27eafd2fdb33db04dcc54a86039537729e5047b29", upload-time = "2026-03-23T15:36:23Z" }, - { url = "https://download-r2.pytorch.org/whl/cu128/torchvision-0.26.0%2Bcu128-cp313-cp313t-win_amd64.whl", hash = "sha256:367d42ea703844ecdb516e9d5eb09929012a58705d2622cf4e9e3c37f278cb85", upload-time = "2026-04-09T23:21:39Z" }, ] [[package]] @@ -5321,10 +4710,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/42/103fa8f9366cfd1329fe449d6b1a25a640c0c17862ed48f21c4af94af322/torchvision-0.27.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9edfb5a549fc2f30ccadb24eca907901e92e426c91a59316be6703a9360e5098", size = 7830902, upload-time = "2026-06-17T21:09:29.739Z" }, { url = "https://files.pythonhosted.org/packages/97/70/fa6052a42110a3657fc94073648da6171220469f4bf9f27e6a0b9378075c/torchvision-0.27.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ae3d49e57c4abc8eafc1a1971f80fc4948a6268fa69340737ca4466936def080", size = 7664211, upload-time = "2026-06-17T21:09:17.206Z" }, { url = "https://files.pythonhosted.org/packages/d0/95/27aca854da7e536a339f46bab1ef67823ac2ac97c59ab2b3203b373d46cf/torchvision-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:0b6e3aa98b7433506bbce1d0d05cb13ec787fc6eb8c5fbd998b26ce05f047543", size = 4079076, upload-time = "2026-06-17T21:09:15.907Z" }, - { url = "https://files.pythonhosted.org/packages/32/bb/b21e0f598ca191bb2a9e9fda2fee37c06ad113313b43c6769dbefa0e921d/torchvision-0.27.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d60311a6d08df905f9656a3a312f0a8f55f0d46321bc737bad30a8dec9644309", size = 1852110, upload-time = "2026-06-17T21:09:22.577Z" }, - { url = "https://files.pythonhosted.org/packages/2f/90/d61171daa5d6cd5f9315f84f9ef947b047a9fdf283d53241327045a8dd6d/torchvision-0.27.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:08aa33bc8e062cca32aefa90ac714916c5a855cbe1ab4c6148fc0453eb40ca5a", size = 7789476, upload-time = "2026-06-17T21:09:13.105Z" }, - { url = "https://files.pythonhosted.org/packages/b8/dc/b21d7801562c23a770e7037989814582f22ca4db479204293561de4b62e8/torchvision-0.27.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:916448be4b19676677b0dbf47d08f68b7955ea0abec7fc79340c31e217a824ba", size = 7664256, upload-time = "2026-06-17T21:09:07.549Z" }, - { url = "https://files.pythonhosted.org/packages/b9/b3/4386976ff77eda55f0aed504a288564f3ff8d170b6db49ee22e172eddfac/torchvision-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:18bc906235bfa901c135acd239f05b8c8ab90d502830cf1ef2cba3301e1f8a23", size = 4150710, upload-time = "2026-06-17T21:09:14.457Z" }, ] [[package]] @@ -5352,9 +4737,6 @@ wheels = [ { url = "https://download-r2.pytorch.org/whl/cu130/torchvision-0.27.1%2Bcu130-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:d2b15508b03a8949d8ff1e67a61342e9191c3fde2bf750996b24b3d472bcd7cb", upload-time = "2026-06-17T15:44:44Z" }, { url = "https://download-r2.pytorch.org/whl/cu130/torchvision-0.27.1%2Bcu130-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:abbfc724597c16da177002a16979aa8c44c4898c97bcb731b647cc57507f5772", upload-time = "2026-06-17T15:44:44Z" }, { url = "https://download-r2.pytorch.org/whl/cu130/torchvision-0.27.1%2Bcu130-cp312-cp312-win_amd64.whl", hash = "sha256:1bf254c102bfaf97d3e7878b76b68999bcd4dcd4303c109e76b4fbf9b15265c5", upload-time = "2026-06-18T04:00:18Z" }, - { url = "https://download-r2.pytorch.org/whl/cu130/torchvision-0.27.1%2Bcu130-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e1d81f9e5f99a73e239e143b73d143181ab2e71a8c8ef79fa90e908cc356218c", upload-time = "2026-06-17T15:44:44Z" }, - { url = "https://download-r2.pytorch.org/whl/cu130/torchvision-0.27.1%2Bcu130-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f9f008d4b1b2f013eaf7bec1a9ff221263581d77668d4e1e0e9c3ed351d56465", upload-time = "2026-06-17T15:44:44Z" }, - { url = "https://download-r2.pytorch.org/whl/cu130/torchvision-0.27.1%2Bcu130-cp313-cp313-win_amd64.whl", hash = "sha256:04f6bda2ab9589ad0a63d44fe6e1dc3ff86f379c100a491b6daba9ec9ec72499", upload-time = "2026-06-18T04:00:19Z" }, ] [[package]] @@ -5460,10 +4842,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/12/b05ba554d2c623bffa59922b94b0775673de251f468a9609bc9e45de95e9/triton-3.6.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8e323d608e3a9bfcc2d9efcc90ceefb764a82b99dea12a86d643c72539ad5d3", size = 188214640, upload-time = "2026-01-20T16:00:35.869Z" }, { url = "https://files.pythonhosted.org/packages/17/5d/08201db32823bdf77a0e2b9039540080b2e5c23a20706ddba942924ebcd6/triton-3.6.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:374f52c11a711fd062b4bfbb201fd9ac0a5febd28a96fb41b4a0f51dde3157f4", size = 176128243, upload-time = "2026-01-20T16:16:07.857Z" }, { url = "https://files.pythonhosted.org/packages/ab/a8/cdf8b3e4c98132f965f88c2313a4b493266832ad47fb52f23d14d4f86bb5/triton-3.6.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74caf5e34b66d9f3a429af689c1c7128daba1d8208df60e81106b115c00d6fca", size = 188266850, upload-time = "2026-01-20T16:00:43.041Z" }, - { url = "https://files.pythonhosted.org/packages/3c/12/34d71b350e89a204c2c7777a9bba0dcf2f19a5bfdd70b57c4dbc5ffd7154/triton-3.6.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:448e02fe6dc898e9e5aa89cf0ee5c371e99df5aa5e8ad976a80b93334f3494fd", size = 176133521, upload-time = "2026-01-20T16:16:13.321Z" }, - { url = "https://files.pythonhosted.org/packages/f9/0b/37d991d8c130ce81a8728ae3c25b6e60935838e9be1b58791f5997b24a54/triton-3.6.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10c7f76c6e72d2ef08df639e3d0d30729112f47a56b0c81672edc05ee5116ac9", size = 188289450, upload-time = "2026-01-20T16:00:49.136Z" }, - { url = "https://files.pythonhosted.org/packages/ce/4e/41b0c8033b503fd3cfcd12392cdd256945026a91ff02452bef40ec34bee7/triton-3.6.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1722e172d34e32abc3eb7711d0025bb69d7959ebea84e3b7f7a341cd7ed694d6", size = 176276087, upload-time = "2026-01-20T16:16:18.989Z" }, - { url = "https://files.pythonhosted.org/packages/35/f8/9c66bfc55361ec6d0e4040a0337fb5924ceb23de4648b8a81ae9d33b2b38/triton-3.6.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d002e07d7180fd65e622134fbd980c9a3d4211fb85224b56a0a0efbd422ab72f", size = 188400296, upload-time = "2026-01-20T16:00:56.042Z" }, ] [[package]] @@ -5482,8 +4860,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cd/5e/fce69606f7f240297f163e25539906732b199530d486ce67ae319877e821/triton-3.7.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6744957e9fd610a29680ec2346057d0c86948ed3812468670719f391e94b44a5", size = 197701306, upload-time = "2026-06-17T19:53:13.673Z" }, { url = "https://files.pythonhosted.org/packages/94/fa/f856e24deb462d5f18bd4b5a746957862ab9b6ee5834bda60605ec348366/triton-3.7.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9497f2e696ee368862a181a90b2dcc03ca978cc4f602abd67c7d81022a6988e1", size = 184692359, upload-time = "2026-06-17T20:03:48.288Z" }, { url = "https://files.pythonhosted.org/packages/c4/6f/fb96d15db6f36d6eae4cafb998c2e0353bf59d7c4ea1662d7497f269134a/triton-3.7.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e40869937a68206ec70d7f25bb7ec6433cb083f9135e1f36dbd318dc449a728", size = 197719725, upload-time = "2026-06-17T19:53:20.419Z" }, - { url = "https://files.pythonhosted.org/packages/00/42/c5089d4d9327fcd1e862c599cc2927f39418f84dd11a84cb2ccff9d4787a/triton-3.7.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cdbfc09d9ec58bc5e68321525653220de7515c199e7a8097a97c85e62b52cd0a", size = 184694629, upload-time = "2026-06-17T20:03:53.444Z" }, - { url = "https://files.pythonhosted.org/packages/07/42/2c3ac59253ae8892b6f307875263dd23dc875cdf732d3aea40d6d41fb7cb/triton-3.7.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58c0e131da05134a2a4788ccbcc0c1105cf0f54c8e98f19e34cd465396dc15eb", size = 197729241, upload-time = "2026-06-17T19:53:27.801Z" }, ] [[package]] @@ -5494,7 +4870,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4d/b4/c50a22dd2d493a3e8e78744cbdcb29932f367b68999c8e08874b94aebd3a/triton_windows-3.7.1.post27-cp310-cp310-win_amd64.whl", hash = "sha256:01ede775b102c91acc89fc6946b946451f966cb64856c650d244d37ea3bbdee5", size = 49678783, upload-time = "2026-06-21T16:47:51.235Z" }, { url = "https://files.pythonhosted.org/packages/26/f5/0f5eaf48abc0c9900f600dbdfa8139e678aa7d47dc1da51b0541979e96df/triton_windows-3.7.1.post27-cp311-cp311-win_amd64.whl", hash = "sha256:b739bd7d39f919280294d8af172a90aa2f17a4377bfbca2ea30a8afae61d5eaa", size = 49679173, upload-time = "2026-06-21T16:48:02.395Z" }, { url = "https://files.pythonhosted.org/packages/76/30/325b420efd0047e119679c646a9a410db216069800ec009fae3da26c69a3/triton_windows-3.7.1.post27-cp312-cp312-win_amd64.whl", hash = "sha256:f5406230d7dbf6965bc4051fcad27b81c39ba4a4bfde06f494dd7ff4eb325a9e", size = 49683004, upload-time = "2026-06-21T16:48:14.02Z" }, - { url = "https://files.pythonhosted.org/packages/ec/28/f0b2801c2cfd79be5878bf429e82b5da00fb78f046a9c21ba946681cc467/triton_windows-3.7.1.post27-cp313-cp313-win_amd64.whl", hash = "sha256:e8ed215c02afc85a81f0097196f8bebdf6f68085f1bc0fe8771b9a74783f15ab", size = 49684257, upload-time = "2026-06-21T16:48:24.901Z" }, ] [[package]] @@ -5563,7 +4938,7 @@ name = "typing-inspection" version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "sys_platform != 'win32'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ @@ -5682,31 +5057,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/08/d9e2e0f9e8e6791d33aefc694ad7eefa7f901f63caff84a81ded38692f9c/watchfiles-1.2.0-cp312-cp312-win32.whl", hash = "sha256:7a2cffd17d27d2ecbb310c2b1d8174f222a5495b1a721894afa88ec11e25b898", size = 275480, upload-time = "2026-05-18T04:30:31.307Z" }, { url = "https://files.pythonhosted.org/packages/1c/e6/9d42569c0102645cc8cea5d8c7d8a1e9d4ada2cb7f05f75e554b8aa2202a/watchfiles-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:f155b3a1b2a5fc89cdc70d47ee5d54e3b75e88efa34982028a35daef9ba00379", size = 288718, upload-time = "2026-05-18T04:32:10.745Z" }, { url = "https://files.pythonhosted.org/packages/0a/26/88e0dc6ee3898169d7fa22bb6a69cabf2502d2ee25cb8c876d1262d204f8/watchfiles-1.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:8fa585ede612ee9f9e91b18bebf9ba11b9ae29a4e3a0d0cf6fca3e382133f0d5", size = 281026, upload-time = "2026-05-18T04:30:22.23Z" }, - { url = "https://files.pythonhosted.org/packages/d1/4d/70a7feced9f87e2ff26dba42667290f41694fc64646c67261fbb8cab5d5c/watchfiles-1.2.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:01ea8d66f0693b9b60a6541c8d10263091ca9a9060d242f3c1f3143f9aad2c98", size = 399730, upload-time = "2026-05-18T04:31:38.162Z" }, - { url = "https://files.pythonhosted.org/packages/31/3a/0da302f2307aee316922806ebd5726c542cbd787c938271cf14a074c7daf/watchfiles-1.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ba0480b9a74af058f43b337e937a451e109295c420916d68ad24e3dc02f5e44", size = 392842, upload-time = "2026-05-18T04:30:27.051Z" }, - { url = "https://files.pythonhosted.org/packages/db/ef/d5bdb705c224dbc256aa0c1ec47bf4e61ec52558f2afb44a71a1fe4d7015/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f34e26a19f91f710c08e0183429f0d1d15df734e6bc78c31e77b9ea9c433658", size = 452989, upload-time = "2026-05-18T04:31:11.945Z" }, - { url = "https://files.pythonhosted.org/packages/71/29/5495f2c1661949ef7a35e4d71111d129cfe7606414a26887a919d0a55406/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4e77f6a55f858504069abd35d336a637555c09bca453dde1ee1e5ada8a6a1fb", size = 458978, upload-time = "2026-05-18T04:30:52.606Z" }, - { url = "https://files.pythonhosted.org/packages/d5/8c/7f9c07c433811c2fffd93e13fdfb7135de9aab5f2ae41be08960fa0047dc/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cb4d80e212f116474a545c21c912b445f16bb0cef9e6a73a498164223e14e2f", size = 490248, upload-time = "2026-05-18T04:31:36.003Z" }, - { url = "https://files.pythonhosted.org/packages/3c/11/d93632febc52fbc21be90231bb7c17fd5387f46c9076fd40a5f9c2ae6910/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b974946a10af379d425e2eef5b62f5c6ebeaccf91d45eaad6f5b27ecd4f91aa0", size = 571847, upload-time = "2026-05-18T04:31:10.862Z" }, - { url = "https://files.pythonhosted.org/packages/55/b4/383173e73aabb07ad1d9c7aa859d95437ac46a6d6a1e11005facda0c9d19/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86bc13c25a8d1fcd70b51d0ce7c9b65e90de5666fcbfd3e34957cc73ee19aeb5", size = 465974, upload-time = "2026-05-18T04:30:17.006Z" }, - { url = "https://files.pythonhosted.org/packages/a7/6c/89b1a230a78f57c52dd8893adb1f92f94411721b6ec12596c56d98c74356/watchfiles-1.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca148d73dea36c9763aaa351e4d7a51780ec1584217c45276f4fe8239c768b71", size = 454782, upload-time = "2026-05-18T04:30:35.656Z" }, - { url = "https://files.pythonhosted.org/packages/24/62/1732118367cfff0a9fce3bf62ff4bfded09ef5df21d9d446b858b3f70a96/watchfiles-1.2.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:c525543d91961c6955b2636b308569e84a1d1c5f5f2932041ab9ef46422f43e3", size = 465182, upload-time = "2026-05-18T04:30:20.846Z" }, - { url = "https://files.pythonhosted.org/packages/28/96/716f7e5f51339bf22963f3345f9f27d7f3b30e2eadc597e257c881dd3c53/watchfiles-1.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a204794696ffb8f9b10fba6f7cb5216d42f3b2b71860ccac6b6e42f5f10973b0", size = 629841, upload-time = "2026-05-18T04:31:05.397Z" }, - { url = "https://files.pythonhosted.org/packages/4c/fe/c40783950fd771ccf66ab3ec2722d188a9af1c7f96c6e811f36e40c6e03f/watchfiles-1.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:10d86db20695afe7997ac9e1717637d6714a8d0220458c33f3d2061f54cec427", size = 658028, upload-time = "2026-05-18T04:31:48.22Z" }, - { url = "https://files.pythonhosted.org/packages/71/72/4508db1856d1d87fcbb3b63f4839bab1b5682cb0e8d224d122263c09654a/watchfiles-1.2.0-cp313-cp313-win32.whl", hash = "sha256:eb283ee99e21ad6443c8cdb06ac5b34b1308c329cbdf03fa02b445363714c799", size = 275183, upload-time = "2026-05-18T04:30:59.57Z" }, - { url = "https://files.pythonhosted.org/packages/f9/36/14b76ca57652e5cc5fd1c11f32a261292c08a0d19a00351013c2549cbfb2/watchfiles-1.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a0f27f01bee51861392bb6b7c4fdb290b27d1eb194e9e28788d68102a0e898d9", size = 288059, upload-time = "2026-05-18T04:32:07.937Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8d/0a85e395398d8d20fadfe5c5d32c726eee17a519e78fb356f2cf7531bffe/watchfiles-1.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:3651aa7058595e9cfb75d35dd5ada2bf9f48a5b8a0f3562821d3e210c507e077", size = 280186, upload-time = "2026-05-18T04:31:54.484Z" }, - { url = "https://files.pythonhosted.org/packages/37/68/36db056f1fdcc5f07302f56e631774d6835bcd6fa3ace402304621d5f9e5/watchfiles-1.2.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:faea288b6f0ab1902ef08f4ca6de005dccf856c4e0c4f21b8c5fce02d90a1b08", size = 399031, upload-time = "2026-05-18T04:30:44.576Z" }, - { url = "https://files.pythonhosted.org/packages/c1/64/01a9d6f66a82a5c101ce939274106cc72759d62427e153f01edd2b9f87c2/watchfiles-1.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01859b11fd9fbca670f4d5da00fbac282cfea9bd67a2125d8b2833a3b5617ea9", size = 391205, upload-time = "2026-05-18T04:30:25.413Z" }, - { url = "https://files.pythonhosted.org/packages/84/2c/0a44fe058cb4bb7b8ede6b6670698bbb7c0400740e378d00022189b7b31d/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fff610d7bb2256a317bb1e96f0d7862c7aa8076733ee5df0fd41bbe76a24a4f4", size = 451892, upload-time = "2026-05-18T04:32:14.005Z" }, - { url = "https://files.pythonhosted.org/packages/67/a1/351e0d56cd35e6488b5c8b4fb11a809a5bc923e8fe8fed9faf8920be0c89/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b141a4891c995a039cd89e9a49e62df1dc8a559a5d1a6e4c7106d16c12777a55", size = 458867, upload-time = "2026-05-18T04:31:22.279Z" }, - { url = "https://files.pythonhosted.org/packages/d5/7d/9d09605187f1b838998624049fcf8bf47b73c1a3b76901fcac1782f62277/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f22943b7770483f6ea0721c6b11d022947a98eb0acae14694de034f4d0d38925", size = 490217, upload-time = "2026-05-18T04:31:43.657Z" }, - { url = "https://files.pythonhosted.org/packages/60/5d/a17a16eccb182f04188cd308ec24b1a71a9b5c4e7098269cf35d9fa56d02/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bc6195825b7dcd217968bb1f801a60fd4c16e8eeab5bedc7fe917d7d5995ab4", size = 571458, upload-time = "2026-05-18T04:32:11.875Z" }, - { url = "https://files.pythonhosted.org/packages/d3/3d/4dd457062083ab1938e5dfd45032eb425cee2ac817287ca8ff4356183e5d/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4a4b147f5dca2a5d325a06a832fb43f345751adfbc63204aec30e0d9ca965a2", size = 464707, upload-time = "2026-05-18T04:30:43.492Z" }, - { url = "https://files.pythonhosted.org/packages/c6/71/ea8c57b128f5383de74d0c7d2d9c57ad7c9a65a930c451bd25d524b295b7/watchfiles-1.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4543579a9bdb0c9560039b4ffddbdb39545707659fbc430ce4c10f3f68d557f9", size = 454663, upload-time = "2026-05-18T04:30:16.061Z" }, - { url = "https://files.pythonhosted.org/packages/53/fd/2e812bf938406d7db351f0703ddd3fc6c061cf30d96153a77bc79a943a44/watchfiles-1.2.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:20aa0e708b920bde876a4aa82dc7dd6ebea228a63a67cda6632c2fc87b787efa", size = 463537, upload-time = "2026-05-18T04:31:44.9Z" }, - { url = "https://files.pythonhosted.org/packages/86/56/d17a7f1dd1bc3035f1072694a551301272f1739c2d8e319c927cb9e29b38/watchfiles-1.2.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:d413349d565dab74297f2a63e84a097936be69bf8f3b3801f27f380e32040f44", size = 629194, upload-time = "2026-05-18T04:31:14.141Z" }, - { url = "https://files.pythonhosted.org/packages/be/06/f1ff66bf5cae50aa4062779a0ecd0bbaf15e466195719074078947d9a17d/watchfiles-1.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f28b2725eb8cce327b9b3ab02415c853011dc55c95832fe90de6bc56f5315f72", size = 656194, upload-time = "2026-05-18T04:31:47.14Z" }, { url = "https://files.pythonhosted.org/packages/23/f4/7513ef1e85fc4c6331b59479d6d72661fc391fbe543678052ac72c8b6c19/watchfiles-1.2.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4674d49eb94706dfe666c069fc0a1b646ffcf920473492e209f6d5f60d3f0cc2", size = 403050, upload-time = "2026-05-18T04:30:36.753Z" }, { url = "https://files.pythonhosted.org/packages/27/0b/a54103cfd732bb703c7a749222011a0483ef3705948dae3b203158601119/watchfiles-1.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:094b9b70103d4e963499bdea001ee3c2697b144cd9ae6218a62c0f89ec9e31db", size = 396629, upload-time = "2026-05-18T04:32:03.268Z" }, { url = "https://files.pythonhosted.org/packages/5e/2c/73f31a3b893886206c3f54d73e8ad8dee58cdb2f69ad2622e0a8a9e07f4e/watchfiles-1.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0ef001f8c25ad0fa9529f914c1600647ecd0f542d11c19b7894768c67b6acb7", size = 457318, upload-time = "2026-05-18T04:31:01.932Z" }, @@ -5755,15 +5105,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" }, { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" }, { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" }, - { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, - { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, - { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, - { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, - { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, - { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, - { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, - { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, { url = "https://files.pythonhosted.org/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d", size = 174947, upload-time = "2026-01-10T09:23:36.166Z" }, { url = "https://files.pythonhosted.org/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03", size = 175260, upload-time = "2026-01-10T09:23:37.409Z" }, { url = "https://files.pythonhosted.org/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da", size = 176071, upload-time = "2026-01-10T09:23:39.158Z" }, @@ -5843,23 +5184,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/48/2d/1c8d89c7c5f9cad9fb2902445d94e2ab1d7aa35de029afbb8ae95c42d00f/yarl-1.24.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e30dd55825dc554ec5b66a94953b8eda8745926514c5089dfcacecb9c99b5bd1", size = 105719, upload-time = "2026-05-19T21:29:18.367Z" }, { url = "https://files.pythonhosted.org/packages/a7/25/722e3b93bd687009afb2d59a35e13d30ddd8f80571445bb0c4e4ce26ec66/yarl-1.24.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dafe10c12ddd4d120d528c4b5599c953bd7b12845347d507b95451195bb6cad", size = 92901, upload-time = "2026-05-19T21:29:20.014Z" }, { url = "https://files.pythonhosted.org/packages/39/47/4486ccfb674c04854a1ef8aa77868b6a6f765feaf69633409d7ca4f02cb8/yarl-1.24.2-cp312-cp312-win_arm64.whl", hash = "sha256:044a09d8401fcf8681977faef6d286b8ade1e2d2e9dceda175d1cfa5ca496f30", size = 87229, upload-time = "2026-05-19T21:29:22.1Z" }, - { url = "https://files.pythonhosted.org/packages/82/62/fcf0ce677f17e5c471c06311dd25964be38a4c586993632910d2e75278bc/yarl-1.24.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:491ac9141decf49ee8030199e1ee251cdff0e131f25678817ff6aa5f837a3536", size = 128978, upload-time = "2026-05-19T21:29:23.83Z" }, - { url = "https://files.pythonhosted.org/packages/d3/58/8e63299bb71ed61a834121d9d3fe6c9fcf2a6a5d09754ff4f20f2d20baf5/yarl-1.24.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e89418f65eda18f99030386305bd44d7d504e328a7945db1ead514fbe03a0607", size = 91733, upload-time = "2026-05-19T21:29:25.375Z" }, - { url = "https://files.pythonhosted.org/packages/c1/24/16748d5dab6daec8b0ed81ccec639a1cded0f18dcc62a4f696b4fe366c37/yarl-1.24.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cdfcce633b4a4bb8281913c57fcafd4b5933fbc19111a5e3930bbd299d6102f1", size = 91113, upload-time = "2026-05-19T21:29:26.928Z" }, - { url = "https://files.pythonhosted.org/packages/1b/66/b63fff7b71211e866624b21432d5943cbb633eb0c2872d9ee3070648f22c/yarl-1.24.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:863297ddede92ee49024e9a9b11ecb59f310ca85b60d8537f56bed9bbb5b1986", size = 103899, upload-time = "2026-05-19T21:29:28.842Z" }, - { url = "https://files.pythonhosted.org/packages/9d/ac/ba1974b8533909636f7733fe86cf677e3619527c3c2fa913e0ea89c48757/yarl-1.24.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:374423f70754a2c96942ede36a29d37dc6b0cb8f92f8d009ddf3ed78d3da5488", size = 97862, upload-time = "2026-05-19T21:29:31.086Z" }, - { url = "https://files.pythonhosted.org/packages/1b/a5/123ac993b5c2ba6f554a140305620cb8f150fa543711bbc49be3ec0a65a4/yarl-1.24.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33a29b5d00ccbf3219bb3e351d7875739c19481e030779f48cc46a7a71681a9b", size = 111060, upload-time = "2026-05-19T21:29:32.657Z" }, - { url = "https://files.pythonhosted.org/packages/23/37/c472d3af3509688392134a88a825276770a187f1daa4de3f6dc0a327a751/yarl-1.24.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a9532c57211730c515341af11fef6e9b61d157487272a096d0c04da445642592", size = 110613, upload-time = "2026-05-19T21:29:34.379Z" }, - { url = "https://files.pythonhosted.org/packages/df/88/09c28dad91e662ccfaa1b78f1c57badde74fc9d0b23e74aef644750ecd73/yarl-1.24.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91e72cf093fd833483a97ee648e0c053c7c629f51ff4a0e7edd84f806b0c5617", size = 107012, upload-time = "2026-05-19T21:29:36.216Z" }, - { url = "https://files.pythonhosted.org/packages/07/ab/9d4f69d571a94f4d112fa7e2e007200f5a54d319f58c82ac7b7baa61f5c6/yarl-1.24.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b3177bc0a768ef3bacceb4f272632990b7bea352f1b2f1eee9d6d6ff16516f92", size = 105887, upload-time = "2026-05-19T21:29:38.746Z" }, - { url = "https://files.pythonhosted.org/packages/8e/9a/000b2b66c0d772a499fc531d21dab92dfeb73b640a12eed6ba89f49bb2d0/yarl-1.24.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e196952aacaf3b232e265ff02980b64d483dc0972bd49bcb061171ff22ac203a", size = 103620, upload-time = "2026-05-19T21:29:40.368Z" }, - { url = "https://files.pythonhosted.org/packages/41/7c/7c1050f73450fbdaa3f0c72017059f00ce5e13366692f3dba25275a1083d/yarl-1.24.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:204e7a61ce99919c0de1bf904ab5d7aa188a129ea8f690a8f76cfb6e2844dc44", size = 100599, upload-time = "2026-05-19T21:29:42.66Z" }, - { url = "https://files.pythonhosted.org/packages/ec/b1/29e5756b3926705f5f6089bd5b9f50a56eaac550da6e260bf713ead44d04/yarl-1.24.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b156914620f0b9d78dc1adb3751141daee561cfec796088abb89ed49d220f1a", size = 110604, upload-time = "2026-05-19T21:29:44.632Z" }, - { url = "https://files.pythonhosted.org/packages/a3/4b/8415bc96e9b150cde942fbac9a8182985e58f40ce5c54c34ed015407d3ee/yarl-1.24.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:8372a2b976cf70654b2be6619ab6068acabb35f724c0fda7b277fbf53d66a5cf", size = 105161, upload-time = "2026-05-19T21:29:46.755Z" }, - { url = "https://files.pythonhosted.org/packages/8b/d4/cde059abfa229553b7298a2eadde2752e723d50aeedaef86ce59da2718ee/yarl-1.24.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f9a1e9b622ca284143aab5d885848686dcd85453bb1ca9abcdb7503e64dc0056", size = 110619, upload-time = "2026-05-19T21:29:48.972Z" }, - { url = "https://files.pythonhosted.org/packages/e7/2c/d6a6c9a61549f7b6c7e6dc6937d195bcf069582b47b7200dcd0e7b256acf/yarl-1.24.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:810e19b685c8c3c5862f6a38160a1f4e4c0916c9390024ec347b6157a45a0992", size = 107362, upload-time = "2026-05-19T21:29:51Z" }, - { url = "https://files.pythonhosted.org/packages/92/dd/3ae5fe417e9d1c353a548553326eb9935e76b6b727161563b424cc296df3/yarl-1.24.2-cp313-cp313-win_amd64.whl", hash = "sha256:7d37fb7c38f2b6edab0f845c4f85148d4c44204f52bc127021bd2bc9fdbf1656", size = 92667, upload-time = "2026-05-19T21:29:52.743Z" }, - { url = "https://files.pythonhosted.org/packages/10/cc/a7beb239f78f27fca1b053c8e8595e4179c02e62249b4687ec218c370c50/yarl-1.24.2-cp313-cp313-win_arm64.whl", hash = "sha256:1e831894be7c2954240e49791fa4b50c05a0dc881de2552cfe3ffd8631c7f461", size = 87069, upload-time = "2026-05-19T21:29:54.442Z" }, { url = "https://files.pythonhosted.org/packages/fd/4d/4b880086bd0d3e034d25647be1d830afc3e3f610e98c4ab3490af6b1b6d5/yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9", size = 53576, upload-time = "2026-05-19T21:31:03.909Z" }, ]