Compare commits

..

3 Commits

Author SHA1 Message Date
github-actions[bot]
0e548fb116 🎨 Auto format 2026-02-26 21:33:34 +00:00
Savannah Ostrowski
f79d4757b7 update tip 2026-02-26 13:31:15 -08:00
Savannah Ostrowski
29c9f2a267 Add documentation for the FastAPI VS Code extension 2026-02-26 13:30:13 -08:00
24 changed files with 46 additions and 172 deletions

View File

@@ -45,7 +45,7 @@ jobs:
run: |
rm -rf ./site
mkdir ./site
- uses: actions/download-artifact@v8
- uses: actions/download-artifact@v7
with:
path: ./site/
pattern: docs-site-*

View File

@@ -28,7 +28,7 @@ jobs:
pyproject.toml
uv.lock
- run: uv sync --locked --no-dev --group github-actions
- uses: actions/download-artifact@v8
- uses: actions/download-artifact@v7
with:
name: coverage-html
path: htmlcov

View File

@@ -107,7 +107,7 @@ jobs:
run: uv pip install "git+https://github.com/Kludex/starlette@main"
- run: mkdir coverage
- name: Test
run: uv run --no-sync bash scripts/test-cov.sh
run: uv run --no-sync bash scripts/test.sh
env:
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
@@ -176,7 +176,7 @@ jobs:
- name: Install Dependencies
run: uv sync --locked --no-dev --group tests --extra all
- name: Get coverage files
uses: actions/download-artifact@v8
uses: actions/download-artifact@v7
with:
pattern: coverage-*
path: coverage

View File

@@ -0,0 +1,23 @@
# Editor Support { #editor-support }
The official [**FastAPI extension**](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) enhances your FastAPI development workflow with route discovery, navigation, as well as FastAPI Cloud deployment, and live log streaming.
For more details about the extension, refer to the README on the [GitHub repository](https://github.com/fastapi/fastapi-vscode).
## Setup and Installation { #setup-and-installation }
The FastAPI extension is available for both [VS Code](https://code.visualstudio.com/) and [Cursor](https://www.cursor.com/). It can be installed directly from the Extensions panel in each editor by searching for "FastAPI" and selecting the extension published by FastAPI Labs. The extension also works in browser-based editors such as [vscode.dev](https://vscode.dev) and [github.dev](https://github.dev).
### Application Discovery { #application-discovery }
By default, the extension will automatically discover FastAPI applications in your workspace by scanning for files that instantiate `FastAPI()`. If auto-detection doesn't work for your project structure, you can specify an entrypoint via `[tool.fastapi]` in `pyproject.toml` or the `fastapi.entryPoint` VS Code setting using module notation (e.g. `myapp.main:app`).
## Features { #features }
- **Path Operation Explorer** — A sidebar tree view of all routes in your application; click to jump to any route or router definition.
- **Route Search** — Search routes by path, method, or name with `Ctrl+Shift+E` (`Cmd+Shift+E` on Mac).
- **CodeLens Navigation** — Clickable links above test client calls (e.g. `client.get('/items')`) that jump to the matching route for quick navigation between tests and implementation.
- **Deploy to FastAPI Cloud** — One-click deployment of your app to FastAPI Cloud.
- **Stream Application Logs** — Real-time log streaming from your FastAPI Cloud-deployed application with level filtering and text search.
If you'd like to familiarize yourself with the extension's features, you can checkout the extension walkthrough by opening the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and selecting "Welcome: Open walkthrough..." and then choosing the "Get started with FastAPI" walkthrough.

View File

@@ -7,10 +7,6 @@ hide:
## Latest Changes
### Internal
* 🔨 Run tests with `pytest-xdist` and `pytest-cov`. PR [#14992](https://github.com/fastapi/fastapi/pull/14992) by [@YuriiMotov](https://github.com/YuriiMotov).
## 0.133.1
### Features

View File

@@ -84,6 +84,13 @@ If you want to install the standard dependencies but without the `fastapi-cloud-
///
/// tip
FastAPI has an <a href="https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode" class="external-link" target="_blank">official extension for VS Code</a>, which provides a lot of features, including a path operation explorer, path operation search, CodeLens navigation in tests, and FastAPI Cloud deployment and logs — all from your editor.
///
## Advanced User Guide { #advanced-user-guide }
There is also an **Advanced User Guide** that you can read later after this **Tutorial - User guide**.

View File

@@ -195,6 +195,7 @@ nav:
- advanced/json-base64-bytes.md
- advanced/strict-content-type.md
- fastapi-cli.md
- editor-support.md
- Deployment:
- deployment/index.md
- deployment/versions.md

View File

@@ -163,7 +163,7 @@ github-actions = [
tests = [
{ include-group = "docs-tests" },
"anyio[trio] >=3.2.1,<5.0.0",
"coverage[toml] >=7.13,<8.0",
"coverage[toml] >=6.5.0,<8.0",
"dirty-equals >=0.9.0",
"flask >=3.0.0,<4.0.0",
"inline-snapshot >=0.21.1",
@@ -178,10 +178,6 @@ tests = [
"types-orjson >=3.6.2",
"types-ujson >=5.10.0.20240515",
"a2wsgi >=1.9.0,<=2.0.0",
"pytest-xdist[psutil]>=2.5.0",
"pytest-cov>=4.0.0",
"pytest-sugar>=1.0.0",
"pytest-timeout>=2.4.0",
]
translations = [
"gitpython >=3.1.46",
@@ -233,7 +229,6 @@ strict_xfail = true
filterwarnings = [
"error",
]
timeout = "20"
[tool.coverage.run]
parallel = true
@@ -245,6 +240,7 @@ source = [
]
relative_files = true
context = '${CONTEXT}'
dynamic_context = "test_function"
omit = [
"tests/benchmarks/*",
"docs_src/response_model/tutorial003_04_py39.py",

View File

@@ -3,4 +3,5 @@
set -e
set -x
bash scripts/test-cov.sh --cov-report=term-missing --cov-report=html ${@}
bash scripts/test.sh ${@}
bash scripts/coverage.sh

View File

@@ -1,6 +0,0 @@
#!/usr/bin/env bash
set -e
set -x
bash scripts/test.sh --cov --cov-context=test ${@}

View File

@@ -4,4 +4,4 @@ set -e
set -x
export PYTHONPATH=./docs_src
pytest -n auto --dist loadgroup tests scripts/tests/ ${@}
coverage run -m pytest tests scripts/tests/ ${@}

View File

@@ -6,7 +6,7 @@ import pytest
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from tests.utils import needs_py310, workdir_lock
from tests.utils import needs_py310
@pytest.fixture(
@@ -29,7 +29,6 @@ def test_path_operation(client: TestClient):
assert response.json() == {"id": "foo", "value": "there goes my hero"}
@workdir_lock
def test_path_operation_img(client: TestClient):
shutil.copy("./docs/en/docs/img/favicon.png", "./image.png")
response = client.get("/items/foo?img=1")

View File

@@ -6,7 +6,7 @@ import pytest
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from tests.utils import needs_py310, workdir_lock
from tests.utils import needs_py310
@pytest.fixture(
@@ -29,7 +29,6 @@ def test_path_operation(client: TestClient):
assert response.json() == {"id": "foo", "value": "there goes my hero"}
@workdir_lock
def test_path_operation_img(client: TestClient):
shutil.copy("./docs/en/docs/img/favicon.png", "./image.png")
response = client.get("/items/foo?img=1")

View File

@@ -4,12 +4,10 @@ from pathlib import Path
from fastapi.testclient import TestClient
from docs_src.background_tasks.tutorial001_py310 import app
from tests.utils import workdir_lock
client = TestClient(app)
@workdir_lock
def test():
log = Path("log.txt")
if log.is_file():

View File

@@ -5,7 +5,7 @@ from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from tests.utils import needs_py310, workdir_lock
from ...utils import needs_py310
@pytest.fixture(
@@ -22,7 +22,6 @@ def get_client(request: pytest.FixtureRequest):
return client
@workdir_lock
def test(client: TestClient):
log = Path("log.txt")
if log.is_file():

View File

@@ -4,8 +4,6 @@ from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from tests.utils import workdir_lock
@pytest.fixture(scope="module")
def client():
@@ -19,7 +17,6 @@ def client():
static_dir.rmdir()
@workdir_lock
def test_swagger_ui_html(client: TestClient):
response = client.get("/docs")
assert response.status_code == 200, response.text
@@ -27,21 +24,18 @@ def test_swagger_ui_html(client: TestClient):
assert "https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" in response.text
@workdir_lock
def test_swagger_ui_oauth2_redirect_html(client: TestClient):
response = client.get("/docs/oauth2-redirect")
assert response.status_code == 200, response.text
assert "window.opener.swaggerUIRedirectOauth2" in response.text
@workdir_lock
def test_redoc_html(client: TestClient):
response = client.get("/redoc")
assert response.status_code == 200, response.text
assert "https://unpkg.com/redoc@2/bundles/redoc.standalone.js" in response.text
@workdir_lock
def test_api(client: TestClient):
response = client.get("/users/john")
assert response.status_code == 200, response.text

View File

@@ -4,8 +4,6 @@ from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from tests.utils import workdir_lock
@pytest.fixture(scope="module")
def client():
@@ -19,7 +17,6 @@ def client():
static_dir.rmdir()
@workdir_lock
def test_swagger_ui_html(client: TestClient):
response = client.get("/docs")
assert response.status_code == 200, response.text
@@ -27,21 +24,18 @@ def test_swagger_ui_html(client: TestClient):
assert "/static/swagger-ui.css" in response.text
@workdir_lock
def test_swagger_ui_oauth2_redirect_html(client: TestClient):
response = client.get("/docs/oauth2-redirect")
assert response.status_code == 200, response.text
assert "window.opener.swaggerUIRedirectOauth2" in response.text
@workdir_lock
def test_redoc_html(client: TestClient):
response = client.get("/redoc")
assert response.status_code == 200, response.text
assert "/static/redoc.standalone.js" in response.text
@workdir_lock
def test_api(client: TestClient):
response = client.get("/users/john")
assert response.status_code == 200, response.text

View File

@@ -3,8 +3,6 @@ from fastapi import FastAPI
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from tests.utils import workdir_lock
@pytest.fixture(name="app", scope="module")
def get_app():
@@ -13,7 +11,6 @@ def get_app():
yield app
@workdir_lock
def test_events(app: FastAPI):
with TestClient(app) as client:
response = client.get("/items/")
@@ -23,7 +20,6 @@ def test_events(app: FastAPI):
assert "Application shutdown" in log.read()
@workdir_lock
def test_openapi_schema(app: FastAPI):
with TestClient(app) as client:
response = client.get("/openapi.json")

View File

@@ -22,7 +22,7 @@ def get_mod_name(request: pytest.FixtureRequest):
@pytest.fixture(name="client")
def get_test_client(mod_name: str, monkeypatch: MonkeyPatch) -> TestClient:
if mod_name in sys.modules:
del sys.modules[mod_name] # pragma: no cover
del sys.modules[mod_name]
monkeypatch.setenv("ADMIN_EMAIL", "admin@example.com")
main_mod = importlib.import_module(mod_name)
return TestClient(main_mod.app)

View File

@@ -5,8 +5,6 @@ import pytest
from fastapi.testclient import TestClient
from inline_snapshot import snapshot
from tests.utils import workdir_lock
@pytest.fixture(scope="module")
def client():
@@ -22,20 +20,17 @@ def client():
static_dir.rmdir()
@workdir_lock
def test_static_files(client: TestClient):
response = client.get("/static/sample.txt")
assert response.status_code == 200, response.text
assert response.text == "This is a sample static file."
@workdir_lock
def test_static_files_not_found(client: TestClient):
response = client.get("/static/non_existent_file.txt")
assert response.status_code == 404, response.text
@workdir_lock
def test_openapi_schema(client: TestClient):
response = client.get("/openapi.json")
assert response.status_code == 200, response.text

View File

@@ -3,10 +3,7 @@ import shutil
from fastapi.testclient import TestClient
from tests.utils import workdir_lock
@workdir_lock
def test_main():
if os.path.isdir("./static"): # pragma: nocover
shutil.rmtree("./static")

View File

@@ -1,5 +1,4 @@
import importlib
import time
from types import ModuleType
import pytest
@@ -43,13 +42,11 @@ def test_websocket_handle_disconnection(client: TestClient):
connection.send_text("Hello from 1234")
data1 = connection.receive_text()
assert data1 == "You wrote: Hello from 1234"
time.sleep(0.01) # Give server time to process broadcast
data2 = connection_two.receive_text()
client1_says = "Client #1234 says: Hello from 1234"
assert data2 == client1_says
data1 = connection.receive_text()
assert data1 == client1_says
connection_two.close()
time.sleep(0.01) # Give server time to process broadcast
data1 = connection.receive_text()
assert data1 == "Client #5678 left the chat"

View File

@@ -9,8 +9,6 @@ needs_py314 = pytest.mark.skipif(
sys.version_info < (3, 14), reason="requires python3.14+"
)
workdir_lock = pytest.mark.xdist_group("workdir_lock")
def skip_module_if_py_gte_314():
"""Skip entire module on Python 3.14+ at import time."""

114
uv.lock generated
View File

@@ -1037,15 +1037,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
]
[[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"
@@ -1151,10 +1142,6 @@ dev = [
{ name = "pyjwt" },
{ name = "pytest" },
{ name = "pytest-codspeed" },
{ name = "pytest-cov" },
{ name = "pytest-sugar" },
{ name = "pytest-timeout" },
{ name = "pytest-xdist", extra = ["psutil"] },
{ name = "python-slugify" },
{ name = "pyyaml" },
{ name = "ruff" },
@@ -1214,10 +1201,6 @@ tests = [
{ name = "pyjwt" },
{ name = "pytest" },
{ name = "pytest-codspeed" },
{ name = "pytest-cov" },
{ name = "pytest-sugar" },
{ name = "pytest-timeout" },
{ name = "pytest-xdist", extra = ["psutil"] },
{ name = "pyyaml" },
{ name = "ruff" },
{ name = "sqlmodel" },
@@ -1274,7 +1257,7 @@ dev = [
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "black", specifier = ">=25.1.0" },
{ name = "cairosvg", specifier = ">=2.8.2" },
{ name = "coverage", extras = ["toml"], specifier = ">=7.13,<8.0" },
{ name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" },
{ name = "dirty-equals", specifier = ">=0.9.0" },
{ name = "flask", specifier = ">=3.0.0,<4.0.0" },
{ name = "gitpython", specifier = ">=3.1.46" },
@@ -1300,10 +1283,6 @@ dev = [
{ name = "pyjwt", specifier = ">=2.9.0" },
{ name = "pytest", specifier = ">=9.0.0" },
{ name = "pytest-codspeed", specifier = ">=4.2.0" },
{ name = "pytest-cov", specifier = ">=4.0.0" },
{ name = "pytest-sugar", specifier = ">=1.0.0" },
{ name = "pytest-timeout", specifier = ">=2.4.0" },
{ name = "pytest-xdist", extras = ["psutil"], specifier = ">=2.5.0" },
{ name = "python-slugify", specifier = ">=8.0.4" },
{ name = "pyyaml", specifier = ">=5.3.1,<7.0.0" },
{ name = "ruff", specifier = ">=0.14.14" },
@@ -1352,7 +1331,7 @@ github-actions = [
tests = [
{ name = "a2wsgi", specifier = ">=1.9.0,<=2.0.0" },
{ name = "anyio", extras = ["trio"], specifier = ">=3.2.1,<5.0.0" },
{ name = "coverage", extras = ["toml"], specifier = ">=7.13,<8.0" },
{ name = "coverage", extras = ["toml"], specifier = ">=6.5.0,<8.0" },
{ name = "dirty-equals", specifier = ">=0.9.0" },
{ name = "flask", specifier = ">=3.0.0,<4.0.0" },
{ name = "httpx", specifier = ">=0.23.0,<1.0.0" },
@@ -1363,10 +1342,6 @@ tests = [
{ name = "pyjwt", specifier = ">=2.9.0" },
{ name = "pytest", specifier = ">=9.0.0" },
{ name = "pytest-codspeed", specifier = ">=4.2.0" },
{ name = "pytest-cov", specifier = ">=4.0.0" },
{ name = "pytest-sugar", specifier = ">=1.0.0" },
{ name = "pytest-timeout", specifier = ">=2.4.0" },
{ name = "pytest-xdist", extras = ["psutil"], specifier = ">=2.5.0" },
{ name = "pyyaml", specifier = ">=5.3.1,<7.0.0" },
{ name = "ruff", specifier = ">=0.14.14" },
{ name = "sqlmodel", specifier = ">=0.0.31" },
@@ -3848,34 +3823,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" },
]
[[package]]
name = "psutil"
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/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" },
{ url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" },
{ url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" },
{ url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" },
{ url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" },
{ url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" },
{ 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" },
{ url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" },
{ url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" },
{ url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" },
{ url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" },
{ url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
]
[[package]]
name = "pwdlib"
version = "0.3.0"
@@ -4430,63 +4377,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/25/0e/8cb71fd3ed4ed08c07aec1245aea7bc1b661ba55fd9c392db76f1978d453/pytest_codspeed-4.2.0-py3-none-any.whl", hash = "sha256:e81bbb45c130874ef99aca97929d72682733527a49f84239ba575b5cb843bab0", size = 113726, upload-time = "2025-10-24T09:02:54.785Z" },
]
[[package]]
name = "pytest-cov"
version = "7.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coverage", extra = ["toml"] },
{ name = "pluggy" },
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" },
]
[[package]]
name = "pytest-sugar"
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
{ name = "termcolor" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/4e/60fed105549297ba1a700e1ea7b828044842ea27d72c898990510b79b0e2/pytest-sugar-1.1.1.tar.gz", hash = "sha256:73b8b65163ebf10f9f671efab9eed3d56f20d2ca68bda83fa64740a92c08f65d", size = 16533, upload-time = "2025-08-23T12:19:35.737Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/87/d5/81d38a91c1fdafb6711f053f5a9b92ff788013b19821257c2c38c1e132df/pytest_sugar-1.1.1-py3-none-any.whl", hash = "sha256:2f8319b907548d5b9d03a171515c1d43d2e38e32bd8182a1781eb20b43344cc8", size = 11440, upload-time = "2025-08-23T12:19:34.894Z" },
]
[[package]]
name = "pytest-timeout"
version = "2.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ac/82/4c9ecabab13363e72d880f2fb504c5f750433b2b6f16e99f4ec21ada284c/pytest_timeout-2.4.0.tar.gz", hash = "sha256:7e68e90b01f9eff71332b25001f85c75495fc4e3a836701876183c4bcfd0540a", size = 17973, upload-time = "2025-05-05T19:44:34.99Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl", hash = "sha256:c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2", size = 14382, upload-time = "2025-05-05T19:44:33.502Z" },
]
[[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.optional-dependencies]
psutil = [
{ name = "psutil" },
]
[[package]]
name = "python-dateutil"
version = "2.9.0.post0"