diff --git a/.claude/settings.json b/.claude/settings.json index 378d0ebec..c6828d992 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -3,13 +3,13 @@ "allow": [ "WebSearch", "WebFetch(domain:docs.temporal.io)", - "Bash(rye run pytest:*)", - "Bash(rye run lint:*)", - "Bash(rye run typecheck:*)", - "Bash(rye run sync:*)", - "Bash(rye run build:*)" + "Bash(uv run pytest:*)", + "Bash(uv run ruff:*)", + "Bash(uv run pyright:*)", + "Bash(uv sync:*)", + "Bash(uv build:*)" ], "deny": [], "ask": [] } -} \ No newline at end of file +} diff --git a/.cursor/rules/00_repo_tooling.mdc b/.cursor/rules/00_repo_tooling.mdc index ca3a44cbd..45a21adfe 100644 --- a/.cursor/rules/00_repo_tooling.mdc +++ b/.cursor/rules/00_repo_tooling.mdc @@ -4,15 +4,15 @@ globs: "**/*" alwaysApply: true --- -Use Rye for Python dependency management and workflows. Prefer these commands: +Use uv for Python dependency management and workflows. Prefer these commands: -- Setup env: `./scripts/bootstrap` or `rye sync --all-features` [[Use Rye in this repo]] -- Run tests: `rye run pytest` or `./scripts/test` -- Run a specific test: `rye run pytest path/to/test_file.py::TestClass::test_method -v` -- Format: `rye run format` or `./scripts/format` -- Lint: `rye run lint` or `./scripts/lint` -- Type check: `rye run typecheck` (runs pyright and mypy) -- Build: `rye build` +- Setup env: `./scripts/bootstrap` or `uv sync --all-groups` +- Run tests: `uv run pytest` or `./scripts/test` +- Run a specific test: `uv run pytest path/to/test_file.py::TestClass::test_method -v` +- Format: `uv run ruff format` or `./scripts/format` +- Lint: `uv run ruff check .` or `./scripts/lint` +- Type check: `uv run pyright` +- Build: `uv build` Environment requirements: @@ -21,4 +21,4 @@ Environment requirements: Notes: -- Only use `uv` inside of tutorial folders which have their own virtualenv (managed by a tutorial specific pyproject.toml inside the relevant tutorial folder). Otherwise use rye at the top level. +- Tutorial folders have their own virtualenv (managed by a tutorial specific pyproject.toml inside the relevant tutorial folder). Use `uv run` within those folders. diff --git a/.cursor/rules/05_permissions_and_tools.mdc b/.cursor/rules/05_permissions_and_tools.mdc index 72ff65979..6c0f841a7 100644 --- a/.cursor/rules/05_permissions_and_tools.mdc +++ b/.cursor/rules/05_permissions_and_tools.mdc @@ -8,11 +8,11 @@ When invoking external tools or the terminal, follow these constraints: - Web search is allowed when needed for docs and references - Prefer fetching docs from `docs.temporal.io` when researching Temporal topics -- Allowed bash commands should go through Rye workflows: - - `rye run pytest:*` - - `rye run lint:*` - - `rye run typecheck:*` - - `rye run sync:*` - - `rye run build:*` +- Allowed bash commands should go through uv workflows: + - `uv run pytest` + - `uv run ruff check .` + - `uv run pyright` + - `uv sync` + - `uv build` -Default to Rye; only use other tools when explicitly required by the codebase. +Default to uv; only use other tools when explicitly required by the codebase. diff --git a/.cursor/rules/50_tests_and_mocking.mdc b/.cursor/rules/50_tests_and_mocking.mdc index 420de4ac7..5648d1950 100644 --- a/.cursor/rules/50_tests_and_mocking.mdc +++ b/.cursor/rules/50_tests_and_mocking.mdc @@ -6,8 +6,8 @@ alwaysApply: true Testing: -- Run tests with `rye run pytest` or `./scripts/test` -- To run a specific test: `rye run pytest path/to/test_file.py::TestClass::test_method -v` +- Run tests with `uv run pytest` or `./scripts/test` +- To run a specific test: `uv run pytest path/to/test_file.py::TestClass::test_method -v` - A mock server is automatically started for tests on port 4010 When writing tests: diff --git a/.cursor/rules/60_style_lint_typecheck.mdc b/.cursor/rules/60_style_lint_typecheck.mdc index f36f02d7c..78de06d79 100644 --- a/.cursor/rules/60_style_lint_typecheck.mdc +++ b/.cursor/rules/60_style_lint_typecheck.mdc @@ -6,9 +6,9 @@ alwaysApply: true Standards: -- Format code via `rye run format` or `./scripts/format` -- Lint via `rye run lint` or `./scripts/lint` -- Type check via `rye run typecheck` (pyright + mypy) +- Format code via `uv run ruff format` or `./scripts/format` +- Lint via `uv run ruff check .` or `./scripts/lint` +- Type check via `uv run pyright` Guidance: diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ff261bad7..c56ef8358 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,6 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} USER vscode -RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash -ENV PATH=/home/vscode/.rye/shims:$PATH +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/ RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c17fdc169..ea8e41aa4 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,21 +7,18 @@ "context": ".." }, - "postStartCommand": "rye sync --all-features", + "postStartCommand": "uv sync --all-groups", "customizations": { "vscode": { "extensions": [ "ms-python.python" ], - "settings": { + "settings": { "terminal.integrated.shell.linux": "/bin/bash", "python.pythonPath": ".venv/bin/python", "python.defaultInterpreterPath": ".venv/bin/python", - "python.typeChecking": "basic", - "terminal.integrated.env.linux": { - "PATH": "/home/vscode/.rye/shims:${env:PATH}" - } + "python.typeChecking": "basic" } } }, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cf293aab..82bdad485 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,16 +21,11 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Install Rye - run: | - curl -sSf https://rye.astral.sh/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: '0.44.0' - RYE_INSTALL_OPTION: '--yes' + - name: Install uv + uses: astral-sh/setup-uv@v5 - name: Install dependencies - run: rye sync --all-features + run: uv sync --all-groups - name: Run lints run: ./scripts/lint @@ -46,19 +41,14 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Install Rye - run: | - curl -sSf https://rye.astral.sh/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: '0.44.0' - RYE_INSTALL_OPTION: '--yes' + - name: Install uv + uses: astral-sh/setup-uv@v5 - name: Install dependencies - run: rye sync --all-features + run: uv sync --all-groups - name: Run build - run: rye build + run: uv build - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/agentex-sdk-python' @@ -83,13 +73,8 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Install Rye - run: | - curl -sSf https://rye.astral.sh/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: '0.44.0' - RYE_INSTALL_OPTION: '--yes' + - name: Install uv + uses: astral-sh/setup-uv@v5 - name: Bootstrap run: ./scripts/bootstrap diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 6b83ad2aa..0e8851e88 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -16,13 +16,8 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Install Rye - run: | - curl -sSf https://rye.astral.sh/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: "0.44.0" - RYE_INSTALL_OPTION: "--yes" + - name: Install uv + uses: astral-sh/setup-uv@v5 - name: Publish to PyPI run: | diff --git a/Brewfile b/Brewfile deleted file mode 100644 index 492ca37bb..000000000 --- a/Brewfile +++ /dev/null @@ -1,2 +0,0 @@ -brew "rye" - diff --git a/CLAUDE.md b/CLAUDE.md index ffb1e50f6..7a3851314 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,32 +5,32 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Development Commands ### Package Management in the top level repo -- Use `rye` for dependency management (preferred) +- Use `uv` for dependency management - Run `./scripts/bootstrap` to set up the environment -- Or use `rye sync --all-features` directly +- Or use `uv sync --all-groups` directly -Special note: the individual tutorials maintain their own tutorial specific virtualenv using `uv`. So when testing/running tutorials, you `uv run` instead of `rye run`. Everything else is similar. +Special note: the individual tutorials maintain their own tutorial specific virtualenv using `uv`. So when testing/running tutorials, you `uv run` instead of the top-level scripts. Everything else is similar. #### Testing -- Run tests: `rye run pytest` or `./scripts/test` -- Run specific test: `rye run pytest path/to/test_file.py::TestClass::test_method -v` +- Run tests: `uv run pytest` or `./scripts/test` +- Run specific test: `uv run pytest path/to/test_file.py::TestClass::test_method -v` - Mock server is automatically started for tests, runs on port 4010 #### Linting and Formatting -- Format code: `rye run format` or `./scripts/format` - * The repository is still in flux, so running format might accidentally change files that aren't part of your scope of changes. So always run `run rye format` with additional arguments to constrain the formatting to the files that you are modifying. -- Lint code: `rye run lint` or `./scripts/lint` -- Type check: `rye run typecheck` (runs both pyright and mypy) +- Format code: `uv run ruff format` or `./scripts/format` + * The repository is still in flux, so running format might accidentally change files that aren't part of your scope of changes. So always run `uv run ruff format` with additional arguments to constrain the formatting to the files that you are modifying. +- Lint code: `uv run ruff check .` or `./scripts/lint` +- Type check: `uv run pyright` ### Building and Running -- Build package: `rye build` +- Build package: `uv build` ### CLI Commands The package provides the `agentex` CLI with these main commands: - `agentex agents` - Get, list, run, build, and deploy agents -- `agentex tasks` - Get, list, and delete tasks +- `agentex tasks` - Get, list, and delete tasks - `agentex secrets` - Sync, get, list, and delete secrets - `agentex uv` - UV wrapper with AgentEx-specific enhancements - `agentex init` - Initialize new agent projects @@ -80,7 +80,7 @@ Most SDK code is auto-generated. Manual changes are preserved in: ### Key Dependencies - `temporalio` - Temporal workflow engine -- `typer` - CLI framework +- `typer` - CLI framework - `pydantic` - Data validation - `httpx` - HTTP client - `fastapi` - Web framework @@ -89,5 +89,5 @@ Most SDK code is auto-generated. Manual changes are preserved in: ### Environment Requirements - Python 3.12+ required -- Uses Rye for dependency management -- Supports both sync and async client patterns \ No newline at end of file +- Uses uv for dependency management +- Supports both sync and async client patterns diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0efe0472..bac280a90 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,35 +1,35 @@ ## Setting up the environment -### With Rye +### With uv -We use [Rye](https://rye.astral.sh/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run: +We use [uv](https://docs.astral.sh/uv/) to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run: ```sh $ ./scripts/bootstrap ``` -Or [install Rye manually](https://rye.astral.sh/guide/installation/) and run: +Or [install uv](https://docs.astral.sh/uv/getting-started/installation/) and run: ```sh -$ rye sync --all-features +$ uv sync --all-groups ``` -You can then run scripts using `rye run python script.py` or by activating the virtual environment: +You can then run scripts using `uv run python script.py` or by activating the virtual environment: ```sh # Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work $ source .venv/bin/activate -# now you can omit the `rye run` prefix +# now you can omit the `uv run` prefix $ python script.py ``` -### Without Rye +### Without uv -Alternatively if you don't want to install `Rye`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command: +Alternatively if you don't want to install `uv`, you can stick with the standard `pip` setup by ensuring you have the Python version specified in `.python-version`, create a virtual environment however you desire and then install dependencies using this command: ```sh -$ pip install -r requirements-dev.lock +$ pip install -e ".[dev]" ``` ## Modifying/Adding code @@ -45,7 +45,7 @@ All files in the `examples/` directory are not modified by the generator and can ```py # add an example to examples/.py -#!/usr/bin/env -S rye run python +#!/usr/bin/env -S uv run python … ``` @@ -57,7 +57,7 @@ $ ./examples/.py ## Using the repository from source -If you’d like to use the repository from source, you can either install from git or link to a cloned repository: +If you'd like to use the repository from source, you can either install from git or link to a cloned repository: To install via git: @@ -72,7 +72,7 @@ Building this package will create two files in the `dist/` directory, a `.tar.gz To create a distributable version of the library, all you have to do is run this command: ```sh -$ rye build +$ uv build # or $ python -m build ``` @@ -98,8 +98,7 @@ $ ./scripts/test ## Linting and formatting -This repository uses [ruff](https://github.com/astral-sh/ruff) and -[black](https://github.com/psf/black) to format the code in the repository. +This repository uses [ruff](https://github.com/astral-sh/ruff) to format and lint the code in the repository. To lint: @@ -130,4 +129,3 @@ the environment. ## 🤖 **Vibe Coding Setup** This repository is setup with some pre-canned prompts for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) as well as [Cursor](https://cursor.com/). - diff --git a/bin/publish-pypi b/bin/publish-pypi index 826054e92..ae91a5cf7 100644 --- a/bin/publish-pypi +++ b/bin/publish-pypi @@ -2,5 +2,5 @@ set -eux mkdir -p dist -rye build --clean -rye publish --yes --token=$PYPI_TOKEN +uv build --clean +uv publish --token $PYPI_TOKEN diff --git a/examples/tutorials/10_async/10_temporal/090_claude_agents_sdk_mvp/README.md b/examples/tutorials/10_async/10_temporal/090_claude_agents_sdk_mvp/README.md index 2f40e53c1..07ab8450f 100644 --- a/examples/tutorials/10_async/10_temporal/090_claude_agents_sdk_mvp/README.md +++ b/examples/tutorials/10_async/10_temporal/090_claude_agents_sdk_mvp/README.md @@ -186,7 +186,7 @@ subagents = { ```bash # Install -rye sync --all-features +uv sync --all-groups # Configure export ANTHROPIC_API_KEY="your-key" diff --git a/examples/tutorials/README.md b/examples/tutorials/README.md index c92316858..00c64c7c7 100644 --- a/examples/tutorials/README.md +++ b/examples/tutorials/README.md @@ -122,7 +122,7 @@ uv run python hello_acp.py ```bash # Format tutorial code (always scope to specific files you're modifying) -rye run format examples/tutorials/00_sync/000_hello_acp/ +uv run ruff format examples/tutorials/00_sync/000_hello_acp/ # Run all async tutorial tests cd examples/tutorials diff --git a/pyproject.toml b/pyproject.toml index 17e758d54..4efc4647f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,10 +80,15 @@ dev = [ [project.scripts] agentex = "agentex.lib.cli.commands.main:app" -[tool.rye] +[tool.uv] managed = true -# version pins are in requirements-dev.lock -dev-dependencies = [ + +[build-system] +requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"] +build-backend = "hatchling.build" + +[dependency-groups] +dev = [ "pyright==1.1.399", "mypy==1.17", "respx", @@ -98,42 +103,6 @@ dev-dependencies = [ "nest_asyncio==1.6.0", "pytest-xdist>=3.6.1", "debugpy>=1.8.15", -] - -[tool.rye.scripts] -format = { chain = [ - "format:ruff", - "format:docs", - "fix:ruff", - # run formatting again to fix any inconsistencies when imports are stripped - "format:ruff", -]} -"format:docs" = "python scripts/utils/ruffen-docs.py README.md api.md" -"format:ruff" = "ruff format" - -"lint" = { chain = [ - "check:ruff", - "typecheck", - "check:importable", -]} -"check:ruff" = "ruff check ." -"fix:ruff" = "ruff check --fix ." - -"check:importable" = "python -c 'import agentex'" - -typecheck = { chain = [ - "typecheck:pyright" -]} -"typecheck:pyright" = "pyright" -"typecheck:verify-types" = "pyright --verifytypes agentex --ignoreexternal" -"typecheck:mypy" = "mypy ." - -[build-system] -requires = ["hatchling==1.26.3", "hatch-fancy-pypi-readme"] -build-backend = "hatchling.build" - -[dependency-groups] -dev = [ "ipywidgets>=8.1.7", "nbstripout>=0.8.1", "yaspin>=3.1.0", diff --git a/requirements-dev.lock b/requirements-dev.lock deleted file mode 100644 index 1078b30de..000000000 --- a/requirements-dev.lock +++ /dev/null @@ -1,422 +0,0 @@ -# generated by rye -# use `rye lock` or `rye sync` to update this lockfile -# -# last locked with the following flags: -# pre: false -# features: [] -# all-features: true -# with-sources: false -# generate-hashes: false -# universal: false - --e file:. -aiohappyeyeballs==2.6.1 - # via aiohttp -aiohttp==3.13.2 - # via agentex-sdk - # via httpx-aiohttp - # via litellm -aiosignal==1.3.2 - # via aiohttp -annotated-types==0.7.0 - # via pydantic -anyio==4.10.0 - # via agentex-sdk - # via httpx - # via mcp - # via openai - # via scale-gp - # via scale-gp-beta - # via sse-starlette - # via starlette - # via watchfiles -appnope==0.1.4 - # via ipykernel -argcomplete==3.1.2 - # via nox -asttokens==3.0.0 - # via stack-data -attrs==25.3.0 - # via aiohttp - # via jsonschema - # via referencing -bytecode==0.17.0 - # via ddtrace -cachetools==5.5.2 - # via google-auth -certifi==2023.7.22 - # via httpcore - # via httpx - # via kubernetes - # via requests -charset-normalizer==3.4.3 - # via requests -click==8.2.1 - # via litellm - # via typer - # via uvicorn -cloudpickle==3.1.1 - # via agentex-sdk -colorama==0.4.6 - # via griffe -colorlog==6.7.0 - # via nox -comm==0.2.3 - # via ipykernel -datadog==0.52.1 - # via agentex-sdk -ddtrace==3.15.0 - # via agentex-sdk -debugpy==1.8.16 - # via ipykernel -decorator==5.2.1 - # via ipython -dirty-equals==0.6.0 -distlib==0.3.7 - # via virtualenv -distro==1.9.0 - # via agentex-sdk - # via openai - # via scale-gp - # via scale-gp-beta -envier==0.6.1 - # via ddtrace -execnet==2.1.1 - # via pytest-xdist -executing==2.2.0 - # via stack-data -fastapi==0.115.14 - # via agentex-sdk -filelock==3.12.4 - # via huggingface-hub - # via virtualenv -frozenlist==1.8.0 - # via aiohttp - # via aiosignal -fsspec==2025.7.0 - # via huggingface-hub -google-auth==2.40.3 - # via kubernetes -griffe==1.12.0 - # via openai-agents -h11==0.16.0 - # via httpcore - # via uvicorn -hf-xet==1.1.7 - # via huggingface-hub -httpcore==1.0.9 - # via httpx -httpx==0.27.2 - # via agentex-sdk - # via httpx-aiohttp - # via litellm - # via mcp - # via openai - # via respx - # via scale-gp - # via scale-gp-beta -httpx-aiohttp==0.1.9 - # via agentex-sdk -httpx-sse==0.4.1 - # via mcp -huggingface-hub==0.34.4 - # via tokenizers -idna==3.4 - # via anyio - # via httpx - # via requests - # via yarl -importlib-metadata==7.0.0 - # via litellm - # via opentelemetry-api -iniconfig==2.0.0 - # via pytest -ipykernel==6.30.1 - # via agentex-sdk -ipython==9.4.0 - # via ipykernel -ipython-pygments-lexers==1.1.1 - # via ipython -jedi==0.19.2 - # via ipython -jinja2==3.1.6 - # via agentex-sdk - # via litellm -jiter==0.10.0 - # via openai -json-log-formatter==1.1.1 - # via agentex-sdk -jsonref==1.1.0 - # via agentex-sdk -jsonschema==4.25.0 - # via agentex-sdk - # via litellm - # via mcp -jsonschema-specifications==2025.4.1 - # via jsonschema -jupyter-client==8.6.3 - # via ipykernel -jupyter-core==5.8.1 - # via ipykernel - # via jupyter-client -kubernetes==28.1.0 - # via agentex-sdk -litellm==1.75.5.post1 - # via agentex-sdk -markdown-it-py==3.0.0 - # via rich -markupsafe==3.0.2 - # via jinja2 -matplotlib-inline==0.1.7 - # via ipykernel - # via ipython -mcp==1.12.4 - # via agentex-sdk - # via openai-agents -mdurl==0.1.2 - # via markdown-it-py -multidict==6.7.0 - # via aiohttp - # via yarl -mypy==1.17.0 -mypy-extensions==1.1.0 - # via mypy -nest-asyncio==1.6.0 - # via ipykernel -nexus-rpc==1.1.0 - # via temporalio -nodeenv==1.8.0 - # via pyright -nox==2023.4.22 -oauthlib==3.3.1 - # via kubernetes - # via requests-oauthlib -openai==2.7.1 - # via agentex-sdk - # via litellm - # via openai-agents -openai-agents==0.4.2 - # via agentex-sdk -opentelemetry-api==1.37.0 - # via ddtrace -packaging==23.2 - # via huggingface-hub - # via ipykernel - # via nox - # via pytest -pathspec==0.12.1 - # via mypy -parso==0.8.4 - # via jedi -pexpect==4.9.0 - # via ipython -platformdirs==3.11.0 - # via jupyter-core - # via virtualenv -pluggy==1.6.0 - # via pytest -prompt-toolkit==3.0.51 - # via ipython - # via questionary -propcache==0.3.1 - # via aiohttp - # via yarl -protobuf==5.29.5 - # via ddtrace - # via temporalio -psutil==7.0.0 - # via ipykernel -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.3 - # via stack-data -pyasn1==0.6.1 - # via pyasn1-modules - # via rsa -pyasn1-modules==0.4.2 - # via google-auth -pydantic==2.11.9 - # via agentex-sdk - # via fastapi - # via litellm - # via mcp - # via openai - # via openai-agents - # via pydantic-settings - # via python-on-whales - # via scale-gp - # via scale-gp-beta -pydantic-core==2.33.2 - # via pydantic -pydantic-settings==2.10.1 - # via mcp -pygments==2.18.0 - # via ipython - # via ipython-pygments-lexers - # via pytest - # via rich -pyjwt==2.10.1 - # via redis -pyright==1.1.399 -pytest==8.4.1 - # via agentex-sdk - # via pytest-asyncio - # via pytest-xdist -pytest-asyncio==1.1.0 - # via agentex-sdk -pytest-xdist==3.7.0 -python-dateutil==2.8.2 - # via jupyter-client - # via kubernetes - # via time-machine -python-dotenv==1.1.1 - # via litellm - # via mcp - # via pydantic-settings -python-multipart==0.0.20 - # via mcp -python-on-whales==0.73.0 - # via agentex-sdk -pytz==2023.3.post1 - # via dirty-equals -pyyaml==6.0.2 - # via agentex-sdk - # via huggingface-hub - # via kubernetes -pyzmq==27.0.1 - # via ipykernel - # via jupyter-client -questionary==2.1.0 - # via agentex-sdk -redis==5.3.1 - # via agentex-sdk -referencing==0.36.2 - # via jsonschema - # via jsonschema-specifications -regex==2025.7.34 - # via tiktoken -requests==2.32.4 - # via datadog - # via huggingface-hub - # via kubernetes - # via openai-agents - # via python-on-whales - # via requests-oauthlib - # via tiktoken -requests-oauthlib==2.0.0 - # via kubernetes -respx==0.22.0 -rich==13.9.4 - # via agentex-sdk - # via typer -rpds-py==0.27.0 - # via jsonschema - # via referencing -rsa==4.9.1 - # via google-auth -ruff==0.9.4 - # via agentex-sdk -scale-gp==0.1.0a59 - # via agentex-sdk -scale-gp-beta==0.1.0a20 - # via agentex-sdk -setuptools==68.2.2 - # via nodeenv -shellingham==1.5.4 - # via typer -six==1.16.0 - # via kubernetes - # via python-dateutil -sniffio==1.3.1 - # via agentex-sdk - # via anyio - # via httpx - # via openai - # via scale-gp - # via scale-gp-beta -sse-starlette==3.0.2 - # via mcp -stack-data==0.6.3 - # via ipython -starlette==0.46.2 - # via fastapi - # via mcp -temporalio==1.18.2 - # via agentex-sdk -tiktoken==0.11.0 - # via litellm -time-machine==2.9.0 -tokenizers==0.21.4 - # via litellm -tornado==6.5.2 - # via ipykernel - # via jupyter-client -tqdm==4.67.1 - # via huggingface-hub - # via openai - # via python-on-whales -traitlets==5.14.3 - # via ipykernel - # via ipython - # via jupyter-client - # via jupyter-core - # via matplotlib-inline -typer==0.16.0 - # via agentex-sdk - # via mcp - # via python-on-whales -types-protobuf==6.30.2.20250809 - # via temporalio -types-requests==2.31.0.6 - # via openai-agents -types-urllib3==1.26.25.14 - # via types-requests -typing-extensions==4.12.2 - # via agentex-sdk - # via aiosignal - # via anyio - # via fastapi - # via huggingface-hub - # via mypy - # via nexus-rpc - # via openai - # via openai-agents - # via opentelemetry-api - # via pydantic - # via pydantic-core - # via pyright - # via python-on-whales - # via referencing - # via scale-gp - # via scale-gp-beta - # via temporalio - # via typer - # via typing-inspection - # via virtualenv -typing-inspection==0.4.2 - # via pydantic - # via pydantic-settings -tzdata==2025.2 - # via agentex-sdk -tzlocal==5.3.1 - # via agentex-sdk -urllib3==1.26.20 - # via kubernetes - # via requests -uvicorn==0.35.0 - # via agentex-sdk - # via mcp -virtualenv==20.24.5 - # via nox -watchfiles==0.24.0 - # via agentex-sdk -wcwidth==0.2.13 - # via prompt-toolkit -websocket-client==1.8.0 - # via kubernetes -wrapt==1.17.3 - # via ddtrace -yarl==1.20.0 - # via aiohttp -zipp==3.23.0 - # via importlib-metadata diff --git a/requirements.lock b/requirements.lock deleted file mode 100644 index 79519671e..000000000 --- a/requirements.lock +++ /dev/null @@ -1,376 +0,0 @@ -# generated by rye -# use `rye lock` or `rye sync` to update this lockfile -# -# last locked with the following flags: -# pre: false -# features: [] -# all-features: true -# with-sources: false -# generate-hashes: false -# universal: false - --e file:. -aiohappyeyeballs==2.6.1 - # via aiohttp -aiohttp==3.13.2 - # via agentex-sdk - # via httpx-aiohttp - # via litellm -aiosignal==1.3.2 - # via aiohttp -annotated-types==0.7.0 - # via pydantic -anyio==4.10.0 - # via agentex-sdk - # via httpx - # via mcp - # via openai - # via scale-gp - # via scale-gp-beta - # via sse-starlette - # via starlette - # via watchfiles -appnope==0.1.4 - # via ipykernel -asttokens==3.0.0 - # via stack-data -attrs==25.3.0 - # via aiohttp - # via jsonschema - # via referencing -bytecode==0.17.0 - # via ddtrace -cachetools==5.5.2 - # via google-auth -certifi==2023.7.22 - # via httpcore - # via httpx - # via kubernetes - # via requests -charset-normalizer==3.4.3 - # via requests -click==8.2.1 - # via litellm - # via typer - # via uvicorn -cloudpickle==3.1.1 - # via agentex-sdk -colorama==0.4.6 - # via griffe -comm==0.2.3 - # via ipykernel -datadog==0.52.1 - # via agentex-sdk -ddtrace==3.15.0 - # via agentex-sdk -debugpy==1.8.16 - # via ipykernel -decorator==5.2.1 - # via ipython -distro==1.8.0 - # via agentex-sdk - # via openai - # via scale-gp - # via scale-gp-beta -envier==0.6.1 - # via ddtrace -executing==2.2.0 - # via stack-data -fastapi==0.115.14 - # via agentex-sdk -filelock==3.19.1 - # via huggingface-hub -frozenlist==1.6.2 - # via aiohttp - # via aiosignal -fsspec==2025.7.0 - # via huggingface-hub -google-auth==2.40.3 - # via kubernetes -griffe==1.12.0 - # via openai-agents -h11==0.16.0 - # via httpcore - # via uvicorn -hf-xet==1.1.7 - # via huggingface-hub -httpcore==1.0.9 - # via httpx -httpx==0.27.2 - # via agentex-sdk - # via httpx-aiohttp - # via litellm - # via mcp - # via openai - # via scale-gp - # via scale-gp-beta -httpx-aiohttp==0.1.9 - # via agentex-sdk -httpx-sse==0.4.1 - # via mcp -huggingface-hub==0.34.4 - # via tokenizers -idna==3.4 - # via anyio - # via httpx - # via requests - # via yarl -importlib-metadata==8.7.0 - # via litellm - # via opentelemetry-api -iniconfig==2.1.0 - # via pytest -ipykernel==6.30.1 - # via agentex-sdk -ipython==9.4.0 - # via ipykernel -ipython-pygments-lexers==1.1.1 - # via ipython -jedi==0.19.2 - # via ipython -jinja2==3.1.6 - # via agentex-sdk - # via litellm -jiter==0.10.0 - # via openai -json-log-formatter==1.1.1 - # via agentex-sdk -jsonref==1.1.0 - # via agentex-sdk -jsonschema==4.25.0 - # via agentex-sdk - # via litellm - # via mcp -jsonschema-specifications==2025.4.1 - # via jsonschema -jupyter-client==8.6.3 - # via ipykernel -jupyter-core==5.8.1 - # via ipykernel - # via jupyter-client -kubernetes==28.1.0 - # via agentex-sdk -litellm==1.75.5.post1 - # via agentex-sdk -markdown-it-py==4.0.0 - # via rich -markupsafe==3.0.2 - # via jinja2 -matplotlib-inline==0.1.7 - # via ipykernel - # via ipython -mcp==1.12.4 - # via agentex-sdk - # via openai-agents -mdurl==0.1.2 - # via markdown-it-py -multidict==6.4.4 - # via aiohttp - # via yarl -nest-asyncio==1.6.0 - # via ipykernel -nexus-rpc==1.1.0 - # via temporalio -oauthlib==3.3.1 - # via kubernetes - # via requests-oauthlib -openai==2.7.1 - # via agentex-sdk - # via litellm - # via openai-agents -openai-agents==0.4.2 - # via agentex-sdk -opentelemetry-api==1.37.0 - # via ddtrace -packaging==25.0 - # via huggingface-hub - # via ipykernel - # via pytest -parso==0.8.4 - # via jedi -pexpect==4.9.0 - # via ipython -platformdirs==4.3.8 - # via jupyter-core -pluggy==1.6.0 - # via pytest -prompt-toolkit==3.0.51 - # via ipython - # via questionary -propcache==0.3.1 - # via aiohttp - # via yarl -pydantic==2.12.5 - # via agentex-sdk -pydantic-core==2.41.5 -protobuf==5.29.5 - # via ddtrace - # via temporalio -psutil==7.0.0 - # via ipykernel -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.3 - # via stack-data -pyasn1==0.6.1 - # via pyasn1-modules - # via rsa -pyasn1-modules==0.4.2 - # via google-auth - # via pydantic -pydantic-settings==2.10.1 - # via mcp -pygments==2.19.2 - # via ipython - # via ipython-pygments-lexers - # via pytest - # via rich -pyjwt==2.10.1 - # via redis -pytest==8.4.1 - # via agentex-sdk - # via pytest-asyncio -pytest-asyncio==1.1.0 - # via agentex-sdk -python-dateutil==2.9.0.post0 - # via jupyter-client - # via kubernetes -python-dotenv==1.1.1 - # via litellm - # via mcp - # via pydantic-settings -python-multipart==0.0.20 - # via mcp -python-on-whales==0.73.0 - # via agentex-sdk -pyyaml==6.0.2 - # via agentex-sdk - # via huggingface-hub - # via kubernetes -pyzmq==27.0.1 - # via ipykernel - # via jupyter-client -questionary==2.1.0 - # via agentex-sdk -redis==5.3.1 - # via agentex-sdk -referencing==0.36.2 - # via jsonschema - # via jsonschema-specifications -regex==2025.7.34 - # via tiktoken -requests==2.32.4 - # via datadog - # via huggingface-hub - # via kubernetes - # via openai-agents - # via python-on-whales - # via requests-oauthlib - # via tiktoken -requests-oauthlib==2.0.0 - # via kubernetes -rich==13.9.4 - # via agentex-sdk - # via typer -rpds-py==0.27.0 - # via jsonschema - # via referencing -rsa==4.9.1 - # via google-auth -ruff==0.12.9 - # via agentex-sdk -scale-gp==0.1.0a59 - # via agentex-sdk -scale-gp-beta==0.1.0a20 - # via agentex-sdk -shellingham==1.5.4 - # via typer -six==1.17.0 - # via kubernetes - # via python-dateutil -sniffio==1.3.0 - # via agentex-sdk -typing-extensions==4.15.0 - # via httpx - # via openai - # via scale-gp - # via scale-gp-beta -sse-starlette==3.0.2 - # via mcp -stack-data==0.6.3 - # via ipython -starlette==0.46.2 - # via fastapi - # via mcp -temporalio==1.18.2 - # via agentex-sdk -tiktoken==0.11.0 - # via litellm -tokenizers==0.21.4 - # via litellm -tornado==6.5.2 - # via ipykernel - # via jupyter-client -tqdm==4.67.1 - # via huggingface-hub - # via openai - # via python-on-whales -traitlets==5.14.3 - # via ipykernel - # via ipython - # via jupyter-client - # via jupyter-core - # via matplotlib-inline -typer==0.16.0 - # via agentex-sdk - # via mcp - # via python-on-whales -types-protobuf==6.30.2.20250809 - # via temporalio -types-requests==2.31.0.6 - # via openai-agents -types-urllib3==1.26.25.14 - # via types-requests - # via agentex-sdk - # via aiosignal - # via anyio - # via fastapi - # via huggingface-hub - # via nexus-rpc - # via openai - # via openai-agents - # via opentelemetry-api - # via pydantic - # via pydantic-core - # via python-on-whales - # via referencing - # via scale-gp - # via scale-gp-beta - # via temporalio - # via typer - # via typing-inspection -typing-inspection==0.4.2 - # via pydantic - # via pydantic-settings -tzdata==2025.2 - # via agentex-sdk -tzlocal==5.3.1 - # via agentex-sdk -urllib3==1.26.20 - # via kubernetes - # via requests -uvicorn==0.35.0 - # via agentex-sdk - # via mcp -watchfiles==0.24.0 - # via agentex-sdk -wcwidth==0.2.13 - # via prompt-toolkit -websocket-client==1.8.0 - # via kubernetes -wrapt==1.17.3 - # via ddtrace -yarl==1.20.0 - # via aiohttp -zipp==3.23.0 - # via importlib-metadata diff --git a/scripts/bootstrap b/scripts/bootstrap index b430fee36..711a1f08e 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,24 +4,12 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then - brew bundle check >/dev/null 2>&1 || { - echo -n "==> Install Homebrew dependencies? (y/N): " - read -r response - case "$response" in - [yY][eE][sS]|[yY]) - brew bundle - ;; - *) - ;; - esac - echo - } +if ! command -v uv &> /dev/null; then + echo "Error: uv is not installed." + echo "Install it from https://docs.astral.sh/uv/getting-started/installation/" + exit 1 fi echo "==> Installing Python dependencies…" -# experimental uv support makes installations significantly faster -rye config --set-bool behavior.use-uv=true - -rye sync --all-features +uv sync --all-groups diff --git a/scripts/format b/scripts/format index 667ec2d7a..23dd53ddd 100755 --- a/scripts/format +++ b/scripts/format @@ -5,4 +5,8 @@ set -e cd "$(dirname "$0")/.." echo "==> Running formatters" -rye run format +uv run ruff format "$@" +uv run python scripts/utils/ruffen-docs.py README.md api.md +uv run ruff check --fix "$@" +# run formatting again to fix any inconsistencies when imports are stripped +uv run ruff format "$@" diff --git a/scripts/lint b/scripts/lint index add940371..e01774fcd 100755 --- a/scripts/lint +++ b/scripts/lint @@ -6,11 +6,12 @@ cd "$(dirname "$0")/.." if [ "$1" = "--fix" ]; then echo "==> Running lints with --fix" - rye run fix:ruff + uv run ruff check --fix . else echo "==> Running lints" - rye run lint + uv run ruff check . + uv run pyright fi echo "==> Making sure it imports" -rye run python -c 'import agentex' +uv run python -c 'import agentex' diff --git a/scripts/test b/scripts/test index 2c69d995f..db770565d 100755 --- a/scripts/test +++ b/scripts/test @@ -55,4 +55,4 @@ fi export DEFER_PYDANTIC_BUILD=false echo "==> Running tests" -rye run pytest "$@" +uv run pytest "$@" diff --git a/src/agentex/lib/core/temporal/plugins/openai_agents/README.md b/src/agentex/lib/core/temporal/plugins/openai_agents/README.md index 5497c4666..dfb8c9e88 100644 --- a/src/agentex/lib/core/temporal/plugins/openai_agents/README.md +++ b/src/agentex/lib/core/temporal/plugins/openai_agents/README.md @@ -701,13 +701,13 @@ The streaming model implementation has comprehensive tests in `tests/test_stream ```bash # Run all tests -rye run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_streaming_model.py -v +uv run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_streaming_model.py -v # Run without parallel execution (more stable) -rye run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_streaming_model.py -v -n0 +uv run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_streaming_model.py -v -n0 # Run specific test -rye run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_streaming_model.py::TestStreamingModelSettings::test_temperature_setting -v +uv run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_streaming_model.py::TestStreamingModelSettings::test_temperature_setting -v ``` #### From Test Directory @@ -716,13 +716,13 @@ rye run pytest src/agentex/lib/core/temporal/plugins/openai_agents/tests/test_st cd src/agentex/lib/core/temporal/plugins/openai_agents/tests # Run all tests -rye run pytest test_streaming_model.py -v +uv run pytest test_streaming_model.py -v # Run without parallel execution (recommended) -rye run pytest test_streaming_model.py -v -n0 +uv run pytest test_streaming_model.py -v -n0 # Run specific test class -rye run pytest test_streaming_model.py::TestStreamingModelSettings -v +uv run pytest test_streaming_model.py::TestStreamingModelSettings -v ``` #### Test Coverage diff --git a/uv.lock b/uv.lock index 828726620..0641c2e22 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "agentex-sdk" -version = "0.9.3" +version = "0.9.4" source = { editable = "." } dependencies = [ { name = "aiohttp" }, @@ -64,8 +64,22 @@ dev = [ [package.dev-dependencies] dev = [ + { name = "debugpy" }, + { name = "dirty-equals" }, + { name = "importlib-metadata" }, { name = "ipywidgets" }, + { name = "mypy" }, { name = "nbstripout" }, + { name = "nest-asyncio" }, + { name = "nox" }, + { name = "pyright" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-xdist" }, + { name = "respx" }, + { name = "rich" }, + { name = "ruff" }, + { name = "time-machine" }, { name = "yaspin" }, ] @@ -119,8 +133,22 @@ provides-extras = ["aiohttp", "dev"] [package.metadata.requires-dev] dev = [ + { name = "debugpy", specifier = ">=1.8.15" }, + { name = "dirty-equals", specifier = ">=0.6.0" }, + { name = "importlib-metadata", specifier = ">=6.7.0" }, { name = "ipywidgets", specifier = ">=8.1.7" }, + { name = "mypy", specifier = "==1.17" }, { name = "nbstripout", specifier = ">=0.8.1" }, + { name = "nest-asyncio", specifier = "==1.6.0" }, + { name = "nox" }, + { name = "pyright", specifier = "==1.1.399" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-xdist", specifier = ">=3.6.1" }, + { name = "respx" }, + { name = "rich", specifier = ">=13.7.1" }, + { name = "ruff" }, + { name = "time-machine" }, { name = "yaspin", specifier = ">=3.1.0" }, ] @@ -248,6 +276,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, ] +[[package]] +name = "argcomplete" +version = "3.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/61/0b9ae6399dd4a58d8c1b1dc5a27d6f2808023d0b5dd3104bb99f45a33ff6/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c", size = 73754, upload-time = "2025-10-20T03:33:34.741Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce", size = 43846, upload-time = "2025-10-20T03:33:33.021Z" }, +] + [[package]] name = "asttokens" version = "3.0.0" @@ -437,6 +474,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "colorlog" +version = "6.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/61/f083b5ac52e505dfc1c624eafbf8c7589a0d7f32daa398d2e7590efa5fda/colorlog-6.10.1.tar.gz", hash = "sha256:eb4ae5cb65fe7fec7773c2306061a8e63e02efc2c72eba9d27b0fa23c94f1321", size = 17162, upload-time = "2025-10-16T16:14:11.978Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl", hash = "sha256:2d7e8348291948af66122cff006c9f8da6255d224e7cf8e37d8de2df3bad8c9c", size = 11743, upload-time = "2025-10-16T16:14:10.512Z" }, +] + [[package]] name = "comm" version = "0.2.3" @@ -526,6 +575,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, ] +[[package]] +name = "dependency-groups" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" }, +] + +[[package]] +name = "dirty-equals" +version = "0.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/1d/c5913ac9d6615515a00f4bdc71356d302437cb74ff2e9aaccd3c14493b78/dirty_equals-0.11.tar.gz", hash = "sha256:f4ac74ee88f2d11e2fa0f65eb30ee4f07105c5f86f4dc92b09eb1138775027c3", size = 128067, upload-time = "2025-11-17T01:51:24.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/8d/dbff05239043271dbeace563a7686212a3dd517864a35623fe4d4a64ca19/dirty_equals-0.11-py3-none-any.whl", hash = "sha256:b1d7093273fc2f9be12f443a8ead954ef6daaf6746fd42ef3a5616433ee85286", size = 28051, upload-time = "2025-11-17T01:51:22.849Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + [[package]] name = "distro" version = "1.9.0" @@ -553,6 +632,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/e9/30493b1cc967f7c07869de4b2ab3929151a58e6bb04495015554d24b61db/envier-0.6.1-py3-none-any.whl", hash = "sha256:73609040a76be48bbcb97074d9969666484aa0de706183a6e9ef773156a8a6a9", size = 10638, upload-time = "2024-10-22T09:56:45.968Z" }, ] +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, +] + [[package]] name = "executing" version = "2.2.1" @@ -617,11 +705,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.19.1" +version = "3.25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/18/a1fd2231c679dcb9726204645721b12498aeac28e1ad0601038f94b42556/filelock-3.25.0.tar.gz", hash = "sha256:8f00faf3abf9dc730a1ffe9c354ae5c04e079ab7d3a683b7c32da5dd05f26af3", size = 40158, upload-time = "2026-03-01T15:08:45.916Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, + { url = "https://files.pythonhosted.org/packages/f9/0b/de6f54d4a8bedfe8645c41497f3c18d749f0bd3218170c667bf4b81d0cdd/filelock-3.25.0-py3-none-any.whl", hash = "sha256:5ccf8069f7948f494968fc0713c10e5c182a9c9d9eef3a636307a20c2490f047", size = 26427, upload-time = "2026-03-01T15:08:44.593Z" }, ] [[package]] @@ -813,6 +901,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/31/a0/651f93d154cb72323358bf2bbae3e642bdb5d2f1bfc874d096f7cb159fa0/huggingface_hub-0.35.3-py3-none-any.whl", hash = "sha256:0e3a01829c19d86d03793e4577816fe3bdfc1602ac62c7fb220d593d351224ba", size = 564262, upload-time = "2025-09-29T14:29:55.813Z" }, ] +[[package]] +name = "humanize" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" }, +] + [[package]] name = "idna" version = "3.10" @@ -1382,6 +1479,41 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, ] +[[package]] +name = "mypy" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/e3/034322d5a779685218ed69286c32faa505247f1f096251ef66c8fd203b08/mypy-1.17.0.tar.gz", hash = "sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03", size = 3352114, upload-time = "2025-07-14T20:34:30.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/e9/e6824ed620bbf51d3bf4d6cbbe4953e83eaf31a448d1b3cfb3620ccb641c/mypy-1.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb", size = 11086395, upload-time = "2025-07-14T20:34:11.452Z" }, + { url = "https://files.pythonhosted.org/packages/ba/51/a4afd1ae279707953be175d303f04a5a7bd7e28dc62463ad29c1c857927e/mypy-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d", size = 10120052, upload-time = "2025-07-14T20:33:09.897Z" }, + { url = "https://files.pythonhosted.org/packages/8a/71/19adfeac926ba8205f1d1466d0d360d07b46486bf64360c54cb5a2bd86a8/mypy-1.17.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8", size = 11861806, upload-time = "2025-07-14T20:32:16.028Z" }, + { url = "https://files.pythonhosted.org/packages/0b/64/d6120eca3835baf7179e6797a0b61d6c47e0bc2324b1f6819d8428d5b9ba/mypy-1.17.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e", size = 12744371, upload-time = "2025-07-14T20:33:33.503Z" }, + { url = "https://files.pythonhosted.org/packages/1f/dc/56f53b5255a166f5bd0f137eed960e5065f2744509dfe69474ff0ba772a5/mypy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8", size = 12914558, upload-time = "2025-07-14T20:33:56.961Z" }, + { url = "https://files.pythonhosted.org/packages/69/ac/070bad311171badc9add2910e7f89271695a25c136de24bbafc7eded56d5/mypy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d", size = 9585447, upload-time = "2025-07-14T20:32:20.594Z" }, + { url = "https://files.pythonhosted.org/packages/be/7b/5f8ab461369b9e62157072156935cec9d272196556bdc7c2ff5f4c7c0f9b/mypy-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06", size = 11070019, upload-time = "2025-07-14T20:32:07.99Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f8/c49c9e5a2ac0badcc54beb24e774d2499748302c9568f7f09e8730e953fa/mypy-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a", size = 10114457, upload-time = "2025-07-14T20:33:47.285Z" }, + { url = "https://files.pythonhosted.org/packages/89/0c/fb3f9c939ad9beed3e328008b3fb90b20fda2cddc0f7e4c20dbefefc3b33/mypy-1.17.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889", size = 11857838, upload-time = "2025-07-14T20:33:14.462Z" }, + { url = "https://files.pythonhosted.org/packages/4c/66/85607ab5137d65e4f54d9797b77d5a038ef34f714929cf8ad30b03f628df/mypy-1.17.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba", size = 12731358, upload-time = "2025-07-14T20:32:25.579Z" }, + { url = "https://files.pythonhosted.org/packages/73/d0/341dbbfb35ce53d01f8f2969facbb66486cee9804048bf6c01b048127501/mypy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658", size = 12917480, upload-time = "2025-07-14T20:34:21.868Z" }, + { url = "https://files.pythonhosted.org/packages/64/63/70c8b7dbfc520089ac48d01367a97e8acd734f65bd07813081f508a8c94c/mypy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c", size = 9589666, upload-time = "2025-07-14T20:34:16.841Z" }, + { url = "https://files.pythonhosted.org/packages/e3/fc/ee058cc4316f219078464555873e99d170bde1d9569abd833300dbeb484a/mypy-1.17.0-py3-none-any.whl", hash = "sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496", size = 2283195, upload-time = "2025-07-14T20:31:54.753Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + [[package]] name = "nbformat" version = "5.10.4" @@ -1430,6 +1562,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bf/2f/9e9d0dcaa4c6ffa22b7aa31069a8a264c753ff8027b36af602cce038c92f/nexus_rpc-1.1.0-py3-none-any.whl", hash = "sha256:d1b007af2aba186a27e736f8eaae39c03aed05b488084ff6c3d1785c9ba2ad38", size = 27743, upload-time = "2025-07-07T19:03:57.556Z" }, ] +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + +[[package]] +name = "nox" +version = "2026.2.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argcomplete" }, + { name = "attrs" }, + { name = "colorlog" }, + { name = "dependency-groups" }, + { name = "humanize" }, + { name = "packaging" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/8e/55a9679b31f1efc48facedd2448eb53c7f1e647fb592aa1403c9dd7a4590/nox-2026.2.9.tar.gz", hash = "sha256:1bc8a202ee8cd69be7aaada63b2a7019126899a06fc930a7aee75585bf8ee41b", size = 4031165, upload-time = "2026-02-10T04:38:58.878Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/58/0d5e5a044f1868bdc45f38afdc2d90ff9867ce398b4e8fa9e666bfc9bfba/nox-2026.2.9-py3-none-any.whl", hash = "sha256:1b7143bc8ecdf25f2353201326152c5303ae4ae56ca097b1fb6179ad75164c47", size = 74615, upload-time = "2026-02-10T04:38:57.266Z" }, +] + [[package]] name = "oauthlib" version = "3.3.1" @@ -1599,6 +1758,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, ] +[[package]] +name = "pathspec" +version = "1.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, +] + [[package]] name = "pexpect" version = "4.9.0" @@ -1865,6 +2033,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, ] +[[package]] +name = "pyright" +version = "1.1.399" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nodeenv" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/9d/d91d5f6d26b2db95476fefc772e2b9a16d54c6bd0ea6bb5c1b6d635ab8b4/pyright-1.1.399.tar.gz", hash = "sha256:439035d707a36c3d1b443aec980bc37053fbda88158eded24b8eedcf1c7b7a1b", size = 3856954, upload-time = "2025-04-10T04:40:25.703Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/b5/380380c9e7a534cb1783c70c3e8ac6d1193c599650a55838d0557586796e/pyright-1.1.399-py3-none-any.whl", hash = "sha256:55f9a875ddf23c9698f24208c764465ffdfd38be6265f7faf9a176e1dc549f3b", size = 5592584, upload-time = "2025-04-10T04:40:23.502Z" }, +] + [[package]] name = "pytest" version = "8.4.2" @@ -1894,6 +2075,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/04/93/2fa34714b7a4ae72f2f8dad66ba17dd9a2c793220719e736dda28b7aec27/pytest_asyncio-1.2.0-py3-none-any.whl", hash = "sha256:8e17ae5e46d8e7efe51ab6494dd2010f4ca8dae51652aa3c8d55acf50bfb2e99", size = 15095, upload-time = "2025-09-12T07:33:52.639Z" }, ] +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -1906,6 +2100,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-discovery" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/bb/93a3e83bdf9322c7e21cafd092e56a4a17c4d8ef4277b6eb01af1a540a6f/python_discovery-1.1.0.tar.gz", hash = "sha256:447941ba1aed8cc2ab7ee3cb91be5fc137c5bdbb05b7e6ea62fbdcb66e50b268", size = 55674, upload-time = "2026-02-26T09:42:49.668Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/54/82a6e2ef37f0f23dccac604b9585bdcbd0698604feb64807dcb72853693e/python_discovery-1.1.0-py3-none-any.whl", hash = "sha256:a162893b8809727f54594a99ad2179d2ede4bf953e12d4c7abc3cc9cdbd1437b", size = 30687, upload-time = "2026-02-26T09:42:48.548Z" }, +] + [[package]] name = "python-dotenv" version = "1.1.1" @@ -2201,6 +2408,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, ] +[[package]] +name = "respx" +version = "0.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/7c/96bd0bc759cf009675ad1ee1f96535edcb11e9666b985717eb8c87192a95/respx-0.22.0.tar.gz", hash = "sha256:3c8924caa2a50bd71aefc07aa812f2466ff489f1848c96e954a5362d17095d91", size = 28439, upload-time = "2024-12-19T22:33:59.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/67/afbb0978d5399bc9ea200f1d4489a23c9a1dad4eee6376242b8182389c79/respx-0.22.0-py2.py3-none-any.whl", hash = "sha256:631128d4c9aba15e56903fb5f66fb1eff412ce28dd387ca3a81339e52dbd3ad0", size = 25127, upload-time = "2024-12-19T22:33:57.837Z" }, +] + [[package]] name = "rich" version = "13.9.4" @@ -2493,6 +2712,69 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/79/bcf350609f3a10f09fe4fc207f132085e497fdd3612f3925ab24d86a0ca0/tiktoken-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:2177ffda31dec4023356a441793fed82f7af5291120751dee4d696414f54db0c", size = 883901, upload-time = "2025-08-08T23:57:59.359Z" }, ] +[[package]] +name = "time-machine" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/fc/37b02f6094dbb1f851145330460532176ed2f1dc70511a35828166c41e52/time_machine-3.2.0.tar.gz", hash = "sha256:a4ddd1cea17b8950e462d1805a42b20c81eb9aafc8f66b392dd5ce997e037d79", size = 14804, upload-time = "2025-12-17T23:33:02.599Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/8b/080c8eedcd67921a52ba5bd0e075362062509ab63c86fc1a0442fad241a6/time_machine-3.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cc4bee5b0214d7dc4ebc91f4a4c600f1a598e9b5606ac751f42cb6f6740b1dbb", size = 19255, upload-time = "2025-12-17T23:31:58.057Z" }, + { url = "https://files.pythonhosted.org/packages/66/17/0e5291e9eb705bf8a5a1305f826e979af307bbeb79def4ddbf4b3f9a81e0/time_machine-3.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ca036304b4460ae2fdc1b52dd8b1fa7cf1464daa427fc49567413c09aa839c1", size = 15360, upload-time = "2025-12-17T23:31:59.048Z" }, + { url = "https://files.pythonhosted.org/packages/8b/e8/9ab87b71d2e2b62463b9b058b7ae7ac09fb57f8fcd88729dec169d304340/time_machine-3.2.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5442735b41d7a2abc2f04579b4ca6047ed4698a8338a4fec92c7c9423e7938cb", size = 33029, upload-time = "2025-12-17T23:32:00.413Z" }, + { url = "https://files.pythonhosted.org/packages/4b/26/b5ca19da6f25ea905b3e10a0ea95d697c1aeba0404803a43c68f1af253e6/time_machine-3.2.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:97da3e971e505cb637079fb07ab0bcd36e33279f8ecac888ff131f45ef1e4d8d", size = 34579, upload-time = "2025-12-17T23:32:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/79/ca/6ac7ad5f10ea18cc1d9de49716ba38c32132c7b64532430d92ef240c116b/time_machine-3.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3cdda6dee4966e38aeb487309bb414c6cb23a81fc500291c77a8fcd3098832e7", size = 35961, upload-time = "2025-12-17T23:32:02.521Z" }, + { url = "https://files.pythonhosted.org/packages/33/67/390dd958bed395ab32d79a9fe61fe111825c0dd4ded54dbba7e867f171e6/time_machine-3.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:33d9efd302a6998bcc8baa4d84f259f8a4081105bd3d7f7af7f1d0abd3b1c8aa", size = 34668, upload-time = "2025-12-17T23:32:03.585Z" }, + { url = "https://files.pythonhosted.org/packages/da/57/c88fff034a4e9538b3ae7c68c9cfb283670b14d17522c5a8bc17d29f9a4b/time_machine-3.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3a0b0a33971f14145853c9bd95a6ab0353cf7e0019fa2a7aa1ae9fddfe8eab50", size = 32891, upload-time = "2025-12-17T23:32:04.656Z" }, + { url = "https://files.pythonhosted.org/packages/2d/70/ebbb76022dba0fec8f9156540fc647e4beae1680c787c01b1b6200e56d70/time_machine-3.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2d0be9e5f22c38082d247a2cdcd8a936504e9db60b7b3606855fb39f299e9548", size = 34080, upload-time = "2025-12-17T23:32:06.146Z" }, + { url = "https://files.pythonhosted.org/packages/db/9a/2ca9e7af3df540dc1c79e3de588adeddb7dcc2107829248e6969c4f14167/time_machine-3.2.0-cp312-cp312-win32.whl", hash = "sha256:3f74623648b936fdce5f911caf386c0a0b579456410975de8c0dfeaaffece1d8", size = 17371, upload-time = "2025-12-17T23:32:07.164Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ce/21d23efc9c2151939af1b7ee4e60d86d661b74ef32b8eaa148f6fe8c899c/time_machine-3.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:34e26a41d994b5e4b205136a90e9578470386749cc9a2ecf51ca18f83ce25e23", size = 18132, upload-time = "2025-12-17T23:32:08.447Z" }, + { url = "https://files.pythonhosted.org/packages/2f/34/c2b70be483accf6db9e5d6c3139bce3c38fe51f898ccf64e8d3fe14fbf4d/time_machine-3.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:0615d3d82c418d6293f271c348945c5091a71f37e37173653d5c26d0e74b13a8", size = 16930, upload-time = "2025-12-17T23:32:09.477Z" }, + { url = "https://files.pythonhosted.org/packages/ee/cd/43ad5efc88298af3c59b66769cea7f055567a85071579ed40536188530c1/time_machine-3.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c421a8eb85a4418a7675a41bf8660224318c46cc62e4751c8f1ceca752059090", size = 19318, upload-time = "2025-12-17T23:32:10.518Z" }, + { url = "https://files.pythonhosted.org/packages/b0/f6/084010ef7f4a3f38b5a4900923d7c85b29e797655c4f6ee4ce54d903cca8/time_machine-3.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f4e758f7727d0058c4950c66b58200c187072122d6f7a98b610530a4233ea7b", size = 15390, upload-time = "2025-12-17T23:32:11.625Z" }, + { url = "https://files.pythonhosted.org/packages/25/aa/1cabb74134f492270dc6860cb7865859bf40ecf828be65972827646e91ad/time_machine-3.2.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:154bd3f75c81f70218b2585cc12b60762fb2665c507eec5ec5037d8756d9b4e0", size = 33115, upload-time = "2025-12-17T23:32:13.219Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/78c5d7dfa366924eb4dbfcc3fc917c39a4280ca234b12819cc1f16c03d88/time_machine-3.2.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d50cfe5ebea422c896ad8d278af9648412b7533b8ea6adeeee698a3fd9b1d3b7", size = 34705, upload-time = "2025-12-17T23:32:14.29Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/d5e877c24541f674c6869ff6e9c56833369796010190252e92c9d7ae5f0f/time_machine-3.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636576501724bd6a9124e69d86e5aef263479e89ef739c5db361469f0463a0a1", size = 36104, upload-time = "2025-12-17T23:32:15.354Z" }, + { url = "https://files.pythonhosted.org/packages/22/1c/d4bae72f388f67efc9609f89b012e434bb19d9549c7a7b47d6c7d9e5c55d/time_machine-3.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:40e6f40c57197fcf7ec32d2c563f4df0a82c42cdcc3cab27f688e98f6060df10", size = 34765, upload-time = "2025-12-17T23:32:16.434Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c3/ac378cf301d527d8dfad2f0db6bad0dfb1ab73212eaa56d6b96ee5d9d20b/time_machine-3.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a1bcf0b846bbfc19a79bc19e3fa04d8c7b1e8101c1b70340ffdb689cd801ea53", size = 33010, upload-time = "2025-12-17T23:32:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/06/35/7ce897319accda7a6970b288a9a8c52d25227342a7508505a2b3d235b649/time_machine-3.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ae55a56c179f4fe7a62575ad5148b6ed82f6c7e5cf2f9a9ec65f2f5b067db5f5", size = 34185, upload-time = "2025-12-17T23:32:18.566Z" }, + { url = "https://files.pythonhosted.org/packages/bf/28/f922022269749cb02eee2b62919671153c4088994fa955a6b0e50327ff81/time_machine-3.2.0-cp313-cp313-win32.whl", hash = "sha256:a66fe55a107e46916007a391d4030479df8864ec6ad6f6a6528221befc5c886e", size = 17397, upload-time = "2025-12-17T23:32:19.605Z" }, + { url = "https://files.pythonhosted.org/packages/ee/dc/fd87cde397f4a7bea493152f0aca8fd569ec709cad9e0f2ca7011eb8c7f7/time_machine-3.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:30c9ce57165df913e4f74e285a8ab829ff9b7aa3e5ec0973f88f642b9a7b3d15", size = 18139, upload-time = "2025-12-17T23:32:20.991Z" }, + { url = "https://files.pythonhosted.org/packages/75/81/b8ce58233addc5d7d54d2fabc49dcbc02d79e3f079d150aa1bec3d5275ef/time_machine-3.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:89cad7e179e9bdcc84dcf09efe52af232c4cc7a01b3de868356bbd59d95bd9b8", size = 16964, upload-time = "2025-12-17T23:32:22.075Z" }, + { url = "https://files.pythonhosted.org/packages/67/e7/487f0ba5fe6c58186a5e1af2a118dfa2c160fedb37ef53a7e972d410408e/time_machine-3.2.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:59d71545e62525a4b85b6de9ab5c02ee3c61110fd7f636139914a2335dcbfc9c", size = 20000, upload-time = "2025-12-17T23:32:23.058Z" }, + { url = "https://files.pythonhosted.org/packages/e1/17/eb2c0054c8d44dd42df84ccd434539249a9c7d0b8eb53f799be2102500ab/time_machine-3.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:999672c621c35362bc28e03ca0c7df21500195540773c25993421fd8d6cc5003", size = 15657, upload-time = "2025-12-17T23:32:24.125Z" }, + { url = "https://files.pythonhosted.org/packages/43/21/93443b5d1dd850f8bb9442e90d817a9033dcce6bfbdd3aabbb9786251c80/time_machine-3.2.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5faf7397f0580c7b9d67288522c8d7863e85f0cffadc0f1fccdb2c3dfce5783e", size = 39216, upload-time = "2025-12-17T23:32:25.542Z" }, + { url = "https://files.pythonhosted.org/packages/9f/9e/18544cf8acc72bb1dc03762231c82ecc259733f4bb6770a7bbe5cd138603/time_machine-3.2.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3dd886ec49f1fa5a00e844f5947e5c0f98ce574750c24b7424c6f77fc1c3e87", size = 40764, upload-time = "2025-12-17T23:32:26.643Z" }, + { url = "https://files.pythonhosted.org/packages/27/f7/9fe9ce2795636a3a7467307af6bdf38bb613ddb701a8a5cd50ec713beb5e/time_machine-3.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da0ecd96bc7bbe450acaaabe569d84e81688f1be8ad58d1470e42371d145fb53", size = 43526, upload-time = "2025-12-17T23:32:27.693Z" }, + { url = "https://files.pythonhosted.org/packages/03/c1/a93e975ba9dec22e87ec92d18c28e67d36bd536f9119ffa439b2892b0c9c/time_machine-3.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:158220e946c1c4fb8265773a0282c88c35a7e3bb5d78e3561214e3b3231166f3", size = 41727, upload-time = "2025-12-17T23:32:28.985Z" }, + { url = "https://files.pythonhosted.org/packages/5f/fb/e3633e5a6bbed1c76bb2e9810dabc2f8467532ffcd29b9aed404b473061a/time_machine-3.2.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c1aee29bc54356f248d5d7dfdd131e12ca825e850a08c0ebdb022266d073013", size = 38952, upload-time = "2025-12-17T23:32:30.031Z" }, + { url = "https://files.pythonhosted.org/packages/82/3d/02e9fb2526b3d6b1b45bc8e4d912d95d1cd699d1a3f6df985817d37a0600/time_machine-3.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c8ed2224f09d25b1c2fc98683613aca12f90f682a427eabb68fc824d27014e4a", size = 39829, upload-time = "2025-12-17T23:32:31.075Z" }, + { url = "https://files.pythonhosted.org/packages/85/c8/c14265212436da8e0814c45463987b3f57de3eca4de023cc2eabb0c62ef3/time_machine-3.2.0-cp313-cp313t-win32.whl", hash = "sha256:3498719f8dab51da76d29a20c1b5e52ee7db083dddf3056af7fa69c1b94e1fe6", size = 17852, upload-time = "2025-12-17T23:32:32.079Z" }, + { url = "https://files.pythonhosted.org/packages/1d/bc/8acb13cf6149f47508097b158a9a8bec9ec4530a70cb406124e8023581f5/time_machine-3.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:e0d90bee170b219e1d15e6a58164aa808f5170090e4f090bd0670303e34181b1", size = 18918, upload-time = "2025-12-17T23:32:33.106Z" }, + { url = "https://files.pythonhosted.org/packages/24/87/c443ee508c2708fd2514ccce9052f5e48888783ce690506919629ebc8eb0/time_machine-3.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:051de220fdb6e20d648111bbad423d9506fdbb2e44d4429cef3dc0382abf1fc2", size = 17261, upload-time = "2025-12-17T23:32:34.446Z" }, + { url = "https://files.pythonhosted.org/packages/61/70/b4b980d126ed155c78d1879c50d60c8dcbd47bd11cb14ee7be50e0dfc07f/time_machine-3.2.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:1398980c017fe5744d66f419e0115ee48a53b00b146d738e1416c225eb610b82", size = 19303, upload-time = "2025-12-17T23:32:35.796Z" }, + { url = "https://files.pythonhosted.org/packages/73/73/eaa33603c69a68fe2b6f54f9dd75481693d62f1d29676531002be06e2d1c/time_machine-3.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4f8f4e35f4191ef70c2ab8ff490761ee9051b891afce2bf86dde3918eb7b537b", size = 15431, upload-time = "2025-12-17T23:32:37.244Z" }, + { url = "https://files.pythonhosted.org/packages/76/10/b81e138e86cc7bab40cdb59d294b341e172201f4a6c84bb0ec080407977a/time_machine-3.2.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6db498686ecf6163c5aa8cf0bcd57bbe0f4081184f247edf3ee49a2612b584f9", size = 33206, upload-time = "2025-12-17T23:32:38.713Z" }, + { url = "https://files.pythonhosted.org/packages/d3/72/4deab446b579e8bd5dca91de98595c5d6bd6a17ce162abf5c5f2ce40d3d8/time_machine-3.2.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:027c1807efb74d0cd58ad16524dec94212fbe900115d70b0123399883657ac0f", size = 34792, upload-time = "2025-12-17T23:32:40.223Z" }, + { url = "https://files.pythonhosted.org/packages/2c/39/439c6b587ddee76d533fe972289d0646e0a5520e14dc83d0a30aeb5565f7/time_machine-3.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92432610c05676edd5e6946a073c6f0c926923123ce7caee1018dc10782c713d", size = 36187, upload-time = "2025-12-17T23:32:41.705Z" }, + { url = "https://files.pythonhosted.org/packages/4b/db/2da4368db15180989bab83746a857bde05ad16e78f326801c142bb747a06/time_machine-3.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c25586b62480eb77ef3d953fba273209478e1ef49654592cd6a52a68dfe56a67", size = 34855, upload-time = "2025-12-17T23:32:42.817Z" }, + { url = "https://files.pythonhosted.org/packages/88/84/120a431fee50bc4c241425bee4d3a4910df4923b7ab5f7dff1bf0c772f08/time_machine-3.2.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6bf3a2fa738d15e0b95d14469a0b8ea42635467408d8b490e263d5d45c9a177f", size = 33222, upload-time = "2025-12-17T23:32:43.94Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ea/89cfda82bb8c57ff91bb9a26751aa234d6d90e9b4d5ab0ad9dce0f9f0329/time_machine-3.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ce76b82276d7ad2a66cdc85dad4df19d1422b69183170a34e8fbc4c3f35502f7", size = 34270, upload-time = "2025-12-17T23:32:45.037Z" }, + { url = "https://files.pythonhosted.org/packages/8a/aa/235357da4f69a51a8d35fcbfcfa77cdc7dc24f62ae54025006570bda7e2d/time_machine-3.2.0-cp314-cp314-win32.whl", hash = "sha256:14d6778273c543441863dff712cd1d7803dee946b18de35921eb8df10714539d", size = 17544, upload-time = "2025-12-17T23:32:46.099Z" }, + { url = "https://files.pythonhosted.org/packages/7b/51/6c8405a7276be79693b792cff22ce41067ec05db26a7d02f2d5b06324434/time_machine-3.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:cbf821da96dbc80d349fa9e7c36e670b41d68a878d28c8850057992fed430eef", size = 18423, upload-time = "2025-12-17T23:32:47.468Z" }, + { url = "https://files.pythonhosted.org/packages/d9/03/a3cf419e20c35fc203c6e4fed48b5b667c1a2b4da456d9971e605f73ecef/time_machine-3.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:71c75d71f8e68abc8b669bca26ed2ddd558430a6c171e32b8620288565f18c0e", size = 17050, upload-time = "2025-12-17T23:32:48.91Z" }, + { url = "https://files.pythonhosted.org/packages/86/a1/142de946dc4393f910bf4564b5c3ba819906e1f49b06c9cb557519c849e4/time_machine-3.2.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4e374779021446fc2b5c29d80457ec9a3b1a5df043dc2aae07d7c1415d52323c", size = 19991, upload-time = "2025-12-17T23:32:49.933Z" }, + { url = "https://files.pythonhosted.org/packages/ee/62/7f17def6289901f94726921811a16b9adce46e666362c75d45730c60274f/time_machine-3.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:122310a6af9c36e9a636da32830e591e7923e8a07bdd0a43276c3a36c6821c90", size = 15707, upload-time = "2025-12-17T23:32:50.969Z" }, + { url = "https://files.pythonhosted.org/packages/5d/d3/3502fb9bd3acb159c18844b26c43220201a0d4a622c0c853785d07699a92/time_machine-3.2.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ba3eeb0f018cc362dd8128befa3426696a2e16dd223c3fb695fde184892d4d8c", size = 39207, upload-time = "2025-12-17T23:32:52.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/be/8b27f4aa296fda14a5a2ad7f588ddd450603c33415ab3f8e85b2f1a44678/time_machine-3.2.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:77d38ba664b381a7793f8786efc13b5004f0d5f672dae814430445b8202a67a6", size = 40764, upload-time = "2025-12-17T23:32:53.167Z" }, + { url = "https://files.pythonhosted.org/packages/42/cd/fe4c4e5c8ab6d48fab3624c32be9116fb120173a35fe67e482e5cf68b3d2/time_machine-3.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f09abeb8f03f044d72712207e0489a62098ad3ad16dac38927fcf80baca4d6a7", size = 43508, upload-time = "2025-12-17T23:32:54.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/28/5a3ba2fce85b97655a425d6bb20a441550acd2b304c96b2c19d3839f721a/time_machine-3.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6b28367ce4f73987a55e230e1d30a57a3af85da8eb1a140074eb6e8c7e6ef19f", size = 41712, upload-time = "2025-12-17T23:32:55.781Z" }, + { url = "https://files.pythonhosted.org/packages/81/58/e38084be7fdabb4835db68a3a47e58c34182d79fc35df1ecbe0db2c5359f/time_machine-3.2.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:903c7751c904581da9f7861c3015bed7cdc40047321291d3694a3cdc783bbca3", size = 38939, upload-time = "2025-12-17T23:32:56.867Z" }, + { url = "https://files.pythonhosted.org/packages/40/d0/ad3feb0a392ef4e0c08bc32024950373ddc0669002cbdcbb9f3bf0c2d114/time_machine-3.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:528217cad85ede5f85c8bc78b0341868d3c3cfefc6ecb5b622e1cacb6c73247b", size = 39837, upload-time = "2025-12-17T23:32:58.283Z" }, + { url = "https://files.pythonhosted.org/packages/5b/9e/5f4b2ea63b267bd78f3245e76f5528836611b5f2d30b5e7300a722fe4428/time_machine-3.2.0-cp314-cp314t-win32.whl", hash = "sha256:75724762ffd517e7e80aaec1fad1ff5a7414bd84e2b3ee7a0bacfeb67c14926e", size = 18091, upload-time = "2025-12-17T23:32:59.403Z" }, + { url = "https://files.pythonhosted.org/packages/39/6f/456b1f4d2700ae02b19eba830f870596a4b89b74bac3b6c80666f1b108c5/time_machine-3.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2526abbd053c5bca898d1b3e7898eec34626b12206718d8c7ce88fd12c1c9c5c", size = 19208, upload-time = "2025-12-17T23:33:00.488Z" }, + { url = "https://files.pythonhosted.org/packages/2f/22/8063101427ecd3d2652aada4d21d0876b07a3dc789125bca2ee858fec3ed/time_machine-3.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7f2fb6784b414edbe2c0b558bfaab0c251955ba27edd62946cce4a01675a992c", size = 17359, upload-time = "2025-12-17T23:33:01.54Z" }, +] + [[package]] name = "tokenizers" version = "0.22.1" @@ -2689,6 +2971,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/85/cd/584a2ceb5532af99dd09e50919e3615ba99aa127e9850eafe5f31ddfdb9a/uvicorn-0.37.0-py3-none-any.whl", hash = "sha256:913b2b88672343739927ce381ff9e2ad62541f9f8289664fa1d1d3803fa2ce6c", size = 67976, upload-time = "2025-09-23T13:33:45.842Z" }, ] +[[package]] +name = "virtualenv" +version = "21.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2f/c9/18d4b36606d6091844daa3bd93cf7dc78e6f5da21d9f21d06c221104b684/virtualenv-21.1.0.tar.gz", hash = "sha256:1990a0188c8f16b6b9cf65c9183049007375b26aad415514d377ccacf1e4fb44", size = 5840471, upload-time = "2026-02-27T08:49:29.702Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/55/896b06bf93a49bec0f4ae2a6f1ed12bd05c8860744ac3a70eda041064e4d/virtualenv-21.1.0-py3-none-any.whl", hash = "sha256:164f5e14c5587d170cf98e60378eb91ea35bf037be313811905d3a24ea33cc07", size = 5825072, upload-time = "2026-02-27T08:49:27.516Z" }, +] + [[package]] name = "watchfiles" version = "0.24.0"