Mypy is now clean.

Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
2025-10-06 21:51:57 -04:00
parent 41555f1f57
commit 8e3e2bfb94
9 changed files with 427 additions and 412 deletions

View File

@@ -48,8 +48,16 @@ def safety(session: Session) -> None:
session: The Nox session object.
"""
requirements = session.poetry.export_requirements()
# Ensure Safety 4.x+ is installed for --ignore-path support
session.install("safety")
session.run("safety", "scan", "--full-report", f"--file={requirements}")
session.run(
"safety",
"scan",
"--full-report",
"--ignore-path",
".nox/",
f"--file={requirements}",
)
@session(python=python_versions)
@@ -62,6 +70,7 @@ def mypy(session: Session) -> None:
args = session.posargs or ["src", "tests", "docs/conf.py"]
session.install(".")
session.install("mypy", "pytest", "pytest-asyncio")
session.cd(str(Path(__file__).parent.resolve()))
session.run("mypy", *args)
if not session.posargs:
session.run("mypy", f"--python-executable={sys.executable}", "noxfile.py")

590
backend/poetry.lock generated
View File

@@ -160,24 +160,16 @@ typing-extensions = ">=4.13.0,<5.0.0"
[[package]]
name = "attrs"
version = "25.3.0"
version = "25.4.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.8"
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"},
{file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"},
{file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"},
{file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"},
]
[package.extras]
benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"]
tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""]
[[package]]
name = "babel"
version = "2.17.0"
@@ -284,14 +276,14 @@ virtualenv = ["virtualenv (>=20.11) ; python_version < \"3.10\"", "virtualenv (>
[[package]]
name = "certifi"
version = "2025.8.3"
version = "2025.10.5"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.7"
groups = ["main", "dev"]
files = [
{file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"},
{file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"},
{file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"},
{file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"},
]
[[package]]
@@ -606,57 +598,56 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
[[package]]
name = "cryptography"
version = "42.0.0"
version = "44.0.1"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = ">=3.7"
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
groups = ["dev"]
files = [
{file = "cryptography-42.0.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434"},
{file = "cryptography-42.0.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01"},
{file = "cryptography-42.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd"},
{file = "cryptography-42.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3"},
{file = "cryptography-42.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b"},
{file = "cryptography-42.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87"},
{file = "cryptography-42.0.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17"},
{file = "cryptography-42.0.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d"},
{file = "cryptography-42.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec"},
{file = "cryptography-42.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc"},
{file = "cryptography-42.0.0-cp37-abi3-win32.whl", hash = "sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4"},
{file = "cryptography-42.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0"},
{file = "cryptography-42.0.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf"},
{file = "cryptography-42.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689"},
{file = "cryptography-42.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0"},
{file = "cryptography-42.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139"},
{file = "cryptography-42.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2"},
{file = "cryptography-42.0.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513"},
{file = "cryptography-42.0.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8"},
{file = "cryptography-42.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81"},
{file = "cryptography-42.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221"},
{file = "cryptography-42.0.0-cp39-abi3-win32.whl", hash = "sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b"},
{file = "cryptography-42.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94"},
{file = "cryptography-42.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e"},
{file = "cryptography-42.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3"},
{file = "cryptography-42.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f"},
{file = "cryptography-42.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08"},
{file = "cryptography-42.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f"},
{file = "cryptography-42.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440"},
{file = "cryptography-42.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0"},
{file = "cryptography-42.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce"},
{file = "cryptography-42.0.0.tar.gz", hash = "sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4"},
{file = "cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd"},
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0"},
{file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf"},
{file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864"},
{file = "cryptography-44.0.1-cp37-abi3-win32.whl", hash = "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a"},
{file = "cryptography-44.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00"},
{file = "cryptography-44.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62"},
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41"},
{file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b"},
{file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7"},
{file = "cryptography-44.0.1-cp39-abi3-win32.whl", hash = "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9"},
{file = "cryptography-44.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f"},
{file = "cryptography-44.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183"},
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12"},
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83"},
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420"},
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4"},
{file = "cryptography-44.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7"},
{file = "cryptography-44.0.1.tar.gz", hash = "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14"},
]
[package.dependencies]
cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
[package.extras]
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"]
nox = ["nox"]
pep8test = ["check-sdist", "click", "mypy", "ruff"]
sdist = ["build"]
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""]
docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""]
pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
sdist = ["build (>=1.0.0)"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
test = ["certifi (>=2024)", "cryptography-vectors (==44.0.1)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
test-randomorder = ["pytest-randomly"]
[[package]]
@@ -671,6 +662,24 @@ files = [
{file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
]
[[package]]
name = "dependency-groups"
version = "1.3.1"
description = "A tool for resolving PEP 735 Dependency Group data"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030"},
{file = "dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd"},
]
[package.dependencies]
packaging = "*"
[package.extras]
cli = ["tomli ; python_version < \"3.11\""]
[[package]]
name = "distlib"
version = "0.4.0"
@@ -734,31 +743,31 @@ idna = ">=2.0.0"
[[package]]
name = "fastapi"
version = "0.111.0"
version = "0.118.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"},
{file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"},
{file = "fastapi-0.118.0-py3-none-any.whl", hash = "sha256:705137a61e2ef71019d2445b123aa8845bd97273c395b744d5a7dfe559056855"},
{file = "fastapi-0.118.0.tar.gz", hash = "sha256:5e81654d98c4d2f53790a7d32d25a7353b30c81441be7d0958a26b5d761fa1c8"},
]
[package.dependencies]
email_validator = ">=2.0.0"
fastapi-cli = ">=0.0.2"
httpx = ">=0.23.0"
jinja2 = ">=2.11.2"
orjson = ">=3.2.1"
email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"standard\""}
fastapi-cli = {version = ">=0.0.8", extras = ["standard"], optional = true, markers = "extra == \"standard\""}
httpx = {version = ">=0.23.0,<1.0.0", optional = true, markers = "extra == \"standard\""}
jinja2 = {version = ">=3.1.5", optional = true, markers = "extra == \"standard\""}
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
python-multipart = ">=0.0.7"
starlette = ">=0.37.2,<0.38.0"
python-multipart = {version = ">=0.0.18", optional = true, markers = "extra == \"standard\""}
starlette = ">=0.40.0,<0.49.0"
typing-extensions = ">=4.8.0"
ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0"
uvicorn = {version = ">=0.12.0", extras = ["standard"]}
uvicorn = {version = ">=0.12.0", extras = ["standard"], optional = true, markers = "extra == \"standard\""}
[package.extras]
all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
[[package]]
name = "fastapi-cli"
@@ -773,6 +782,7 @@ files = [
]
[package.dependencies]
fastapi-cloud-cli = {version = ">=0.1.1", optional = true, markers = "extra == \"standard\""}
rich-toolkit = ">=0.14.8"
typer = ">=0.15.1"
uvicorn = {version = ">=0.15.0", extras = ["standard"]}
@@ -781,6 +791,30 @@ uvicorn = {version = ">=0.15.0", extras = ["standard"]}
standard = ["fastapi-cloud-cli (>=0.1.1)", "uvicorn[standard] (>=0.15.0)"]
standard-no-fastapi-cloud-cli = ["uvicorn[standard] (>=0.15.0)"]
[[package]]
name = "fastapi-cloud-cli"
version = "0.3.0"
description = "Deploy and manage FastAPI Cloud apps from the command line 🚀"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "fastapi_cloud_cli-0.3.0-py3-none-any.whl", hash = "sha256:572677dbe38b6d4712d30097a8807b383d648ca09eb58e4a07cef4a517020832"},
{file = "fastapi_cloud_cli-0.3.0.tar.gz", hash = "sha256:17c7f8baa16b2f907696bf77d49df4a04e8715bbf5233024f273870f3ff1ca4d"},
]
[package.dependencies]
httpx = ">=0.27.0"
pydantic = {version = ">=1.6.1", extras = ["email"]}
rich-toolkit = ">=0.14.5"
rignore = ">=0.5.1"
sentry-sdk = ">=2.20.0"
typer = ">=0.12.3"
uvicorn = {version = ">=0.15.0", extras = ["standard"]}
[package.extras]
standard = ["uvicorn[standard] (>=0.15.0)"]
[[package]]
name = "filelock"
version = "3.19.1"
@@ -1069,14 +1103,14 @@ socks = ["socksio (==1.*)"]
[[package]]
name = "identify"
version = "2.6.14"
version = "2.6.15"
description = "File identification library for Python"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "identify-2.6.14-py2.py3-none-any.whl", hash = "sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e"},
{file = "identify-2.6.14.tar.gz", hash = "sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a"},
{file = "identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757"},
{file = "identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf"},
]
[package.extras]
@@ -1442,24 +1476,26 @@ files = [
[[package]]
name = "nox"
version = "2024.4.15"
version = "2025.5.1"
description = "Flexible test automation."
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "nox-2024.4.15-py3-none-any.whl", hash = "sha256:6492236efa15a460ecb98e7b67562a28b70da006ab0be164e8821177577c0565"},
{file = "nox-2024.4.15.tar.gz", hash = "sha256:ecf6700199cdfa9e5ea0a41ff5e6ef4641d09508eda6edb89d9987864115817f"},
{file = "nox-2025.5.1-py3-none-any.whl", hash = "sha256:56abd55cf37ff523c254fcec4d152ed51e5fe80e2ab8317221d8b828ac970a31"},
{file = "nox-2025.5.1.tar.gz", hash = "sha256:2a571dfa7a58acc726521ac3cd8184455ebcdcbf26401c7b737b5bc6701427b2"},
]
[package.dependencies]
argcomplete = ">=1.9.4,<4.0"
colorlog = ">=2.6.1,<7.0.0"
argcomplete = ">=1.9.4,<4"
attrs = ">=23.1"
colorlog = ">=2.6.1,<7"
dependency-groups = ">=1.1"
packaging = ">=20.9"
virtualenv = ">=20.14.1"
[package.extras]
tox-to-nox = ["jinja2", "tox"]
tox-to-nox = ["importlib-resources ; python_version < \"3.9\"", "jinja2", "tox (>=4)"]
uv = ["uv (>=0.1.6)"]
[[package]]
@@ -1480,99 +1516,6 @@ nox = ">=2020.8.22"
packaging = ">=20.9"
tomlkit = ">=0.7"
[[package]]
name = "orjson"
version = "3.11.3"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "orjson-3.11.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:29cb1f1b008d936803e2da3d7cba726fc47232c45df531b29edf0b232dd737e7"},
{file = "orjson-3.11.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97dceed87ed9139884a55db8722428e27bd8452817fbf1869c58b49fecab1120"},
{file = "orjson-3.11.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:58533f9e8266cb0ac298e259ed7b4d42ed3fa0b78ce76860626164de49e0d467"},
{file = "orjson-3.11.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c212cfdd90512fe722fa9bd620de4d46cda691415be86b2e02243242ae81873"},
{file = "orjson-3.11.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff835b5d3e67d9207343effb03760c00335f8b5285bfceefd4dc967b0e48f6a"},
{file = "orjson-3.11.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5aa4682912a450c2db89cbd92d356fef47e115dffba07992555542f344d301b"},
{file = "orjson-3.11.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d18dd34ea2e860553a579df02041845dee0af8985dff7f8661306f95504ddf"},
{file = "orjson-3.11.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d8b11701bc43be92ea42bd454910437b355dfb63696c06fe953ffb40b5f763b4"},
{file = "orjson-3.11.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:90368277087d4af32d38bd55f9da2ff466d25325bf6167c8f382d8ee40cb2bbc"},
{file = "orjson-3.11.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd7ff459fb393358d3a155d25b275c60b07a2c83dcd7ea962b1923f5a1134569"},
{file = "orjson-3.11.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f8d902867b699bcd09c176a280b1acdab57f924489033e53d0afe79817da37e6"},
{file = "orjson-3.11.3-cp310-cp310-win32.whl", hash = "sha256:bb93562146120bb51e6b154962d3dadc678ed0fce96513fa6bc06599bb6f6edc"},
{file = "orjson-3.11.3-cp310-cp310-win_amd64.whl", hash = "sha256:976c6f1975032cc327161c65d4194c549f2589d88b105a5e3499429a54479770"},
{file = "orjson-3.11.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d2ae0cc6aeb669633e0124531f342a17d8e97ea999e42f12a5ad4adaa304c5f"},
{file = "orjson-3.11.3-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ba21dbb2493e9c653eaffdc38819b004b7b1b246fb77bfc93dc016fe664eac91"},
{file = "orjson-3.11.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00f1a271e56d511d1569937c0447d7dce5a99a33ea0dec76673706360a051904"},
{file = "orjson-3.11.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b67e71e47caa6680d1b6f075a396d04fa6ca8ca09aafb428731da9b3ea32a5a6"},
{file = "orjson-3.11.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7d012ebddffcce8c85734a6d9e5f08180cd3857c5f5a3ac70185b43775d043d"},
{file = "orjson-3.11.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd759f75d6b8d1b62012b7f5ef9461d03c804f94d539a5515b454ba3a6588038"},
{file = "orjson-3.11.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6890ace0809627b0dff19cfad92d69d0fa3f089d3e359a2a532507bb6ba34efb"},
{file = "orjson-3.11.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d4a5e041ae435b815e568537755773d05dac031fee6a57b4ba70897a44d9d2"},
{file = "orjson-3.11.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d68bf97a771836687107abfca089743885fb664b90138d8761cce61d5625d55"},
{file = "orjson-3.11.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:bfc27516ec46f4520b18ef645864cee168d2a027dbf32c5537cb1f3e3c22dac1"},
{file = "orjson-3.11.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f66b001332a017d7945e177e282a40b6997056394e3ed7ddb41fb1813b83e824"},
{file = "orjson-3.11.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:212e67806525d2561efbfe9e799633b17eb668b8964abed6b5319b2f1cfbae1f"},
{file = "orjson-3.11.3-cp311-cp311-win32.whl", hash = "sha256:6e8e0c3b85575a32f2ffa59de455f85ce002b8bdc0662d6b9c2ed6d80ab5d204"},
{file = "orjson-3.11.3-cp311-cp311-win_amd64.whl", hash = "sha256:6be2f1b5d3dc99a5ce5ce162fc741c22ba9f3443d3dd586e6a1211b7bc87bc7b"},
{file = "orjson-3.11.3-cp311-cp311-win_arm64.whl", hash = "sha256:fafb1a99d740523d964b15c8db4eabbfc86ff29f84898262bf6e3e4c9e97e43e"},
{file = "orjson-3.11.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8c752089db84333e36d754c4baf19c0e1437012242048439c7e80eb0e6426e3b"},
{file = "orjson-3.11.3-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:9b8761b6cf04a856eb544acdd82fc594b978f12ac3602d6374a7edb9d86fd2c2"},
{file = "orjson-3.11.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b13974dc8ac6ba22feaa867fc19135a3e01a134b4f7c9c28162fed4d615008a"},
{file = "orjson-3.11.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f83abab5bacb76d9c821fd5c07728ff224ed0e52d7a71b7b3de822f3df04e15c"},
{file = "orjson-3.11.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6fbaf48a744b94091a56c62897b27c31ee2da93d826aa5b207131a1e13d4064"},
{file = "orjson-3.11.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc779b4f4bba2847d0d2940081a7b6f7b5877e05408ffbb74fa1faf4a136c424"},
{file = "orjson-3.11.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd4b909ce4c50faa2192da6bb684d9848d4510b736b0611b6ab4020ea6fd2d23"},
{file = "orjson-3.11.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:524b765ad888dc5518bbce12c77c2e83dee1ed6b0992c1790cc5fb49bb4b6667"},
{file = "orjson-3.11.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:84fd82870b97ae3cdcea9d8746e592b6d40e1e4d4527835fc520c588d2ded04f"},
{file = "orjson-3.11.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fbecb9709111be913ae6879b07bafd4b0785b44c1eb5cac8ac76da048b3885a1"},
{file = "orjson-3.11.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9dba358d55aee552bd868de348f4736ca5a4086d9a62e2bfbbeeb5629fe8b0cc"},
{file = "orjson-3.11.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eabcf2e84f1d7105f84580e03012270c7e97ecb1fb1618bda395061b2a84a049"},
{file = "orjson-3.11.3-cp312-cp312-win32.whl", hash = "sha256:3782d2c60b8116772aea8d9b7905221437fdf53e7277282e8d8b07c220f96cca"},
{file = "orjson-3.11.3-cp312-cp312-win_amd64.whl", hash = "sha256:79b44319268af2eaa3e315b92298de9a0067ade6e6003ddaef72f8e0bedb94f1"},
{file = "orjson-3.11.3-cp312-cp312-win_arm64.whl", hash = "sha256:0e92a4e83341ef79d835ca21b8bd13e27c859e4e9e4d7b63defc6e58462a3710"},
{file = "orjson-3.11.3-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:af40c6612fd2a4b00de648aa26d18186cd1322330bd3a3cc52f87c699e995810"},
{file = "orjson-3.11.3-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:9f1587f26c235894c09e8b5b7636a38091a9e6e7fe4531937534749c04face43"},
{file = "orjson-3.11.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61dcdad16da5bb486d7227a37a2e789c429397793a6955227cedbd7252eb5a27"},
{file = "orjson-3.11.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11c6d71478e2cbea0a709e8a06365fa63da81da6498a53e4c4f065881d21ae8f"},
{file = "orjson-3.11.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff94112e0098470b665cb0ed06efb187154b63649403b8d5e9aedeb482b4548c"},
{file = "orjson-3.11.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b756575aaa2a855a75192f356bbda11a89169830e1439cfb1a3e1a6dde7be"},
{file = "orjson-3.11.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9416cc19a349c167ef76135b2fe40d03cea93680428efee8771f3e9fb66079d"},
{file = "orjson-3.11.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b822caf5b9752bc6f246eb08124c3d12bf2175b66ab74bac2ef3bbf9221ce1b2"},
{file = "orjson-3.11.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:414f71e3bdd5573893bf5ecdf35c32b213ed20aa15536fe2f588f946c318824f"},
{file = "orjson-3.11.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:828e3149ad8815dc14468f36ab2a4b819237c155ee1370341b91ea4c8672d2ee"},
{file = "orjson-3.11.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac9e05f25627ffc714c21f8dfe3a579445a5c392a9c8ae7ba1d0e9fb5333f56e"},
{file = "orjson-3.11.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e44fbe4000bd321d9f3b648ae46e0196d21577cf66ae684a96ff90b1f7c93633"},
{file = "orjson-3.11.3-cp313-cp313-win32.whl", hash = "sha256:2039b7847ba3eec1f5886e75e6763a16e18c68a63efc4b029ddf994821e2e66b"},
{file = "orjson-3.11.3-cp313-cp313-win_amd64.whl", hash = "sha256:29be5ac4164aa8bdcba5fa0700a3c9c316b411d8ed9d39ef8a882541bd452fae"},
{file = "orjson-3.11.3-cp313-cp313-win_arm64.whl", hash = "sha256:18bd1435cb1f2857ceb59cfb7de6f92593ef7b831ccd1b9bfb28ca530e539dce"},
{file = "orjson-3.11.3-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cf4b81227ec86935568c7edd78352a92e97af8da7bd70bdfdaa0d2e0011a1ab4"},
{file = "orjson-3.11.3-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:bc8bc85b81b6ac9fc4dae393a8c159b817f4c2c9dee5d12b773bddb3b95fc07e"},
{file = "orjson-3.11.3-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:88dcfc514cfd1b0de038443c7b3e6a9797ffb1b3674ef1fd14f701a13397f82d"},
{file = "orjson-3.11.3-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d61cd543d69715d5fc0a690c7c6f8dcc307bc23abef9738957981885f5f38229"},
{file = "orjson-3.11.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2b7b153ed90ababadbef5c3eb39549f9476890d339cf47af563aea7e07db2451"},
{file = "orjson-3.11.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:7909ae2460f5f494fecbcd10613beafe40381fd0316e35d6acb5f3a05bfda167"},
{file = "orjson-3.11.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2030c01cbf77bc67bee7eef1e7e31ecf28649353987775e3583062c752da0077"},
{file = "orjson-3.11.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a0169ebd1cbd94b26c7a7ad282cf5c2744fce054133f959e02eb5265deae1872"},
{file = "orjson-3.11.3-cp314-cp314-win32.whl", hash = "sha256:0c6d7328c200c349e3a4c6d8c83e0a5ad029bdc2d417f234152bf34842d0fc8d"},
{file = "orjson-3.11.3-cp314-cp314-win_amd64.whl", hash = "sha256:317bbe2c069bbc757b1a2e4105b64aacd3bc78279b66a6b9e51e846e4809f804"},
{file = "orjson-3.11.3-cp314-cp314-win_arm64.whl", hash = "sha256:e8f6a7a27d7b7bec81bd5924163e9af03d49bbb63013f107b48eb5d16db711bc"},
{file = "orjson-3.11.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:56afaf1e9b02302ba636151cfc49929c1bb66b98794291afd0e5f20fecaf757c"},
{file = "orjson-3.11.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:913f629adef31d2d350d41c051ce7e33cf0fd06a5d1cb28d49b1899b23b903aa"},
{file = "orjson-3.11.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e0a23b41f8f98b4e61150a03f83e4f0d566880fe53519d445a962929a4d21045"},
{file = "orjson-3.11.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d721fee37380a44f9d9ce6c701b3960239f4fb3d5ceea7f31cbd43882edaa2f"},
{file = "orjson-3.11.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73b92a5b69f31b1a58c0c7e31080aeaec49c6e01b9522e71ff38d08f15aa56de"},
{file = "orjson-3.11.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2489b241c19582b3f1430cc5d732caefc1aaf378d97e7fb95b9e56bed11725f"},
{file = "orjson-3.11.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5189a5dab8b0312eadaf9d58d3049b6a52c454256493a557405e77a3d67ab7f"},
{file = "orjson-3.11.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9d8787bdfbb65a85ea76d0e96a3b1bed7bf0fbcb16d40408dc1172ad784a49d2"},
{file = "orjson-3.11.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:8e531abd745f51f8035e207e75e049553a86823d189a51809c078412cefb399a"},
{file = "orjson-3.11.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8ab962931015f170b97a3dd7bd933399c1bae8ed8ad0fb2a7151a5654b6941c7"},
{file = "orjson-3.11.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:124d5ba71fee9c9902c4a7baa9425e663f7f0aecf73d31d54fe3dd357d62c1a7"},
{file = "orjson-3.11.3-cp39-cp39-win32.whl", hash = "sha256:22724d80ee5a815a44fc76274bb7ba2e7464f5564aacb6ecddaa9970a83e3225"},
{file = "orjson-3.11.3-cp39-cp39-win_amd64.whl", hash = "sha256:215c595c792a87d4407cb72dd5e0f6ee8e694ceeb7f9102b533c5a9bf2a916bb"},
{file = "orjson-3.11.3.tar.gz", hash = "sha256:1c0603b1d2ffcd43a411d64797a19556ef76958aef1c182f22dc30860152a98a"},
]
[[package]]
name = "packaging"
version = "25.0"
@@ -1718,6 +1661,7 @@ files = [
[package.dependencies]
annotated-types = ">=0.6.0"
email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""}
pydantic-core = "2.33.2"
typing-extensions = ">=4.12.2"
typing-inspection = ">=0.4.0"
@@ -2126,6 +2070,141 @@ click = ">=8.1.7"
rich = ">=13.7.1"
typing-extensions = ">=4.12.2"
[[package]]
name = "rignore"
version = "0.7.0"
description = "Python Bindings for the ignore crate"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "rignore-0.7.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f9a456e1620aefb016fe0af51b09acd06736fddc8ce3417adfdd9191031b4c48"},
{file = "rignore-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4a96b9b30e3567ecec1fd37535f3c83093d0552af0891765a314650f35a22ad"},
{file = "rignore-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e011b6412690e34113d5cb133844bfe087fe9a57b37c63cb68671dfbf6080ed"},
{file = "rignore-0.7.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c177b8267aa361bf04f9e28fa948881ff01e98e2556bf9d39b088e42de23b190"},
{file = "rignore-0.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cfe5873ac415f62d221d8bd04d88f9a70e73fe7aea0c094b9974e530628d8ea"},
{file = "rignore-0.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20d62988d4f565ab101ec33c501527fde52693eced4ea34d5da61b88db602616"},
{file = "rignore-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:427ba9cfc424aedb0b569d659d2f2ea88ed308d8eb245446db10733a73db0fb1"},
{file = "rignore-0.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:86280aae7d0980debe5ed6785e3fc9a68ca627ac84e7c84048d7d3fe6d80ef7a"},
{file = "rignore-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:389c5fe844ad1fd5fba46c0cba0d9e68bfdcaae12e943b135395730efe45bcfe"},
{file = "rignore-0.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:34a34d5e86fda5355b55d927f43ff515c7371e8880b8f16cb92c3278c21327ee"},
{file = "rignore-0.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f7aacce87c710a3f254eb8b28a0cec1801362e7cf4f8258cceb8f36fc9cc695a"},
{file = "rignore-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3b88dfeb0d08902fe28eb5d75cbfac1d130ccdaeaca742eab1628bab7960294"},
{file = "rignore-0.7.0-cp310-cp310-win32.whl", hash = "sha256:bf43125e8b34828ba91fe37a5cfadd677ff46152d539cdab19bb1390f85d21a5"},
{file = "rignore-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:39a6cf0d81ffbbbd1c353b6a9a5634722714a6caafdcdc056f361e62049aa93b"},
{file = "rignore-0.7.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a83923fd4adff85737c54aecbdb8b7c8f1bba913af019ffebcf6d65d3903cefd"},
{file = "rignore-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f029f6b8f66310659d4e8616a0adaf0de79b7b076b1e37261d532b24e000eff2"},
{file = "rignore-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:686c162f945ede315b7b63958d83531b18226cad4fae9170a5787dd8b8b4be89"},
{file = "rignore-0.7.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a3c8b62a00c1b6e0ed73412ba8d37d05e214e6a8757f2779d313078d2bdec209"},
{file = "rignore-0.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f115666738614cdb0ef122c2b48806043b9b6c603dc03a4708b2eb1df5a44514"},
{file = "rignore-0.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ffaf2047304b97bc648592f82c0aeba3468f43546a918994411b8f1d79d42d6"},
{file = "rignore-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04678c2f1787eb07378754d6aa50e66ce712e0b75e8b843fd9e5e4da35130617"},
{file = "rignore-0.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:53a4c4a43558f34b32732efcee9c79c7948ff26673bb764aa0e9bbe951e435fa"},
{file = "rignore-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:794f72ce7195cad1fb41c03b3e3484396c404498b73855004ebea965a697edd9"},
{file = "rignore-0.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:989f35a152bc508c52d63d7d4527215c5dabe7981e5744bcf35f96c99f3758f7"},
{file = "rignore-0.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b945b29a995fdcf669dc098ec40237131742de2cf49484011ba3f81d0fff23a3"},
{file = "rignore-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e4deda4c3e5cec1ebfb714094cd9af79e8840680187537d13a216377d6aa2ed6"},
{file = "rignore-0.7.0-cp311-cp311-win32.whl", hash = "sha256:d0fa18c39a4f25275abeb05a7889d11b4dfed9966d5eb1d41fd13da1394863b0"},
{file = "rignore-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac18b6fe469a3c57a92c5fc82f94f260922177b003189104eb758316b7b54d6e"},
{file = "rignore-0.7.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:df6d38f3c3903bfeec94e8a927a3656e0b95c27d3b5c29e63797dd359978aff8"},
{file = "rignore-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:da1b9ccc2cf6df196fe3187287e7ed858e967ae56974901414031f5524ea33b8"},
{file = "rignore-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0525ccf3e8b9ccd6f1dfc87ecc78218a83605070b247633636d144acdf6b73be"},
{file = "rignore-0.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:570bcf51fd9f78ec79ec33f2f852e6665027fae80cc3e5e2523c97d3f4220369"},
{file = "rignore-0.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32f5d3d90a520d61e43c2a23724852c689c3ed36b38264c77b613f967e2d1f68"},
{file = "rignore-0.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d189cfb9059dfa497e5480c411bd2aba838124b50b93abf7e92556221b7956"},
{file = "rignore-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c871a31596476ac4343f6b803ee8ddca068425e1837cf6849ebe46c498c73c5"},
{file = "rignore-0.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b7d8ce1efbd8fa865712d34753ce4eb8e0732874df95351244e14308fb87d0a"},
{file = "rignore-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d261aea1a51ef93c262b52ad195a1092a8bae17577e8192473d1b5fd30379346"},
{file = "rignore-0.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:034bef935e3734b4ad2dada59c96717f3e3d0b48551a0c79379c4d3280b4a397"},
{file = "rignore-0.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5f816b65c9bf97093d792c9b50369d5a81a5f95b4ed5f003d4091bd1db3b70d8"},
{file = "rignore-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b88479f0a89828781d25a9acd485be88abf4f1f1c14e455b6530da265adb593c"},
{file = "rignore-0.7.0-cp312-cp312-win32.whl", hash = "sha256:89324cffc3312ad50e43f07f51966d421dc44d7c0d219747259270ee5fbc59e3"},
{file = "rignore-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:bbbbc7582d3926a250a14acf7c6b1d60b6d610275ac026856555fd12492e716e"},
{file = "rignore-0.7.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:190e469db68112c4027a7a126facfd80ce353374ff208c585ca7dacc75de0472"},
{file = "rignore-0.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0a43f6fabf46ed8e96fbf2861187362e513960c2a8200c35242981bd36ef8b96"},
{file = "rignore-0.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b89a59e5291805eca3c3317a55fcd2a579e9ee1184511660078a398182463deb"},
{file = "rignore-0.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a155f36be847c05c800e0218e9ac04946ba44bf077e1f11dc024ca9e1f7a727"},
{file = "rignore-0.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dba075135ac3cda5f3236b4f03f82bbcd97454a908631ad3da93aae1e7390b17"},
{file = "rignore-0.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8525b8c31f36dc9fbcb474ef58d654f6404b19b6110b7f5df332e58e657a4aa8"},
{file = "rignore-0.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0428b64d8b02ad83fc0a2505ded0e9064cac97df7aa1dffc9c7558b56429912"},
{file = "rignore-0.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab1db960a64835ec3ed541951821bfc38f30dfbd6ebd990f7d039d0c54ff957"},
{file = "rignore-0.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3749711b1e50fb5b28b55784e159a3b8209ecc72d01cc1511c05bc3a23b4a063"},
{file = "rignore-0.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:57240739c786f897f89e29c05e529291ee1b477df9f6b29b774403a23a169fe2"},
{file = "rignore-0.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6b70581286acd5f96ce11efd209bfe9261108586e1a948cc558fc3f58ba5bf5f"},
{file = "rignore-0.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33fb6e4cba1b798f1328e889b4bf2341894d82e3be42bb3513b4e0fe38788538"},
{file = "rignore-0.7.0-cp313-cp313-win32.whl", hash = "sha256:119f0497fb4776cddc663ee8f35085ce00758bd423221ba1e8222a816e10cf5e"},
{file = "rignore-0.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:fb06e11dda689be138909f53639f0baa8d7c6be4d76ca9ec316382ccf3517469"},
{file = "rignore-0.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f2255821ab4bc34fa129a94535f5d0d88b164940b25d0a3b26ebd41d99f1a9f"},
{file = "rignore-0.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b57efcbbc1510f8ce831a5e19fb1fe9dd329bb246c4e4f8a09bf1c06687b0331"},
{file = "rignore-0.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ead4bc2baceeccdfeb82cb70ba8f70fdb6dc1e58976f805f9d0d19b9ee915f0"},
{file = "rignore-0.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f0a8996437a22df0faf2844d65ec91d41176b9d4e7357abee42baa39dc996ae"},
{file = "rignore-0.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:cb17ef4a413444fccbd57e1b4a3870f1320951b81f1b7007af9c70e1a5bc2897"},
{file = "rignore-0.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:b12b316adf6cf64f9d22bd690b2aa019a37335a1f632a0da7fb15a423cb64080"},
{file = "rignore-0.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:dba8181d999387c17dd6cce5fd7f0009376ca8623d2d86842d034b18d83dc768"},
{file = "rignore-0.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:04a3d4513cdd184f4f849ae8d6407a169cca543a2c4dd69bfc42e67cb0155504"},
{file = "rignore-0.7.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:a296bc26b713aacd0f31702e7d89426ba6240abdbf01b2b18daeeaeaa782f475"},
{file = "rignore-0.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7f71807ed0bc1542860a8fa1615a0d93f3d5a22dde1066e9f50d7270bc60686"},
{file = "rignore-0.7.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7e6ff54399ddb650f4e4dc74b325766e7607967a49b868326e9687fc3642620"},
{file = "rignore-0.7.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:09dfad3ca450b3967533c6b1a2c7c0228c63c518f619ff342df5f9c3ed978b66"},
{file = "rignore-0.7.0-cp314-cp314-win32.whl", hash = "sha256:2850718cfb1caece6b7ac19a524c7905a8d0c6627b0d0f4e81798e20b6c75078"},
{file = "rignore-0.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2401637dc8ab074f5e642295f8225d2572db395ae504ffc272a8d21e9fe77b2c"},
{file = "rignore-0.7.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:8f6a65e240750b97ed8b85ab5330b9b90c1ef98323c2252956a3f2c1ea5a1609"},
{file = "rignore-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cc8fe20862b3be12095ddc5b35feaad86c79bfc99156eb97f03c8c077c7baaa"},
{file = "rignore-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d9c9cc3e07f832c9d4aecb98ffe079659f4cef9ff73faa5bef49f96ca4f4c7f"},
{file = "rignore-0.7.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ca0a4e5f31d321034bda7f78cb890f1e9c82cd3dbce61667de8a20b655c33dcc"},
{file = "rignore-0.7.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa5851ab746e864b5ceba201aef3902f23a4f77977ffc3dfb0d4b1174a7d010b"},
{file = "rignore-0.7.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e41d498fda0b51734bcf635aa5c932983b5caf65e140c110a8f2dfc1b0238d41"},
{file = "rignore-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9bcbea607f60b3c7ece991fee5426a6a313f099059dd57d53603c72957dc423f"},
{file = "rignore-0.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0e67a9c6a3b7686b5985a290ff6ef7d2fabc86b696c91f513477de50b8a4e1f5"},
{file = "rignore-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8a8470c0938a511d706b17f425ecaa1b16de8b47b91f42b4bb019674f32afa65"},
{file = "rignore-0.7.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:e7c7190c1657c7956345ae9883cf63d997b7f69fd79a08dce9f8611181e679cc"},
{file = "rignore-0.7.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3a772ff7b97f4aaf253dd4511df508557eada3f9e17e595b8eb932e6759340bf"},
{file = "rignore-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9fcdba48e2d8ba4b77e434981d13f0f148cfedc78fca4811fb22d171904b3417"},
{file = "rignore-0.7.0-cp38-cp38-win32.whl", hash = "sha256:61177875c949e94c516e197271b1aa68228464eade35a5c0605b32aa918eeec2"},
{file = "rignore-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:c5f4cdc650bb19b6f6c0d2cfd6e8e4e6be27a5fb7513248f21f9c1c98f14d7d5"},
{file = "rignore-0.7.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5fd2d3ced1e54afb33f30884d03af0526540a1642b16f0a67b46a9ba3ded89bb"},
{file = "rignore-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7972651bbdfce4125525f54a7d9761bd26ec88201f669900a9c16c944db88113"},
{file = "rignore-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e39eccbb92f1b562b72aefeec93bfae38c8f302a58aaf9b2d77362b57e1cf27"},
{file = "rignore-0.7.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc34644c1d42ea0ec7b7b14a56203dbf19df6c258d75937191f871da3cd1c1ca"},
{file = "rignore-0.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cd512a48d9b0900b297fc0c2227e81096eed21e42dae5a9e82e332500fb8730"},
{file = "rignore-0.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:baee13481bf5d335aa48cb3607637f842edaf418f5dde252fe9d99f360533549"},
{file = "rignore-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7ae8d7ec27ce07599aef2e83e7cff831888e381db0f0ee066d9fb4873ba14ab"},
{file = "rignore-0.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7a68d1a180d5af3e1ca2e3e1f2b318e6925677d06f5f4d6b3cbd2f63eaad9255"},
{file = "rignore-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0714ee0759fe57068ea8dc234672f939b5d07dbc89d4e0b59468fdb88dbca830"},
{file = "rignore-0.7.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:44cda8590511c9a9aa32e253267f1742b41260f3b71d9bcabdb07911cca41a9a"},
{file = "rignore-0.7.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2f680188a2cfae1e64a863223e6a702c212d28b77fa3b9cc0547a4957b5845b0"},
{file = "rignore-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:236003f4d348e4e2992aa7936d38aeffbaf17e43e3b068623096ee4b8f7efa2b"},
{file = "rignore-0.7.0-cp39-cp39-win32.whl", hash = "sha256:0bd08c60e14d6c24078f4b5b8dc12616a4d620e15a0545399e348d3cb137304b"},
{file = "rignore-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:c7b033fa7cba2df9a7647ee6001709ff5ddea51e8fefcb4ca4d24ed6d575822f"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11831ac0c3bc656667848abd0cb869d288b13ad69a976cac307b447a4f79c9d3"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1f18bdc1bfd73da6a43bcf2c08f94e1ecddabf234e47e0f95daf6107cf937fb3"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6268a12ecb6d25caf0adb166732940bd9113e7dddd46018e457f1fb9408a707"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c1402445b24c8904b6cef124f2798d55a2ba84b41397d7fdab6fe316b1f20e6"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8aa1c3215cc9587e55b3326357637e17a2ed713ddb2c59339f908aae98ae01d6"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:78c8f56aaae18406699026e26f9c3b4721adc95f08ac4e76972aed0efb5eb91d"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:89ab6d73ffd48be27032def1decef83faebee891519e7f2006df5657b8ba2f4a"},
{file = "rignore-0.7.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:cf4eebeebeabd27467b51d5dbc92adc7177fcfd73a29c86f649853ba476d98fa"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f40142a34a7f08cd90fb4e74e43deffe3381fa3b164fb59857fa4e3996d4716d"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccbc0b6285bb981316e5646ac96be7bca9665ee2444427d8d170fda5eda6f022"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77cdf15a8b0ab80cd1d05a754b3237330e60e8731c255b7eb2a5d240a68df9f8"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14e7e5ac99d60dd1993032205de7e79c36687825c45a7caa704620a0e9fde03f"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98fae67456f053942ccda2cb2677a55fd34397e6674eaa403ab7c1c4930dcb12"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b55d2dcee6808f677ef25219ec0bb4852fbf2edb0b5010a5f18fe5feee276d6"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:7ff87634a648f17a9992ac4ce2fb48397696e3ab4a80154a895b9d1f6fc606cf"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:c5721daa569fae74f5bf060165f96c6fec0a963ed008213e778259945406ec53"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:5770e783e08403b02c052b8b74a3e9431142aca93c78ccd1cc389b4dc60c2846"},
{file = "rignore-0.7.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:504f66805fcc2a684cd1cda460d9f15b8b08997f06d9281efa221007072c53f5"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:280fa78100c94640f36fe40304b5fdda1f14487f306f20b884f4dc230ad86e7b"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f9ba817b3ef8560c34d18764f32b7165027a8b82503a1f57ccfdc821e689d30"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2150dbfb0227762a0af2decd7cc67a1c8b5cb4d35f8b83c674143fefc9b76f3"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e9af74b3b90266d7700b44a08217af636421b6e823f9280f9521a06e4fc18b9"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:165890c27b1fd8ec71d47a05e6a11c6cf42693f3b479f3fc8d0047b5c2a46191"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:3830a252b7e82ba61595489a819af721f645dd42548d5801000583044745a41c"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:d5a50ab60948bd7339ab50329991acfe7afb5fec4a444f0e19939ee6e18d364a"},
{file = "rignore-0.7.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:648c052ba530ff43ecb516dd33831563ecac9878cd54897171237198870c48d4"},
{file = "rignore-0.7.0.tar.gz", hash = "sha256:cfe6a2cbec855b440d7550d53e670246fce43ca5847e46557b6d4577c9cdb540"},
]
[[package]]
name = "ruamel-yaml"
version = "0.18.15"
@@ -2211,6 +2290,65 @@ files = [
{file = "ruamel.yaml.clib-0.2.14.tar.gz", hash = "sha256:803f5044b13602d58ea378576dd75aa759f52116a0232608e8fdada4da33752e"},
]
[[package]]
name = "sentry-sdk"
version = "2.40.0"
description = "Python client for Sentry (https://sentry.io)"
optional = false
python-versions = ">=3.6"
groups = ["main"]
files = [
{file = "sentry_sdk-2.40.0-py2.py3-none-any.whl", hash = "sha256:d5f6ae0f27ea73e7b09c70ad7d42242326eb44765e87a15d8c5aab96b80013e6"},
{file = "sentry_sdk-2.40.0.tar.gz", hash = "sha256:b9c4672fb2cafabcc28586ab8fd0ceeff9b2352afcf2b936e13d5ba06d141b9f"},
]
[package.dependencies]
certifi = "*"
urllib3 = ">=1.26.11"
[package.extras]
aiohttp = ["aiohttp (>=3.5)"]
anthropic = ["anthropic (>=0.16)"]
arq = ["arq (>=0.23)"]
asyncpg = ["asyncpg (>=0.23)"]
beam = ["apache-beam (>=2.12)"]
bottle = ["bottle (>=0.12.13)"]
celery = ["celery (>=3)"]
celery-redbeat = ["celery-redbeat (>=2)"]
chalice = ["chalice (>=1.16.0)"]
clickhouse-driver = ["clickhouse-driver (>=0.2.0)"]
django = ["django (>=1.8)"]
falcon = ["falcon (>=1.4)"]
fastapi = ["fastapi (>=0.79.0)"]
flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"]
grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"]
http2 = ["httpcore[http2] (==1.*)"]
httpx = ["httpx (>=0.16.0)"]
huey = ["huey (>=2)"]
huggingface-hub = ["huggingface_hub (>=0.22)"]
langchain = ["langchain (>=0.0.210)"]
langgraph = ["langgraph (>=0.6.6)"]
launchdarkly = ["launchdarkly-server-sdk (>=9.8.0)"]
litellm = ["litellm (>=1.77.5)"]
litestar = ["litestar (>=2.0.0)"]
loguru = ["loguru (>=0.5)"]
openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"]
openfeature = ["openfeature-sdk (>=0.7.1)"]
opentelemetry = ["opentelemetry-distro (>=0.35b0)"]
opentelemetry-experimental = ["opentelemetry-distro"]
pure-eval = ["asttokens", "executing", "pure_eval"]
pymongo = ["pymongo (>=3.1)"]
pyspark = ["pyspark (>=2.4.4)"]
quart = ["blinker (>=1.1)", "quart (>=0.16.1)"]
rq = ["rq (>=0.6)"]
sanic = ["sanic (>=0.8)"]
sqlalchemy = ["sqlalchemy (>=1.2)"]
starlette = ["starlette (>=0.19.1)"]
starlite = ["starlite (>=1.48)"]
statsig = ["statsig (>=0.55.3)"]
tornado = ["tornado (>=6)"]
unleash = ["UnleashClient (>=6.0.1)"]
[[package]]
name = "shellingham"
version = "1.5.4"
@@ -2562,21 +2700,21 @@ sqlcipher = ["sqlcipher3_binary"]
[[package]]
name = "starlette"
version = "0.37.2"
version = "0.48.0"
description = "The little ASGI library that shines."
optional = false
python-versions = ">=3.8"
python-versions = ">=3.9"
groups = ["main", "dev"]
files = [
{file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"},
{file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"},
{file = "starlette-0.48.0-py3-none-any.whl", hash = "sha256:0764ca97b097582558ecb498132ed0c7d942f233f365b86ba37770e026510659"},
{file = "starlette-0.48.0.tar.gz", hash = "sha256:7e8cee469a8ab2352911528110ce9088fdc6a37d9876926e73da7ce4aa4c7a46"},
]
[package.dependencies]
anyio = ">=3.4.0,<5"
anyio = ">=3.6.2,<5"
[package.extras]
full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"]
full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
[[package]]
name = "tokenize-rt"
@@ -2675,107 +2813,13 @@ files = [
[package.dependencies]
typing-extensions = ">=4.12.0"
[[package]]
name = "ujson"
version = "5.11.0"
description = "Ultra fast JSON encoder and decoder for Python"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "ujson-5.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25"},
{file = "ujson-5.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89"},
{file = "ujson-5.11.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6"},
{file = "ujson-5.11.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb"},
{file = "ujson-5.11.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db"},
{file = "ujson-5.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c"},
{file = "ujson-5.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138"},
{file = "ujson-5.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915"},
{file = "ujson-5.11.0-cp310-cp310-win32.whl", hash = "sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723"},
{file = "ujson-5.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0"},
{file = "ujson-5.11.0-cp310-cp310-win_arm64.whl", hash = "sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105"},
{file = "ujson-5.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f"},
{file = "ujson-5.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58"},
{file = "ujson-5.11.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26"},
{file = "ujson-5.11.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a"},
{file = "ujson-5.11.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6"},
{file = "ujson-5.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b"},
{file = "ujson-5.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba"},
{file = "ujson-5.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3"},
{file = "ujson-5.11.0-cp311-cp311-win32.whl", hash = "sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34"},
{file = "ujson-5.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01"},
{file = "ujson-5.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835"},
{file = "ujson-5.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702"},
{file = "ujson-5.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d"},
{file = "ujson-5.11.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80"},
{file = "ujson-5.11.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc"},
{file = "ujson-5.11.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c"},
{file = "ujson-5.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5"},
{file = "ujson-5.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b"},
{file = "ujson-5.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc"},
{file = "ujson-5.11.0-cp312-cp312-win32.whl", hash = "sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88"},
{file = "ujson-5.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f"},
{file = "ujson-5.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6"},
{file = "ujson-5.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53"},
{file = "ujson-5.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752"},
{file = "ujson-5.11.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50"},
{file = "ujson-5.11.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a"},
{file = "ujson-5.11.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03"},
{file = "ujson-5.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701"},
{file = "ujson-5.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60"},
{file = "ujson-5.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328"},
{file = "ujson-5.11.0-cp313-cp313-win32.whl", hash = "sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241"},
{file = "ujson-5.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0"},
{file = "ujson-5.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9"},
{file = "ujson-5.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302"},
{file = "ujson-5.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d"},
{file = "ujson-5.11.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638"},
{file = "ujson-5.11.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c"},
{file = "ujson-5.11.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba"},
{file = "ujson-5.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018"},
{file = "ujson-5.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840"},
{file = "ujson-5.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c"},
{file = "ujson-5.11.0-cp314-cp314-win32.whl", hash = "sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac"},
{file = "ujson-5.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629"},
{file = "ujson-5.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764"},
{file = "ujson-5.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433"},
{file = "ujson-5.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3"},
{file = "ujson-5.11.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823"},
{file = "ujson-5.11.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9"},
{file = "ujson-5.11.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076"},
{file = "ujson-5.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c"},
{file = "ujson-5.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746"},
{file = "ujson-5.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef"},
{file = "ujson-5.11.0-cp314-cp314t-win32.whl", hash = "sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5"},
{file = "ujson-5.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec"},
{file = "ujson-5.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab"},
{file = "ujson-5.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694"},
{file = "ujson-5.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac"},
{file = "ujson-5.11.0-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a"},
{file = "ujson-5.11.0-cp39-cp39-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02"},
{file = "ujson-5.11.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c"},
{file = "ujson-5.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a"},
{file = "ujson-5.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052"},
{file = "ujson-5.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596"},
{file = "ujson-5.11.0-cp39-cp39-win32.whl", hash = "sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547"},
{file = "ujson-5.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b"},
{file = "ujson-5.11.0-cp39-cp39-win_arm64.whl", hash = "sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9"},
{file = "ujson-5.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362"},
{file = "ujson-5.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39"},
{file = "ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc"},
{file = "ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844"},
{file = "ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49"},
{file = "ujson-5.11.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04"},
{file = "ujson-5.11.0.tar.gz", hash = "sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0"},
]
[[package]]
name = "urllib3"
version = "2.5.0"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.9"
groups = ["dev"]
groups = ["main", "dev"]
files = [
{file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"},
{file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"},
@@ -3116,4 +3160,4 @@ tests-strict = ["pytest (==4.6.0) ; python_version < \"3.10.0\" and python_versi
[metadata]
lock-version = "2.1"
python-versions = ">=3.13,<4.0"
content-hash = "3830d0acb8910ad5e4c89970d977f6ad770b987fba82ee43be47dd634a3ad0a8"
content-hash = "9e8c5e902a32a6378ad5ae0142a6bf9a459585a0e9e7bba62301874af70bfb2f"

View File

@@ -18,7 +18,7 @@ Changelog = "https://github.com/xlorepdarkhelm/backend/releases"
[tool.poetry.dependencies]
python = ">=3.13,<4.0"
click = "8.1.7"
fastapi = {extras = ["standard"], version = "0.111.0"}
fastapi = {extras = ["standard"], version = "0.118.0"}
asyncpg = "0.30.0"
sqlalchemy = "2.0.43"
alembic = "1.13.1"
@@ -50,10 +50,10 @@ typeguard = "4.2.1"
xdoctest = {extras = ["colors"], version = "1.1.3"}
myst-parser = {version = "2.0.0"}
pytest-asyncio = "1.1.0"
cryptography = "42.0.0" # For safety
cryptography = "44.0.1" # For safety
httpx = "0.27.0"
python-dotenv = "1.0.0"
nox = "2024.4.15"
nox = "2025.5.1"
nox-poetry = "1.2.0"
asyncpg-stubs = "0.30.2"
types-python-dateutil = "2.9.0.20250822"

View File

@@ -46,20 +46,16 @@ def _load_env_from_base_or_parent() -> None:
_load_env_from_base_or_parent()
from tests.types import BookingCreateData # noqa: E402
from tests.types import BookingUpdateData # noqa: E402
from tests.types import RoomData # noqa: E402
from tests.types import RoomUpdateData # noqa: E402
from tests.types import UserData # noqa: E402
from backend.main import app # noqa: E402
from backend.models import Booking # noqa: E402
from backend.models import BookingList # noqa: E402
from backend.models import Room # noqa: E402
from backend.models import RoomList # noqa: E402
from backend.models import User # noqa: E402
from backend.models import UserList # noqa: E402
from backend.schemas.bookings import BookingCreate # noqa: E402
from backend.types import BookingCreateData # noqa: E402
from backend.types import BookingUpdateData # noqa: E402
from backend.types import RoomData # noqa: E402
from backend.types import RoomUpdateData # noqa: E402
from backend.types import UserData # noqa: E402
# Modern handler type for exception handlers
@@ -96,7 +92,7 @@ async def client() -> AsyncGenerator[AsyncClient, None]:
Yields:
An HTTPX AsyncClient instance for making async HTTP requests.
"""
transport = ASGITransport(app=app)
transport = ASGITransport(app=app) # type: ignore[arg-type]
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac
@@ -142,7 +138,7 @@ def event_publisher() -> AsyncMock:
@pytest.fixture
def sample_users() -> UserList:
def sample_users() -> list[User]:
"""Fixture to provide sample User objects for testing.
Returns:
@@ -155,7 +151,7 @@ def sample_users() -> UserList:
@pytest.fixture
def sample_users_data(sample_users: UserList) -> list[UserData]:
def sample_users_data(sample_users: list[User]) -> list[UserData]:
"""Fixture to provide sample user data dictionaries for testing.
Args:
@@ -168,7 +164,7 @@ def sample_users_data(sample_users: UserList) -> list[UserData]:
@pytest.fixture
def sample_rooms() -> RoomList:
def sample_rooms() -> list[Room]:
"""Fixture to provide sample Room objects for testing.
Returns:
@@ -193,7 +189,7 @@ def sample_rooms() -> RoomList:
@pytest.fixture
def sample_room(sample_rooms: RoomList) -> Room:
def sample_room(sample_rooms: list[Room]) -> Room:
"""Fixture to provide a sample Room object for testing.
Args:
@@ -206,7 +202,7 @@ def sample_room(sample_rooms: RoomList) -> Room:
@pytest.fixture
def sample_room_data(sample_rooms: RoomList) -> RoomData:
def sample_room_data(sample_rooms: list[Room]) -> RoomData:
"""Fixture to provide sample room creation data for testing.
Args:
@@ -272,7 +268,7 @@ def utcnow() -> datetime:
@pytest.fixture
def sample_bookings(utcnow: datetime, sample_room: Room) -> BookingList:
def sample_bookings(utcnow: datetime, sample_room: Room) -> list[Booking]:
"""Fixture to provide sample Booking objects for testing.
Args:
@@ -305,7 +301,7 @@ def sample_bookings(utcnow: datetime, sample_room: Room) -> BookingList:
@pytest.fixture
def sample_booking(sample_bookings: BookingList) -> Booking:
def sample_booking(sample_bookings: list[Booking]) -> Booking:
"""Fixture to provide a sample Booking object for testing.
Args:
@@ -426,7 +422,7 @@ def updated_booking(
@pytest.fixture
def conflict_booking_update_data(sample_bookings: BookingList) -> BookingUpdateData:
def conflict_booking_update_data(sample_bookings: list[Booking]) -> BookingUpdateData:
"""Fixture to provide booking update data that would cause a conflict.
Args:

View File

@@ -9,23 +9,22 @@ from httpx import AsyncClient
from sqlalchemy.exc import NoResultFound
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from tests.types import BookingCreateData
from tests.types import BookingData
from tests.types import BookingUpdateData
from backend.db import get_session
from backend.dependencies.bookings import delete_booking_service
from backend.dependencies.bookings import get_booking_service
from backend.dependencies.bookings import get_bookings_for_month_service
from backend.dependencies.bookings import new_booking_service
from backend.dependencies.bookings import update_booking_service
from backend.dependencies.db import get_session
from backend.dependencies.rooms import get_room_service
from backend.main import app
from backend.models import Booking
from backend.models import BookingList
from backend.models import Room
from backend.routers.rooms import publish_room_availability_event
from backend.services.bookings import update_booking
from backend.types import BookingCreateData
from backend.types import BookingData
from backend.types import BookingUpdateData
# Useful constants for booking router tests
@@ -237,7 +236,7 @@ async def test_booking_creation_conflict(
client: AsyncClient,
sample_room: Room,
sample_booking: Booking,
sample_bookings: BookingList,
sample_bookings: list[Booking],
sample_booking_data: BookingCreateData,
conflict_booking_data: BookingCreateData,
endpoint: str,
@@ -310,7 +309,7 @@ async def test_booking_creation_conflict(
async def test_booking_update_conflict(
client: AsyncClient,
sample_room: Room,
sample_bookings: BookingList,
sample_bookings: list[Booking],
conflict_booking_update_data: BookingUpdateData,
payload: str,
expected_status: int,
@@ -447,7 +446,7 @@ async def test_read_booking_parametrized(
)
async def test_read_bookings_for_month_parametrized(
client: AsyncClient,
sample_bookings: BookingList,
sample_bookings: list[Booking],
sample_room: Room,
mock_case: str,
expected_status: int,

View File

@@ -4,14 +4,12 @@ import asyncio
import re
from typing import Any
import asyncpg
import asyncpg # type: ignore [import-untyped]
import pytest
from httpx import AsyncClient
from httpx import Response
from sqlalchemy.exc import NoResultFound
from sqlalchemy.exc import SQLAlchemyError
from tests.types import RoomData
from tests.types import RoomUpdateData
from backend.dependencies.rooms import delete_room_service
from backend.dependencies.rooms import get_room_service
@@ -20,9 +18,10 @@ from backend.dependencies.rooms import new_room_service
from backend.dependencies.rooms import update_room_service
from backend.main import app
from backend.models import Room
from backend.models import RoomList
from backend.routers.rooms import publish_room_availability_event
from backend.routers.rooms import room_availability_subscribers
from backend.types import RoomData
from backend.types import RoomUpdateData
# Useful constants for rooms router tests
@@ -45,7 +44,7 @@ ROOM_NOT_FOUND_ID = 999
)
async def test_get_rooms_parametrized_fixture(
client: AsyncClient,
sample_rooms: RoomList,
sample_rooms: list[Room],
room_case: str,
) -> None:
"""Parametrized test for GET /rooms/ using fixture data only.
@@ -64,7 +63,7 @@ async def test_get_rooms_parametrized_fixture(
else:
rooms = []
async def mock_get_rooms(*args: Any, **kwargs: Any) -> RoomList:
async def mock_get_rooms(*args: Any, **kwargs: Any) -> list[Room]:
return rooms
app.dependency_overrides[get_rooms_service] = lambda: mock_get_rooms
@@ -108,7 +107,7 @@ async def test_new_room_success(
@pytest.mark.asyncio
async def test_update_room_success(
client: AsyncClient,
sample_rooms: RoomList,
sample_rooms: list[Room],
room_update_data: RoomData,
updated_room: Room,
) -> None:
@@ -126,7 +125,7 @@ async def test_update_room_success(
"""
room_id = sample_rooms[0].id
async def mock_get_rooms(*args: Any, **kwargs: Any) -> RoomList:
async def mock_get_rooms(*args: Any, **kwargs: Any) -> list[Room]:
return sample_rooms
async def mock_update_room(*args: Any, **kwargs: Any) -> Room:
@@ -233,7 +232,7 @@ async def test_stream_room_availability(client: AsyncClient) -> None:
)
async def test_update_room_error_cases_post(
client: AsyncClient,
sample_rooms: RoomList,
sample_rooms: list[Room],
room_update_data: RoomUpdateData,
exception: Exception,
expected_status: int,
@@ -276,7 +275,7 @@ async def test_update_room_error_cases_post(
)
async def test_update_room_error_cases(
client: AsyncClient,
sample_rooms: RoomList,
sample_rooms: list[Room],
room_update_data: RoomData,
exception: Exception,
expected_status: int,
@@ -365,7 +364,7 @@ async def test_delete_room_error_cases(
)
async def test_update_room_asyncpg_error(
client: AsyncClient,
sample_rooms: RoomList,
sample_rooms: list[Room],
room_update_data: RoomUpdateData,
exception: Exception,
expected_status: int,
@@ -509,7 +508,7 @@ async def test_get_rooms_asyncpg_error(
- Response detail matches expected_detail.
"""
async def mock_get_rooms(*args: Any, **kwargs: Any) -> RoomList:
async def mock_get_rooms(*args: Any, **kwargs: Any) -> list[Room]:
raise exception
app.dependency_overrides[get_rooms_service] = lambda: mock_get_rooms
@@ -531,7 +530,7 @@ def test_publish_room_availability_event_no_subscribers() -> None:
@pytest.mark.asyncio
async def test_patch_room_update_data_pop_id(
client: AsyncClient,
sample_rooms: RoomList,
sample_rooms: list[Room],
room_update_data: RoomData,
updated_room: Room,
) -> None:
@@ -711,7 +710,7 @@ async def test_get_rooms_error_branches_full(
- Response detail matches expected_detail.
"""
async def mock_get_rooms(*args: Any, **kwargs: Any) -> RoomList:
async def mock_get_rooms(*args: Any, **kwargs: Any) -> list[Room]:
raise exception
app.dependency_overrides[get_rooms_service] = lambda: mock_get_rooms

View File

@@ -6,11 +6,11 @@ import pytest
import sqlalchemy.exc
from httpx import AsyncClient
from sqlalchemy.exc import SQLAlchemyError
from tests.types import UserData
from backend.dependencies.users import get_users_service
from backend.main import app
from backend.models import UserList
from backend.models import User
from backend.types import UserData
# Useful constants for users router tests
@@ -26,7 +26,7 @@ USERS_UNEXPECTED_ERROR_DETAIL = "An unexpected error occurred"
@pytest.mark.parametrize("has_users", [True, False], ids=["users_exist", "users_empty"])
async def test_read_users_parametrized(
client: AsyncClient,
sample_users: UserList,
sample_users: list[User],
sample_users_data: list[UserData],
has_users: bool,
) -> None:
@@ -43,7 +43,7 @@ async def test_read_users_parametrized(
- Response JSON matches expected user data or empty list.
"""
async def mock_get_users(*args: Any, **kwargs: Any) -> UserList:
async def mock_get_users(*args: Any, **kwargs: Any) -> list[User]:
return sample_users if has_users else []
app.dependency_overrides[get_users_service] = lambda: mock_get_users

View File

@@ -17,23 +17,18 @@ from typing import Any
from typing import Awaitable
from typing import Callable
from typing import Iterator
from typing import cast
from unittest.mock import AsyncMock
from unittest.mock import MagicMock
from unittest.mock import patch
import pytest
from dateutil.parser import isoparse # type: ignore[import-untyped]
from sqlalchemy import delete
from sqlalchemy import update
from sqlalchemy.exc import NoResultFound
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from tests.types import BookingData
from tests.types import BookingUpdateData
from backend.models import Booking
from backend.models import BookingList
from backend.models import Room
from backend.schemas.bookings import BookingCreate
from backend.schemas.bookings import BookingResponse
@@ -42,12 +37,12 @@ from backend.services.bookings import get_booking
from backend.services.bookings import get_bookings_for_month
from backend.services.bookings import new_booking
from backend.services.bookings import update_booking
from backend.services.bookings import validate_new_booking_max_future
from backend.services.bookings import validate_new_booking_no_overlap
from backend.services.bookings import validate_new_booking_room_exists
from backend.services.bookings import validate_new_booking_time_constraints
from backend.services.bookings import validate_max_future
from backend.services.bookings import validate_no_overlap
from backend.services.bookings import validate_room_exists
from backend.services.bookings import validate_time_constraints
from backend.types import BookingData
from backend.types import BookingUpdateData
# Error message constants
@@ -185,7 +180,7 @@ async def await_all_asyncmock_methods(session: Any, method_names: list[str]) ->
@pytest.mark.asyncio
async def test_get_bookings_for_month_returns_bookings(
async_session: AsyncMock,
sample_bookings: BookingList,
sample_bookings: list[Booking],
month: str,
expected_count: int,
) -> None:
@@ -272,7 +267,7 @@ async def test_new_booking_success(
new=AsyncMock(return_value=None),
),
):
result = await new_booking(async_session, booking_create)
result = await new_booking(async_session, **booking_create.model_dump())
assert isinstance(result, dict)
assert result["room_id"] == booking_create.room_id
assert result["start_time"] == booking_create.start_time
@@ -315,21 +310,10 @@ async def test_update_booking_success(
),
):
booking_id = updated_booking.id
# Remove 'id' if present in booking_update_data
# Convert ISO strings to datetime objects for service call
filtered_booking_update_data: dict[str, object] = {
k: (
v
if k not in {"start_time", "end_time"}
else isoparse(str(v)).isoformat()
)
for k, v in booking_update_data.items()
if k != "id"
}
result = await update_booking(
async_session,
booking_id,
**filtered_booking_update_data,
**booking_update_data,
event_publisher=event_publisher,
)
assert isinstance(result, Booking)
@@ -378,43 +362,15 @@ async def test_delete_booking_success(
await delete_booking(async_session, booking_id)
async_session.commit.assert_called()
with pytest.raises(ValueError, match="The selected room does not exist."):
await validate_new_booking_room_exists(async_session, 999)
await validate_room_exists(async_session, 999)
@pytest.mark.parametrize(
"func, args, should_raise",
[
# validate_new_booking_time_constraints
# validate_max_future
(
"validate_new_booking_time_constraints",
(
datetime.now(timezone.utc) + timedelta(days=1),
datetime.now(timezone.utc) + timedelta(days=2),
datetime.now(timezone.utc),
),
False,
), # valid: start < end
(
"validate_new_booking_time_constraints",
(
datetime.now(timezone.utc) - timedelta(days=2),
datetime.now(timezone.utc) - timedelta(days=1),
datetime.now(timezone.utc),
),
True,
), # invalid: start < now
(
"validate_new_booking_time_constraints",
(
datetime.now(timezone.utc) + timedelta(days=2),
datetime.now(timezone.utc) + timedelta(days=1),
datetime.now(timezone.utc),
),
True,
), # invalid: start > end
# validate_new_booking_max_future
(
"validate_new_booking_max_future",
"validate_max_future",
(
datetime.now(timezone.utc) + timedelta(days=1),
datetime.now(timezone.utc) + timedelta(days=30),
@@ -424,7 +380,7 @@ async def test_delete_booking_success(
False,
), # valid: within max future
(
"validate_new_booking_max_future",
"validate_max_future",
(
datetime.now(timezone.utc) + timedelta(days=1),
datetime.now(timezone.utc) + timedelta(days=400),
@@ -476,9 +432,6 @@ async def test_delete_booking_success(
), # invalid: exceeds max future
],
ids=[
"valid: start < end",
"invalid: start < now (past)",
"invalid: start > end",
"valid: within max future",
"invalid: exceeds max future",
"valid: start < end, within max",
@@ -504,8 +457,7 @@ def test_time_constraint_validators_param(
- No exception for valid constraints.
"""
func_map: dict[str, Callable[..., Any]] = {
"validate_new_booking_time_constraints": validate_new_booking_time_constraints,
"validate_new_booking_max_future": validate_new_booking_max_future,
"validate_max_future": validate_max_future,
"validate_time_constraints": validate_time_constraints,
}
validator: Callable[..., Any] = func_map[func]
@@ -543,11 +495,13 @@ async def run_event_publisher_operation(
if operation == "new_booking":
# booking is expected to be a BookingCreate or BookingData from fixture
result = await new_booking(
async_session, booking_create, event_publisher=event_publisher
async_session,
**booking_create.model_dump(),
event_publisher=event_publisher,
)
event_publisher.assert_awaited()
assert (
result["id"] if isinstance(result, dict) else getattr(result, "id", None)
result.id if isinstance(result, dict) else getattr(result, "id", None)
) == booking_id
elif operation == "update_booking":
result = await update_booking( # type: ignore
@@ -681,10 +635,12 @@ async def test_event_publisher_called(
with apply_patches(patch_targets):
if operation == "new_booking":
result = await new_booking(
async_session, booking_create, event_publisher=event_publisher
async_session,
**booking_create.model_dump(),
event_publisher=event_publisher,
)
event_publisher.assert_awaited()
assert result["id"] == mock_update_booking_return_dict.get("id")
assert result.id == mock_update_booking_return_dict.get("id")
elif operation == "update_booking":
booking_id = sample_booking.id # already int
result = await update_booking( # type: ignore
@@ -1144,14 +1100,15 @@ async def test_new_booking_param(
async_session, "scalars", AsyncMock(return_value=mock_scalars_result)
):
if expected_exception:
exc_info: pytest.ExceptionInfo[Exception]
with pytest.raises(expected_exception) as exc_info: # pyright: ignore
await new_booking(async_session, booking_create)
await new_booking(async_session, **booking_create.model_dump())
if expected_error:
assert expected_error in str(exc_info.value) # pyright: ignore
async_session.rollback.assert_called()
else:
result = await new_booking(async_session, booking_create)
assert result["room_id"] == booking_create.room_id
result = await new_booking(async_session, **booking_create.model_dump())
assert result.room_id == booking_create.room_id
async_session.add.assert_called_once()
# Accept either one or two commits, depending on service logic
assert async_session.commit.call_count >= 1
@@ -1269,10 +1226,6 @@ async def test_update_booking_param(
else:
async_session.execute = AsyncMock(return_value=execute_return) # type: ignore[method-assign]
update_params = dict(update_params) # type: ignore
update_params = cast(
BookingUpdateData, {k: v for k, v in update_params.items() if k != "id"}
)
updated_booking = Booking(**update_params)
updated_booking.id = booking_id
async_session.scalar = AsyncMock(return_value=updated_booking) # type: ignore[method-assign]
@@ -1297,27 +1250,22 @@ async def test_update_booking_param(
async_session.scalars = AsyncMock(return_value=scalars_mock) # type: ignore[method-assign]
event_publisher = AsyncMock()
if expected_exception:
update_params = cast(
BookingUpdateData, {k: v for k, v in update_params.items() if k != "id"}
)
exc_info: pytest.ExceptionInfo[Exception]
with pytest.raises(expected_exception) as exc_info: # pyright: ignore
await update_booking(
async_session,
booking_id,
**{k: v for k, v in update_params.items() if k != "id"},
**update_params,
event_publisher=event_publisher,
)
if expected_message:
assert expected_message in str(exc_info.value) # pyright: ignore
async_session.rollback.assert_called()
else:
update_params = cast(
BookingUpdateData, {k: v for k, v in update_params.items() if k != "id"}
)
result: Booking = await update_booking(
async_session,
booking_id,
**{k: v for k, v in update_params.items() if k != "id"},
**update_params,
event_publisher=event_publisher,
)
assert result == updated_booking
@@ -1388,6 +1336,7 @@ async def test_delete_booking_param(
async_session.rollback = AsyncMock() # type: ignore[method-assign]
if expected_exception:
exc_info: pytest.ExceptionInfo[Exception]
with pytest.raises(expected_exception) as exc_info: # pyright: ignore
await delete_booking(async_session, booking_id)
if expected_message:
@@ -1430,9 +1379,13 @@ async def test_validate_new_booking_no_overlap_param(
session.scalars.return_value = scalars_mock
if raises:
with pytest.raises(ValueError, match=BOOKING_CONFLICT_MSG):
await validate_new_booking_no_overlap(session, booking)
await validate_no_overlap(
session, booking.room_id, booking.start_time, booking.end_time
)
else:
await validate_new_booking_no_overlap(session, booking)
await validate_no_overlap(
session, booking.room_id, booking.start_time, booking.end_time
)
session.scalars.assert_called_once()
@@ -1461,7 +1414,9 @@ async def test_validate_no_overlap_param(overlap: bool, raises: bool) -> None:
session.scalars.return_value = scalars_mock
if raises:
with pytest.raises(ValueError, match=BOOKING_CONFLICT_MSG):
await validate_no_overlap(session, booking_id, room_id, new_start, new_end)
await validate_no_overlap(session, room_id, new_start, new_end)
else:
await validate_no_overlap(session, booking_id, room_id, new_start, new_end)
await validate_no_overlap(
session, room_id, new_start, new_end, exclude_booking_id=booking_id
)
session.scalars.assert_called_once()

View File

@@ -23,7 +23,6 @@ from unittest.mock import AsyncMock
from unittest.mock import MagicMock
from unittest.mock import patch
# Third-party imports
import pytest
from sqlalchemy import delete
from sqlalchemy import select
@@ -33,13 +32,15 @@ from sqlalchemy.ext.asyncio import AsyncSession
# Local imports
from backend.models import Room
from backend.models import RoomList
from backend.services.rooms import delete_room
from backend.services.rooms import get_room
from backend.services.rooms import get_rooms
from backend.services.rooms import new_room
from backend.services.rooms import update_room
# Third-party imports
from backend.types import RoomData
# Error message constants
ROOM_NOT_FOUND_MSG = "Room not found"
@@ -51,7 +52,7 @@ ROOM_NOT_FOUND_ID = 999
@pytest.mark.asyncio
async def test_get_rooms_returns_all_rooms(
async_session: AsyncSession, sample_rooms: RoomList
async_session: AsyncSession, sample_rooms: list[Room]
) -> None:
"""Test successful retrieval of all rooms from the database.
@@ -68,7 +69,7 @@ async def test_get_rooms_returns_all_rooms(
mock_scalars = AsyncMock(return_value=mock_scalars_result)
async_session.scalars = mock_scalars # type: ignore [method-assign]
result: RoomList = await get_rooms(async_session)
result: list[Room] = await get_rooms(async_session)
assert isinstance(result, list)
assert len(result) == 2
@@ -93,7 +94,7 @@ async def test_get_rooms_returns_empty_list(async_session: AsyncSession) -> None
mock_scalars = AsyncMock(return_value=mock_scalars_result)
async_session.scalars = mock_scalars # type: ignore [method-assign]
result: RoomList = await get_rooms(async_session)
result: list[Room] = await get_rooms(async_session)
assert isinstance(result, list)
assert len(result) == 0
@@ -186,13 +187,17 @@ async def test_get_room_and_delete_room_database_error(
ids=["sqlalchemy_error", "dummy_error"],
)
async def test_new_room_database_error(
async_session: AsyncSession, sample_room: Room, exc_type: type[Exception]
async_session: AsyncSession,
sample_room: Room,
sample_room_data: RoomData,
exc_type: type[Exception],
) -> None:
"""Test error handling and finally block coverage for new_room.
Args:
async_session: The asynchronous database session fixture.
sample_room: The sample Room object fixture.
sample_room_data: The data for creating the room.
exc_type: The exception type to raise.
Asserts:
@@ -209,7 +214,7 @@ async def test_new_room_database_error(
async_session.rollback = AsyncMock() # type: ignore [method-assign]
with patch("backend.services.rooms.logger.debug") as mock_debug:
with pytest.raises(exc_type):
await new_room(async_session, sample_room)
await new_room(async_session, **sample_room_data)
assert mock_debug.called
async_session.add.assert_called_once_with(sample_room)
async_session.commit.assert_called_once()
@@ -322,12 +327,20 @@ async def test_get_room_returns_room_fixture(
assert async_session.scalar.call_args.args[0].compare(
select(Room).where(Room.id == sample_room.id)
)
@pytest.mark.asyncio
async def test_new_room_commits_errors(
async_session: AsyncSession, sample_room: Room, sample_room_data: RoomData
) -> None:
"""Test handling of database errors in new_room.
Verifies that new_room rolls back the session on database failure.
Args:
async_session: The asynchronous database session.
sample_room: The sample Room object fixture.
sample_room_data: The data for creating the room.
Asserts:
- SQLAlchemyError is raised
@@ -342,7 +355,7 @@ async def test_get_room_returns_room_fixture(
async_session.rollback = AsyncMock() # type: ignore [method-assign]
with pytest.raises(SQLAlchemyError):
await new_room(async_session, sample_room)
await new_room(async_session, **sample_room_data)
async_session.add.assert_called_once_with(sample_room)
async_session.commit.assert_called_once()
async_session.rollback.assert_called_once()