From d93cb61c5d589ab49f3e6fa823918b9bcd6df873 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 19:01:04 +0200 Subject: [PATCH 01/34] feat: add fastapi package cd backend && poetry add fastapi --- backend/poetry.lock | 701 ++++++++++++++++++++++++++++++++++++++++- backend/pyproject.toml | 1 + 2 files changed, 699 insertions(+), 3 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 012d5456..a49b2ed0 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "alembic" @@ -677,6 +677,26 @@ files = [ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] +[[package]] +name = "dnspython" +version = "2.6.1" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + [[package]] name = "dulwich" version = "0.21.7" @@ -764,6 +784,21 @@ https = ["urllib3 (>=1.24.1)"] paramiko = ["paramiko"] pgp = ["gpg"] +[[package]] +name = "email-validator" +version = "2.1.1" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, + {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + [[package]] name = "et-xmlfile" version = "1.1.0" @@ -789,6 +824,50 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "fastapi" +version = "0.111.0" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"}, + {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"}, +] + +[package.dependencies] +email_validator = ">=2.0.0" +fastapi-cli = ">=0.0.2" +httpx = ">=0.23.0" +jinja2 = ">=2.11.2" +orjson = ">=3.2.1" +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" +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"]} + +[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)"] + +[[package]] +name = "fastapi-cli" +version = "0.0.4" +description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"}, + {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"}, +] + +[package.dependencies] +typer = ">=0.12.3" + +[package.extras] +standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] + [[package]] name = "fastjsonschema" version = "2.19.1" @@ -1113,6 +1192,110 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "httpcore" +version = "1.0.5" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httptools" +version = "0.6.1" +description = "A collection of framework independent HTTP protocol utils." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, + {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, + {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, + {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, + {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, + {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, + {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, +] + +[package.extras] +test = ["Cython (>=0.29.24,<0.30.0)"] + +[[package]] +name = "httpx" +version = "0.27.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + [[package]] name = "identify" version = "2.5.36" @@ -1219,6 +1402,23 @@ files = [ test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] trio = ["async_generator", "trio"] +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + [[package]] name = "keyring" version = "24.3.1" @@ -1374,6 +1574,30 @@ babel = ["Babel"] lingua = ["lingua"] testing = ["pytest"] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "markupsafe" version = "2.1.5" @@ -1492,6 +1716,17 @@ pillow = ">=8" pyparsing = ">=2.3.1" python-dateutil = ">=2.7" +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "more-itertools" version = "10.2.0" @@ -1565,7 +1800,6 @@ files = [ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, - {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"}, {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] @@ -1741,6 +1975,61 @@ files = [ [package.dependencies] et-xmlfile = "*" +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, +] + [[package]] name = "packaging" version = "24.0" @@ -2305,6 +2594,20 @@ python-dotenv = ">=0.21.0" toml = ["tomli (>=2.0.1)"] yaml = ["pyyaml (>=6.0.1)"] +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + [[package]] name = "pyparsing" version = "3.1.2" @@ -2416,6 +2719,20 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-multipart" +version = "0.0.9" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, + {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, +] + +[package.extras] +dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"] + [[package]] name = "pytz" version = "2024.1" @@ -2635,6 +2952,24 @@ files = [ [package.dependencies] requests = ">=2.0.1,<3.0.0" +[[package]] +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + [[package]] name = "ruff" version = "0.3.7" @@ -2925,6 +3260,24 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] +[[package]] +name = "starlette" +version = "0.37.2" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.8" +files = [ + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] + [[package]] name = "tomli" version = "2.0.1" @@ -2985,6 +3338,23 @@ files = [ {file = "trove_classifiers-2024.5.17.tar.gz", hash = "sha256:d47a6f1c48803091c3fc81f535fecfeef65b558f2b9e4e83df7a79d17bce8bbf"}, ] +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + [[package]] name = "typing-extensions" version = "4.11.0" @@ -3007,6 +3377,93 @@ files = [ {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, ] +[[package]] +name = "ujson" +version = "5.10.0" +description = "Ultra fast JSON encoder and decoder for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, + {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"}, + {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"}, + {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"}, + {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"}, + {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"}, + {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"}, + {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"}, + {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"}, + {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"}, + {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"}, + {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"}, + {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"}, + {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"}, + {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"}, +] + [[package]] name = "urllib3" version = "2.2.1" @@ -3024,6 +3481,76 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "uvicorn" +version = "0.30.1" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.8" +files = [ + {file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"}, + {file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} +h11 = ">=0.8" +httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "uvloop" +version = "0.19.0" +description = "Fast implementation of asyncio event loop on top of libuv" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, + {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, +] + +[package.extras] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] + [[package]] name = "virtualenv" version = "20.26.2" @@ -3044,6 +3571,174 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +[[package]] +name = "watchfiles" +version = "0.22.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, + {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, + {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, + {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, + {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, + {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, + {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, + {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, + {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, + {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, + {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, + {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, + {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, + {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, + {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, +] + +[package.dependencies] +anyio = ">=3.0.0" + +[[package]] +name = "websockets" +version = "12.0" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + [[package]] name = "xattr" version = "1.1.0" @@ -3238,4 +3933,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.9.7 || >3.9.7,<4.0" -content-hash = "321c08a721f8ab2dde124041e2961be041dd0ff1f791ee939501b92f8dbe34b9" +content-hash = "c60d51d66d4f418f14ff1c0097d4e5d72447b9c8f1970cf7a03266c67b4aba62" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 0e877419..88e28083 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -34,6 +34,7 @@ scipy = "1.12.0" slack-sdk = "~3.27" SQLAlchemy = "~2.0" pycountry = "23.12.11" +fastapi = "^0.111.0" [tool.poetry.group.dev.dependencies] From bec2f3c00524604224a8f53a4fe0c5843ce5efba Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 20:48:43 +0200 Subject: [PATCH 02/34] feat: base api + docker container --- .env.template | 1 + backend/bloom/services/api.py | 93 +++++++++++++++++++++++++++++++++++ backend/poetry.lock | 2 +- backend/pyproject.toml | 1 + docker-compose.yaml | 5 +- 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 backend/bloom/services/api.py diff --git a/.env.template b/.env.template index 1891c821..fab4d6dd 100644 --- a/.env.template +++ b/.env.template @@ -8,6 +8,7 @@ POSTGRES_USER=bloom_user POSTGRES_PASSWORD=bloom POSTGRES_DB=bloom_db POSTGRES_PORT=5432 +API_PORT=8000 SPIRE_TOKEN= SLACK_URL= diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py new file mode 100644 index 00000000..02d3166e --- /dev/null +++ b/backend/bloom/services/api.py @@ -0,0 +1,93 @@ +from fastapi import FastAPI, APIRouter +from fastapi import Request + +from datetime import datetime + +app = FastAPI() + +@app.get("/vessels") +async def list_vessels(): + return {"vessels": ["TODO"]} + +@app.get("/vessels/{vessel_id}") +async def get_vessel(vessel_id: int): + return {"vessel": "TODO"} + +@app.get("/vessels/{vessel_id}/positions") +async def list_vessel_positions(vessel_id: int, start: datetime = datetime.now(), end:datetime=None): + return {"positions": ["TODO"]} + +@app.get("/vessels/{vessel_id}/positions/last") +async def list_vessel_position_last(vessel_id: int, date:datetime = datetime.now()): + return {"position": ["TODO"]} + +@app.get("/vessels/{vessel_id}/excursions") +async def list_vessel_excursions(vessel_id: int): + return {"excursions": ["TODO"]} + + +@app.get("/vessels/{vessel_id}/excursions/{excursions_id}") +async def get_vessel_excursion(vessel_id: int,excursions_id: int): + return {"excursion": "TODO"} + + +@app.get("/vessels/{vessel_id}/excursions/{excursions_id}/segments") +async def list_vessel_excursion_segments(vessel_id: int,excursions_id: int): + return {"segments": ["TODO"]} + +@app.get("/vessels/{vessel_id}/excursions/{excursions_id}/segments/{segment_id}") +async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segment_id:int): + return {"segment": "TODO"} + +@app.get("/ports") +async def list_ports(): + return {"ports": ["TODO"]} + +@app.get("/ports/{port_id}") +async def get_port(port_id:int): + return {"port": "TODO"} + +@app.get("/zones") +async def list_zones(): + return {"zones": ["TODO"]} + +@app.get("/zones/{zones_id}") +async def get_zone(zones_id:int): + return {"zone": "TODO"} + +@app.get("/statics/{zones}") +async def get_statics_zones(): + return {} + +@app.get("/maptiles/mpa") +async def get_maptile_mpa(): + return {"data":{}} + +@app.get("/maptiles/territorial") +async def get_maptile_territorial(): + return {"data":{}} + +@app.get("/maptiles/coastal") +async def get_maptile_coastal(): + return {"data":{}} + +@app.get("/maptiles") +async def list_maptiles(request:Request): + return { + "mpa": f"{request.url_for('get_maptile_mpa')}", + "territorial": f"{request.url_for('get_maptile_territorial')}", + "coastal": f"{request.url_for('get_maptile_coastal')}", + } + +@app.get("/maptiles") +async def list_maptiles(): + return {"data":{}} + +@app.get("/") +async def root(request:Request): + return { + "maptiles": f"{request.url_for('list_maptiles')}", + "ports": f"{request.url_for('list_ports')}", + "vessels": f"{request.url_for('list_vessels')}", + "zones": f"{request.url_for('list_zones')}", + } \ No newline at end of file diff --git a/backend/poetry.lock b/backend/poetry.lock index a49b2ed0..7b7d6fe8 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -3933,4 +3933,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.9.7 || >3.9.7,<4.0" -content-hash = "c60d51d66d4f418f14ff1c0097d4e5d72447b9c8f1970cf7a03266c67b4aba62" +content-hash = "740d50a18a924511385f56fa4158106fc29c78d82e29e36a614846144ea3b755" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 88e28083..395946d0 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -35,6 +35,7 @@ slack-sdk = "~3.27" SQLAlchemy = "~2.0" pycountry = "23.12.11" fastapi = "^0.111.0" +uvicorn = "^0.30.1" [tool.poetry.group.dev.dependencies] diff --git a/docker-compose.yaml b/docker-compose.yaml index 6030c332..2bc4334c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -18,7 +18,7 @@ services: - -c - | echo "Starting Scheduler" && - cron -f -L 2 + service cron start && uvicorn bloom.services.api:app --host 0.0.0.0 --reload volumes: - ./:/project/ - ./data:/project/data @@ -26,8 +26,9 @@ services: <<: *common-env POSTGRES_PORT: 5432 STREAMLIT_SERVER_ADDRESS: ${STREAMLIT_SERVER_ADDRESS:-0.0.0.0} + WATCHFILES_FORCE_POLLING: true ports: - - 8501:8501 + - ${API_PORT:-8000}:8000 networks: - bloom_net depends_on: From 69811beb38dd4e935f775b5baa9e8315166d6a52 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 21:40:33 +0200 Subject: [PATCH 03/34] feat: add vessels & vessels/{id} --- backend/bloom/services/api.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 02d3166e..17e8521e 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -3,15 +3,26 @@ from datetime import datetime +from bloom.config import settings +from bloom.container import UseCases +from bloom.domain.vessel import Vessel app = FastAPI() @app.get("/vessels") async def list_vessels(): - return {"vessels": ["TODO"]} + use_cases = UseCases() + vessel_repository = use_cases.vessel_repository() + db = use_cases.db() + with db.session() as session: + return vessel_repository.get_vessels_list(session) @app.get("/vessels/{vessel_id}") async def get_vessel(vessel_id: int): - return {"vessel": "TODO"} + use_cases = UseCases() + vessel_repository = use_cases.vessel_repository() + db = use_cases.db() + with db.session() as session: + return vessel_repository.get_vessel_by_id(session,vessel_id) @app.get("/vessels/{vessel_id}/positions") async def list_vessel_positions(vessel_id: int, start: datetime = datetime.now(), end:datetime=None): From b9b8604af8cde81a0e810c2421f55599ee8e664b Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 21:41:08 +0200 Subject: [PATCH 04/34] feat: docker add load-data script and volume persistence --- docker-compose-load-data.yaml | 4 +--- docker-compose.yaml | 5 +++++ docker/up_with_data.bat | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 docker/up_with_data.bat diff --git a/docker-compose-load-data.yaml b/docker-compose-load-data.yaml index 32d9b601..334357ef 100644 --- a/docker-compose-load-data.yaml +++ b/docker-compose-load-data.yaml @@ -16,8 +16,6 @@ services: command: - -c - "/venv/bin/python3 backend/bloom/tasks/load_dim_vessel_from_csv.py && - /venv/bin/python3 backend/alembic/init_script/load_positions_data.py && - /venv/bin/python3 backend/alembic/init_script/load_amp_data.py && /venv/bin/python3 backend/bloom/tasks/load_dim_port_from_csv.py && /venv/bin/python3 backend/bloom/tasks/compute_port_geometry_buffer.py" volumes: @@ -29,7 +27,7 @@ services: networks: - bloom_net depends_on: - init: + bloom-init: condition: service_completed_successfully networks: diff --git a/docker-compose.yaml b/docker-compose.yaml index 2bc4334c..8d706a40 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -45,6 +45,8 @@ services: - ${POSTGRES_PORT:-5432}:5432 networks: - bloom_net + volumes: + - bloom-data:/var/lib/postgresql/data healthcheck: # PostGis database initialization is done with two steps (postgres+postgis) # This causes healthcheck to be valid before real full initialization @@ -114,6 +116,9 @@ services: bloom-postgres: condition: service_healthy # The service is working and still running +volumes: + bloom-data: + networks: bloom_net: name: bloom_net diff --git a/docker/up_with_data.bat b/docker/up_with_data.bat new file mode 100644 index 00000000..84559c72 --- /dev/null +++ b/docker/up_with_data.bat @@ -0,0 +1,2 @@ +cd %~dp0/.. +docker compose -f docker-compose.yaml -f docker-compose-load-data.yaml up || pause \ No newline at end of file From b70010bb11cf02e78739dfcc831c69d4f58e0b86 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 21:45:47 +0200 Subject: [PATCH 05/34] feat: add ports & ports/{id} endpoints --- backend/bloom/domain/port.py | 13 +++++++++---- backend/bloom/infra/repositories/repository_port.py | 2 +- backend/bloom/services/api.py | 13 +++++++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/backend/bloom/domain/port.py b/backend/bloom/domain/port.py index 8e36d6a8..23f78a7a 100644 --- a/backend/bloom/domain/port.py +++ b/backend/bloom/domain/port.py @@ -3,12 +3,17 @@ # For compliance with python 3.9 syntax from pydantic import BaseModel, ConfigDict from shapely import Point, Polygon - +from shapely.geometry import mapping, shape from typing import Union - class Port(BaseModel): - model_config = ConfigDict(arbitrary_types_allowed=True) + model_config = ConfigDict( + arbitrary_types_allowed=True, + json_encoders = { + Point: lambda point: mapping(point), + Polygon: lambda polygon: mapping(polygon), + }, + ) id: Union[int, None] = None name: str locode: str @@ -20,4 +25,4 @@ class Port(BaseModel): geometry_buffer: Union[Polygon, None] = None has_excursion: bool = False created_at: Union[datetime, None] = None - updated_at: Union[datetime, None] = None + updated_at: Union[datetime, None] = None \ No newline at end of file diff --git a/backend/bloom/infra/repositories/repository_port.py b/backend/bloom/infra/repositories/repository_port.py index f090d659..264dc6e1 100644 --- a/backend/bloom/infra/repositories/repository_port.py +++ b/backend/bloom/infra/repositories/repository_port.py @@ -18,7 +18,7 @@ def __init__(self, session_factory: Callable) -> None: self.session_factory = session_factory def get_port_by_id(self, session: Session, port_id: int) -> Union[Port, None]: - entity = session.get(sql_model.Port, port_id).scalar() + entity = session.get(sql_model.Port, port_id) if entity is not None: return PortRepository.map_to_domain(entity) else: diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 17e8521e..1bdd1496 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -6,6 +6,7 @@ from bloom.config import settings from bloom.container import UseCases from bloom.domain.vessel import Vessel + app = FastAPI() @app.get("/vessels") @@ -52,11 +53,19 @@ async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segmen @app.get("/ports") async def list_ports(): - return {"ports": ["TODO"]} + use_cases = UseCases() + port_repository = use_cases.port_repository() + db = use_cases.db() + with db.session() as session: + return [p.model_dump_json() for p in port_repository.get_all_ports(session)] @app.get("/ports/{port_id}") async def get_port(port_id:int): - return {"port": "TODO"} + use_cases = UseCases() + port_repository = use_cases.port_repository() + db = use_cases.db() + with db.session() as session: + return port_repository.get_port_by_id(session,port_id) @app.get("/zones") async def list_zones(): From 102b604fcfdd8e8b68aceb86d75a156d80e6df2e Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 22:07:09 +0200 Subject: [PATCH 06/34] feat: add zones & zones/{id} endpoints --- backend/bloom/infra/repositories/repository_zone.py | 10 ++++++++++ backend/bloom/services/api.py | 12 ++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index 57ef53b8..1416d6cd 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -1,4 +1,5 @@ from contextlib import AbstractContextManager +from typing import Any, List, Union from bloom.domain.zone import Zone from bloom.infra.database import sql_model @@ -14,6 +15,15 @@ def __init__( ) -> Callable[..., AbstractContextManager]: self.session_factory = session_factory + def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: + return session.get(sql_model.Zone, zone_id) + + def get_all_zones(self, session: Session) -> List[Zone]: + q = session.query(sql_model.Zone) + if not q: + return [] + return [ZoneRepository.map_to_domain(entity) for entity in q] + def batch_create_zone(self, session: Session, zones: list[Zone]) -> list[Zone]: orm_list = [ZoneRepository.map_to_orm(zone) for zone in zones] session.add_all(orm_list) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 1bdd1496..d31aa3ee 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -69,11 +69,19 @@ async def get_port(port_id:int): @app.get("/zones") async def list_zones(): - return {"zones": ["TODO"]} + use_cases = UseCases() + zone_repository = use_cases.zone_repository() + db = use_cases.db() + with db.session() as session: + return zone_repository.get_all_zones(session) @app.get("/zones/{zones_id}") async def get_zone(zones_id:int): - return {"zone": "TODO"} + use_cases = UseCases() + zone_repository = use_cases.zone_repository() + db = use_cases.db() + with db.session() as session: + return zone_repository.get_zone_by_id(session,zones_id) @app.get("/statics/{zones}") async def get_statics_zones(): From e127f576d7dde7b40cf57d22c7098f464992e68f Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Sun, 12 May 2024 22:50:42 +0200 Subject: [PATCH 07/34] fix: fix load data to use bloom/tasks (loading positions missing) # Conflicts: # docker-compose-load-data.yaml --- .../init_script/load_positions_data.py | 2 +- .../bloom/tasks/load_spire_data_from_csv.py | 84 +++++++++++++++++++ docker-compose-load-data.yaml | 3 +- 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 backend/bloom/tasks/load_spire_data_from_csv.py diff --git a/backend/alembic/init_script/load_positions_data.py b/backend/alembic/init_script/load_positions_data.py index a3d176d8..140e1809 100644 --- a/backend/alembic/init_script/load_positions_data.py +++ b/backend/alembic/init_script/load_positions_data.py @@ -13,7 +13,7 @@ df = pd.read_csv( Path(settings.data_folder).joinpath("./spire_positions_subset.csv"), - sep="," + sep=";" ) df.to_sql("spire_vessel_positions", engine, if_exists="append", index=False) diff --git a/backend/bloom/tasks/load_spire_data_from_csv.py b/backend/bloom/tasks/load_spire_data_from_csv.py new file mode 100644 index 00000000..3968b1f1 --- /dev/null +++ b/backend/bloom/tasks/load_spire_data_from_csv.py @@ -0,0 +1,84 @@ +from pathlib import Path +from time import perf_counter + +import pandas as pd +from bloom.config import settings +from bloom.container import UseCases +from bloom.domain.spire_ais_data import SpireAisData +from bloom.infra.database.errors import DBException +from bloom.logger import logger +from pydantic import ValidationError +from shapely import wkb +import numpy as np + + +def map_to_domain(row: pd.Series) -> SpireAisData: + isna = row.isna() + + return SpireAisData( + spire_update_statement=row['spire_update_statement'], + vessel_ais_class=row['vessel_ais_class'], + vessel_flag=row['vessel_flag'], + vessel_name=row['vessel_name'], + vessel_callsign=row['vessel_callsign'], + vessel_timestamp=row['vessel_timestamp'], + vessel_update_timestamp=row['vessel_update_timestamp'], + vessel_ship_type=row['vessel_ship_type'], + vessel_sub_ship_type=row['vessel_sub_ship_type'], + vessel_mmsi=row['vessel_mmsi'], + vessel_imo=row['vessel_imo'], + vessel_width=row['vessel_width'], + vessel_length=row['vessel_length'], + position_accuracy=row['position_accuracy'], + position_collection_type=row['position_collection_type'], + position_course=row['position_course'], + position_heading=row['position_heading'], + position_latitude=row['position_latitude'], + position_longitude=row['position_longitude'], + position_maneuver=row['position_maneuver'], + position_navigational_status=row['position_navigational_status'], + position_rot=row['position_rot'], + position_speed=row['position_speed'], + position_timestamp=row['position_timestamp'], + position_update_timestamp=row['position_update_timestamp'], + voyage_destination=row['voyage_destination'], + voyage_draught=row['voyage_draught'], + voyage_eta=row['voyage_eta'], + voyage_timestamp=row['voyage_timestamp'], + voyage_update_timestamp=row['voyage_update_timestamp'], + created_at=row['created_at'], + ) + + +def run(csv_file_name: str): + use_cases = UseCases() + db = use_cases.db() + spire_ais_data_repository = use_cases.spire_ais_data_repository() + + total = 0 + try: + df = pd.read_csv(csv_file_name, sep=";") + df = df.rename(columns={}) + df=df.replace(np.NaN,None) + spire_ais_data = df.apply(map_to_domain, axis=1) + with db.session() as session: + spire_ais_data = spire_ais_data_repository.batch_create_ais_data(session=session, ais_list=list(spire_ais_data)) + session.commit() + total = len(spire_ais_data) + #print(spire_ais_data) + except ValidationError as e: + logger.error("Erreur de validation des données de bateau") + logger.error(e.errors()) + except DBException: + logger.error("Erreur d'insertion en base") + logger.info(f"{total} ais data créés") + + +if __name__ == "__main__": + time_start = perf_counter() + file_name = Path(settings.data_folder).joinpath("./spire_positions_subset.csv") + logger.info(f"DEBUT - Chargement des données AIS Spire depuis le fichier {file_name}") + run(file_name) + time_end = perf_counter() + duration = time_end - time_start + logger.info(f"FIN - Chargement des données AIS Spire en {duration:.2f}s") diff --git a/docker-compose-load-data.yaml b/docker-compose-load-data.yaml index 334357ef..c887e215 100644 --- a/docker-compose-load-data.yaml +++ b/docker-compose-load-data.yaml @@ -16,8 +16,9 @@ services: command: - -c - "/venv/bin/python3 backend/bloom/tasks/load_dim_vessel_from_csv.py && + /venv/bin/python3 backend/bloom/tasks/load_dim_zone_amp_from_csv.py && /venv/bin/python3 backend/bloom/tasks/load_dim_port_from_csv.py && - /venv/bin/python3 backend/bloom/tasks/compute_port_geometry_buffer.py" + /venv/bin/python3 backend/bloom/tasks/load_spire_data_from_csv.py" volumes: - ./:/project/ - ./data:/project/data From 872db80bfdc053fe7b9aefdfd07a5769f886c3f9 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Mon, 3 Jun 2024 22:32:26 +0200 Subject: [PATCH 08/34] feat: fix zones/{id} endpoint --- backend/bloom/domain/zone.py | 9 +++++++-- backend/bloom/infra/repositories/repository_zone.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/bloom/domain/zone.py b/backend/bloom/domain/zone.py index be395bda..cccc40dc 100644 --- a/backend/bloom/domain/zone.py +++ b/backend/bloom/domain/zone.py @@ -2,11 +2,16 @@ from typing import Union from pydantic import BaseModel, ConfigDict -from shapely import Geometry, Point +from shapely import Geometry, Point, MultiPolygon,Polygon +from shapely.geometry import mapping, shape class Zone(BaseModel): - model_config = ConfigDict(arbitrary_types_allowed=True) + model_config = ConfigDict(arbitrary_types_allowed=True, + json_encoders = { + #Point: lambda point: mapping(point) if point != None else None, + Geometry: lambda p: mapping(p), + },) id: Union[int, None] = None category: str sub_category: Union[str, None] = None diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index 1416d6cd..60ef51c0 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -16,7 +16,7 @@ def __init__( self.session_factory = session_factory def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: - return session.get(sql_model.Zone, zone_id) + return ZoneRepository.map_to_domain(session.get(sql_model.Zone, zone_id)) def get_all_zones(self, session: Session) -> List[Zone]: q = session.query(sql_model.Zone) From fb8197e15f603edaab57d6e9a368402d82aedc94 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Tue, 4 Jun 2024 00:24:51 +0200 Subject: [PATCH 09/34] feat: ajout serveur redis + cache system pour fastapi --- .env.template | 3 ++ backend/bloom/config.py | 4 +++ backend/bloom/services/api.py | 64 +++++++++++++++++++++++++---------- backend/poetry.lock | 31 ++++++++++++++++- backend/pyproject.toml | 1 + docker-compose.yaml | 17 ++++++++++ 6 files changed, 102 insertions(+), 18 deletions(-) diff --git a/.env.template b/.env.template index fab4d6dd..b6429282 100644 --- a/.env.template +++ b/.env.template @@ -9,6 +9,9 @@ POSTGRES_PASSWORD=bloom POSTGRES_DB=bloom_db POSTGRES_PORT=5432 API_PORT=8000 +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_CACHE_EXPIRATION=3600 SPIRE_TOKEN= SLACK_URL= diff --git a/backend/bloom/config.py b/backend/bloom/config.py index 254eedc2..4149de44 100644 --- a/backend/bloom/config.py +++ b/backend/bloom/config.py @@ -44,6 +44,10 @@ class Settings(BaseSettings): spire_token:str = Field(default='') data_folder:str=Field(default=str(Path(__file__).parent.parent.parent.joinpath('./data'))) db_url:str=Field(default='') + + redis_host: str = Field(default='localhost') + redis_port: int = Field(default=6379) + redis_cache_expiration: int = Field(default=3600) logging_level:str=Field( default="INFO", diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index d31aa3ee..945238de 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -1,21 +1,34 @@ from fastapi import FastAPI, APIRouter from fastapi import Request +import redis +import json from datetime import datetime from bloom.config import settings from bloom.container import UseCases from bloom.domain.vessel import Vessel +rd = redis.Redis(host=settings.redis_host, port=settings.redis_port, db=0) + app = FastAPI() @app.get("/vessels") async def list_vessels(): - use_cases = UseCases() - vessel_repository = use_cases.vessel_repository() - db = use_cases.db() - with db.session() as session: - return vessel_repository.get_vessels_list(session) + cache= rd.get(app.url_path_for('list_vessels')) + if cache: + return json.loads(cache) + else: + use_cases = UseCases() + vessel_repository = use_cases.vessel_repository() + db = use_cases.db() + with db.session() as session: + + json_data = [v.model_dump_json() + for v in vessel_repository.get_vessels_list(session)] + rd.set(app.url_path_for('list_vessels'), json.dumps(json_data)) + rd.expire(app.url_path_for('list_vessels'),settings.redis_cache_expiration) + return json_data @app.get("/vessels/{vessel_id}") async def get_vessel(vessel_id: int): @@ -52,12 +65,21 @@ async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segmen return {"segment": "TODO"} @app.get("/ports") -async def list_ports(): - use_cases = UseCases() - port_repository = use_cases.port_repository() - db = use_cases.db() - with db.session() as session: - return [p.model_dump_json() for p in port_repository.get_all_ports(session)] +async def list_ports(request:Request): + cache= rd.get(app.url_path_for('list_ports')) + if cache: + return json.loads(cache) + else: + use_cases = UseCases() + port_repository = use_cases.port_repository() + db = use_cases.db() + with db.session() as session: + json_data = [p.model_dump_json() + for p in port_repository.get_all_ports(session)] + rd.set(app.url_path_for('list_ports'), json.dumps(json_data)) + rd.expire(app.url_path_for('list_ports'),settings.redis_cache_expiration) + return json_data + @app.get("/ports/{port_id}") async def get_port(port_id:int): @@ -68,12 +90,20 @@ async def get_port(port_id:int): return port_repository.get_port_by_id(session,port_id) @app.get("/zones") -async def list_zones(): - use_cases = UseCases() - zone_repository = use_cases.zone_repository() - db = use_cases.db() - with db.session() as session: - return zone_repository.get_all_zones(session) +async def list_zones(): + cache= rd.get(app.url_path_for('list_zones')) + if cache: + return json.loads(cache) + else: + use_cases = UseCases() + zone_repository = use_cases.zone_repository() + db = use_cases.db() + with db.session() as session: + json_data = [z.model_dump_json() + for z in zone_repository.get_all_zones(session)] + rd.set(app.url_path_for('list_zones'), json.dumps(json_data)) + rd.expire(app.url_path_for('list_zones'),settings.redis_cache_expiration) + return json_data @app.get("/zones/{zones_id}") async def get_zone(zones_id:int): diff --git a/backend/poetry.lock b/backend/poetry.lock index 7b7d6fe8..87fac669 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -52,6 +52,17 @@ doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (>=0.23)"] +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + [[package]] name = "attrs" version = "23.2.0" @@ -2917,6 +2928,24 @@ files = [ [package.extras] full = ["numpy"] +[[package]] +name = "redis" +version = "5.0.4" +description = "Python client for Redis database and key-value store" +optional = false +python-versions = ">=3.7" +files = [ + {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, + {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} + +[package.extras] +hiredis = ["hiredis (>=1.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] + [[package]] name = "requests" version = "2.31.0" @@ -3933,4 +3962,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.9.7 || >3.9.7,<4.0" -content-hash = "740d50a18a924511385f56fa4158106fc29c78d82e29e36a614846144ea3b755" +content-hash = "6ea5343f496003ab742b90ad669be63a2314ae6b63f26dcba6806708d919a91b" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 395946d0..57637c2b 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -36,6 +36,7 @@ SQLAlchemy = "~2.0" pycountry = "23.12.11" fastapi = "^0.111.0" uvicorn = "^0.30.1" +redis = "^5.0.4" [tool.poetry.group.dev.dependencies] diff --git a/docker-compose.yaml b/docker-compose.yaml index 8d706a40..a9589324 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -26,6 +26,8 @@ services: <<: *common-env POSTGRES_PORT: 5432 STREAMLIT_SERVER_ADDRESS: ${STREAMLIT_SERVER_ADDRESS:-0.0.0.0} + REDIS_HOST: bloom-redis + REDIS_PORT: 6379 WATCHFILES_FORCE_POLLING: true ports: - ${API_PORT:-8000}:8000 @@ -34,6 +36,20 @@ services: depends_on: bloom-init: condition: service_completed_successfully + bloom-redis: + image: redis:7-alpine + container_name: bloom_redis + hostname: bloom-redis + restart: always + ports: + - ${REDIS_PORT:-6379}:6379 + environment: + - REDIS_PASSWORD=${REDIS_PASSWORD:-redis} + - REDIS_PORT=${REDIS_PORT:-6379} + volumes: + - bloom-redis:/data + networks: + - bloom_net bloom-postgres: container_name: postgres_bloom @@ -118,6 +134,7 @@ services: volumes: bloom-data: + bloom-redis: networks: bloom_net: From eef38cbc4f5c783bd8cc0fe34f3d759aff0b424a Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Tue, 4 Jun 2024 23:55:50 +0200 Subject: [PATCH 10/34] feat: add endpoints vessels/excursions/segments & vessels/positions/last --- backend/bloom/domain/segment.py | 9 +- backend/bloom/domain/vessel_last_position.py | 23 +++++ backend/bloom/domain/vessel_position.py | 8 +- .../repositories/repository_excursion.py | 21 ++++- .../infra/repositories/repository_segment.py | 94 ++++++++++++++++++- .../repository_vessel_position.py | 27 ++++++ backend/bloom/services/api.py | 55 ++++++++--- 7 files changed, 219 insertions(+), 18 deletions(-) create mode 100644 backend/bloom/domain/vessel_last_position.py diff --git a/backend/bloom/domain/segment.py b/backend/bloom/domain/segment.py index e391e8a6..9c706a23 100644 --- a/backend/bloom/domain/segment.py +++ b/backend/bloom/domain/segment.py @@ -2,11 +2,16 @@ from typing import Union from pydantic import BaseModel, ConfigDict -from shapely import Point +from shapely import Point,Geometry +from shapely.geometry import mapping, shape class Segment(BaseModel): - model_config = ConfigDict(arbitrary_types_allowed=True) + model_config = ConfigDict(arbitrary_types_allowed=True, + json_encoders = { + Geometry: lambda geometry: mapping(geometry), + }, + ) id: Union[int, None] = None excursion_id: int timestamp_start: Union[datetime, None] = None diff --git a/backend/bloom/domain/vessel_last_position.py b/backend/bloom/domain/vessel_last_position.py new file mode 100644 index 00000000..525d9af5 --- /dev/null +++ b/backend/bloom/domain/vessel_last_position.py @@ -0,0 +1,23 @@ +from datetime import datetime + +from pydantic import BaseModel, ConfigDict +from shapely import Geometry, Point +from shapely.geometry import mapping, shape +from bloom.domain.vessel import Vessel +from bloom.domain.port import Port + +from typing import Union + + +class VesselLastPosition(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True, + json_encoders = { + Geometry: lambda p: mapping(p), + },) + vessel: Vessel = None + excursion_id: Union[int, None] = None + position: Union[Point, None] = None + timestamp: Union[datetime, None] = None + heading: Union[float, None] = None + speed: Union[float, None] = None + arrival_port: Union[Port, None] = None diff --git a/backend/bloom/domain/vessel_position.py b/backend/bloom/domain/vessel_position.py index 04548ab7..b1ebabbf 100644 --- a/backend/bloom/domain/vessel_position.py +++ b/backend/bloom/domain/vessel_position.py @@ -1,13 +1,17 @@ from datetime import datetime from pydantic import BaseModel, ConfigDict -from shapely import Point +from shapely import Geometry, Point +from shapely.geometry import mapping, shape from typing import Union class VesselPosition(BaseModel): - model_config = ConfigDict(arbitrary_types_allowed=True) + model_config = ConfigDict(arbitrary_types_allowed=True, + json_encoders = { + Geometry: lambda p: mapping(p), + },) id: Union[int, None] = None timestamp: datetime diff --git a/backend/bloom/infra/repositories/repository_excursion.py b/backend/bloom/infra/repositories/repository_excursion.py index f42deebf..85070431 100644 --- a/backend/bloom/infra/repositories/repository_excursion.py +++ b/backend/bloom/infra/repositories/repository_excursion.py @@ -1,5 +1,5 @@ from contextlib import AbstractContextManager -from typing import Union +from typing import Any, List, Union import pandas as pd from dependency_injector.providers import Callable @@ -34,6 +34,25 @@ def get_param_from_last_excursion(self, session: Session, vessel_id: int) -> Uni return None return {"arrival_port_id": result.arrival_port_id, "arrival_position": result.arrival_position} + def get_excursions_by_vessel_id(self, session: Session, vessel_id: int) -> List[Excursion]: + """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" + stmt = select(sql_model.Excursion).where(sql_model.Excursion.vessel_id == vessel_id) + result = session.execute(stmt).scalars() + if result is None: + return [] + return [ ExcursionRepository.map_to_domain(r) for r in result] + + def get_vessel_excursion_by_id(self, session: Session, vessel_id: int, excursion_id:int) -> Union[Excursion,None]: + """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" + stmt = select(sql_model.Excursion).where( (sql_model.Excursion.vessel_id == vessel_id ) + & (sql_model.Excursion.id == excursion_id )) + result = session.execute(stmt) + if result is None: + return None + return [ ExcursionRepository.map_to_domain(r) for r in result.scalars()][0] + + + def get_excursion_by_id(self, session: Session, id: int) -> Union[Excursion, None]: """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" sql = select(sql_model.Excursion).where(sql_model.Excursion.id == id) diff --git a/backend/bloom/infra/repositories/repository_segment.py b/backend/bloom/infra/repositories/repository_segment.py index c4558f95..51f1c091 100644 --- a/backend/bloom/infra/repositories/repository_segment.py +++ b/backend/bloom/infra/repositories/repository_segment.py @@ -1,5 +1,6 @@ from contextlib import AbstractContextManager from datetime import datetime +from typing import Any, List, Union import pandas as pd from dependency_injector.providers import Callable @@ -10,9 +11,11 @@ from sqlalchemy.orm import Session from bloom.domain.segment import Segment +from bloom.domain.vessel_last_position import VesselLastPosition from bloom.domain.zone import Zone from bloom.infra.database import sql_model from bloom.infra.repositories.repository_zone import ZoneRepository +from bloom.infra.repositories.repository_vessel import VesselRepository class SegmentRepository: @@ -35,9 +38,96 @@ def get_segments_by_excursions(self, session: Session, id: int) -> pd.DataFrame: df = pd.DataFrame(q, columns=["segment_duration", "in_amp_zone", "in_territorial_waters", "in_costal_waters"]) return df + def get_all_vessels_last_position(self, session: Session) -> List[Segment]: + stmt = select( + sql_model.Vessel, + sql_model.Segment.excursion_id, + sql_model.Segment.end_position, + sql_model.Segment.timestamp_end, + sql_model.Segment.heading_at_end, + sql_model.Segment.speed_at_end, + sql_model.Excursion.arrival_port_id + ).join( + sql_model.Vessel, + sql_model.Excursion.vessel_id == sql_model.Vessel.id + ).filter( + sql_model.Segment.last_vessel_segment == True + ) + result = session.execute(stmt) + if result is not None : + return [VesselLastPosition( + vessel=VesselRepository.map_to_domain(record[0]), + excursion_id=record[1], + position=to_shape(record[2]), + timestamp=record[3], + heading=record[4], + speed=record[5], + arrival=record[6], + ) for record in result] + else: + return [] + + def get_vessel_last_position(self, session: Session,vessel_id:int) -> List[Segment]: + stmt = select( + sql_model.Vessel, + sql_model.Segment.excursion_id, + sql_model.Segment.end_position, + sql_model.Segment.timestamp_end, + sql_model.Segment.heading_at_end, + sql_model.Segment.speed_at_end, + sql_model.Excursion.arrival_port_id + ).join( + sql_model.Vessel, + sql_model.Excursion.vessel_id == sql_model.Vessel.id + ).filter( + sql_model.Segment.last_vessel_segment == True, + sql_model.Vessel.id == vessel_id, + ) + result = session.execute(stmt) + if result is not None: + return [VesselLastPosition( + vessel=VesselRepository.map_to_domain(record[0]), + excursion_id=record[1], + position=to_shape(record[2]), + timestamp=record[3], + heading=record[4], + speed=record[5], + arrival_port_id=record[6], + ) for record in result][0] + else: + return None + + def list_vessel_excursion_segments(self,session,vessel_id:int,excursions_id: int) -> List[Segment]: + stmt = select( + sql_model.Segment + ).join( + sql_model.Excursion, + sql_model.Segment.excursion_id == sql_model.Excursion.id + ).where( sql_model.Segment.excursion_id == excursions_id, + sql_model.Excursion.vessel_id == vessel_id) + result = session.execute(stmt) + if result is not None : + return [ SegmentRepository.map_to_domain(record) for record in result.scalars()] + else: + return [] + + def get_vessel_excursion_segment_by_id(self,session,vessel_id:int,excursions_id: int, segment_id:int) -> Union[Segment,None]: + stmt = select( + sql_model.Segment + ).join( + sql_model.Excursion, + sql_model.Segment.excursion_id == sql_model.Excursion.id + ).where( sql_model.Segment.excursion_id == excursions_id, + sql_model.Excursion.vessel_id == vessel_id, + sql_model.Segment.id == segment_id) + result = session.execute(stmt) + if result is not None : + return [ SegmentRepository.map_to_domain(record) for record in result.scalars()][0] + else: + return [] + def get_last_vessel_id_segments(self, session: Session) -> pd.DataFrame: stmt = select( - sql_model.Vessel.id, sql_model.Segment.excursion_id, sql_model.Segment.end_position, sql_model.Segment.timestamp_end, @@ -172,4 +262,4 @@ def map_to_orm(segment: Segment) -> sql_model.Segment: last_vessel_segment=segment.last_vessel_segment, created_at=segment.created_at, updated_at=segment.updated_at - ) + ) \ No newline at end of file diff --git a/backend/bloom/infra/repositories/repository_vessel_position.py b/backend/bloom/infra/repositories/repository_vessel_position.py index d7793a5b..65e340ac 100644 --- a/backend/bloom/infra/repositories/repository_vessel_position.py +++ b/backend/bloom/infra/repositories/repository_vessel_position.py @@ -1,4 +1,5 @@ from datetime import datetime +from typing import Any, List, Union import pandas as pd from dependency_injector.providers import Callable @@ -10,6 +11,8 @@ from bloom.domain.vessel_position import VesselPosition from bloom.infra.database import sql_model +from bloom.logger import logger + class VesselPositionRepository: def __init__(self, session_factory: Callable) -> None: @@ -26,6 +29,30 @@ def batch_create_vessel_position(self, session: Session, vessel_positions: list[ session.add_all(orm_list) return [VesselPositionRepository.map_to_domain(orm) for orm in orm_list] + def get_all_vessel_last_positions(self, session: Session) -> List[VesselPosition]: + + stmt=select(sql_model.VesselPosition)\ + .order_by(sql_model.VesselPosition.timestamp.desc())\ + .group_by(sql_model.VesselPosition.vessel_id) + result = session.execute(stmt).scalars() + #logger.info(type(result)) + if result is not None : + return [VesselPositionRepository.map_to_domain(record) for record in result] + else: + return [] + + def get_vessel_positions(self, session: Session, vessel_id:int, + start:datetime=datetime.now(), + end:datetime=None) -> List[VesselPosition]: + + stmt=select(sql_model.VesselPosition).filter_by(vessel_id=vessel_id).order_by(sql_model.VesselPosition.timestamp.desc()) + result = session.execute(stmt).scalars() + #logger.info(type(result)) + if result is not None : + return [VesselPositionRepository.map_to_domain(record) for record in result] + else: + return [] + def get_positions_with_vessel_created_updated_after(self, session: Session, created_updated_after: datetime) -> pd.DataFrame: stmt = select(sql_model.VesselPosition.id, sql_model.VesselPosition.timestamp, diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 945238de..94c0ce1c 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -3,14 +3,15 @@ import redis import json -from datetime import datetime - from bloom.config import settings from bloom.container import UseCases from bloom.domain.vessel import Vessel rd = redis.Redis(host=settings.redis_host, port=settings.redis_port, db=0) +from datetime import datetime + + app = FastAPI() @app.get("/vessels") @@ -38,31 +39,55 @@ async def get_vessel(vessel_id: int): with db.session() as session: return vessel_repository.get_vessel_by_id(session,vessel_id) -@app.get("/vessels/{vessel_id}/positions") -async def list_vessel_positions(vessel_id: int, start: datetime = datetime.now(), end:datetime=None): - return {"positions": ["TODO"]} +@app.get("/vessels/all/positions/last") +async def list_all_vessel_last_position(): + use_cases = UseCases() + segment_repository = use_cases.segment_repository() + db = use_cases.db() + with db.session() as session: + return segment_repository.get_all_vessels_last_position(session) @app.get("/vessels/{vessel_id}/positions/last") -async def list_vessel_position_last(vessel_id: int, date:datetime = datetime.now()): - return {"position": ["TODO"]} +async def get_vessel_last_position(vessel_id: int): + use_cases = UseCases() + segment_repository = use_cases.segment_repository() + db = use_cases.db() + with db.session() as session: + return segment_repository.get_vessel_last_position(session,vessel_id) @app.get("/vessels/{vessel_id}/excursions") async def list_vessel_excursions(vessel_id: int): - return {"excursions": ["TODO"]} + use_cases = UseCases() + excursion_repository = use_cases.excursion_repository() + db = use_cases.db() + with db.session() as session: + return excursion_repository.get_excursions_by_vessel_id(session,vessel_id) @app.get("/vessels/{vessel_id}/excursions/{excursions_id}") async def get_vessel_excursion(vessel_id: int,excursions_id: int): - return {"excursion": "TODO"} + use_cases = UseCases() + excursion_repository = use_cases.excursion_repository() + db = use_cases.db() + with db.session() as session: + return excursion_repository.get_vessel_excursion_by_id(session,vessel_id,excursions_id) @app.get("/vessels/{vessel_id}/excursions/{excursions_id}/segments") async def list_vessel_excursion_segments(vessel_id: int,excursions_id: int): - return {"segments": ["TODO"]} + use_cases = UseCases() + segment_repository = use_cases.segment_repository() + db = use_cases.db() + with db.session() as session: + return segment_repository.list_vessel_excursion_segments(session,vessel_id,excursions_id) @app.get("/vessels/{vessel_id}/excursions/{excursions_id}/segments/{segment_id}") async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segment_id:int): - return {"segment": "TODO"} + use_cases = UseCases() + segment_repository = use_cases.segment_repository() + db = use_cases.db() + with db.session() as session: + return segment_repository.get_vessel_excursion_segment_by_id(session,vessel_id,excursions_id,segment_id) @app.get("/ports") async def list_ports(request:Request): @@ -89,6 +114,14 @@ async def get_port(port_id:int): with db.session() as session: return port_repository.get_port_by_id(session,port_id) +@app.get("/vessels/all/positions/last") +async def list_vessel_positions(vessel_id: int, date:datetime=datetime.now()): + use_cases = UseCases() + vessel_position_repository = use_cases.vessel_position_repository() + db = use_cases.db() + with db.session() as session: + return vessel_position_repository.get_vessel_positions(session,vessel_id) + @app.get("/zones") async def list_zones(): cache= rd.get(app.url_path_for('list_zones')) From 456807b9dd69764ba636d9f9eb2795480f558679 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Tue, 4 Jun 2024 23:57:24 +0200 Subject: [PATCH 11/34] feat: add docker/up_with_data.sh --- docker/up_with_data.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docker/up_with_data.sh diff --git a/docker/up_with_data.sh b/docker/up_with_data.sh new file mode 100644 index 00000000..2577ab6f --- /dev/null +++ b/docker/up_with_data.sh @@ -0,0 +1,2 @@ +cd "$(dirname "$0")"/.. +docker compose -f docker-compose.yaml -f docker-compose-load-data.yaml up || pause \ No newline at end of file From 1e9d68933f0f9326330733ced1f7b7de8d94d793 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Wed, 5 Jun 2024 00:35:39 +0200 Subject: [PATCH 12/34] =?UTF-8?q?revert:=20modif=20non=20souhait=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/bloom/infra/repositories/repository_segment.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/bloom/infra/repositories/repository_segment.py b/backend/bloom/infra/repositories/repository_segment.py index 51f1c091..05d6839d 100644 --- a/backend/bloom/infra/repositories/repository_segment.py +++ b/backend/bloom/infra/repositories/repository_segment.py @@ -128,6 +128,7 @@ def get_vessel_excursion_segment_by_id(self,session,vessel_id:int,excursions_id: def get_last_vessel_id_segments(self, session: Session) -> pd.DataFrame: stmt = select( + sql_model.Vessel.id, sql_model.Segment.excursion_id, sql_model.Segment.end_position, sql_model.Segment.timestamp_end, From 11f12daca4a6dac15b1d0e076fadfec5eeec534d Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 12:44:57 +0200 Subject: [PATCH 13/34] feat: ajout cache/all/flush + noache parameter pour zones et ports --- backend/bloom/services/api.py | 29 +++++++++++++++++++++++------ docker-compose-load-data.yaml | 3 ++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 94c0ce1c..cd660ad9 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -6,14 +6,21 @@ from bloom.config import settings from bloom.container import UseCases from bloom.domain.vessel import Vessel +from bloom.logger import logger rd = redis.Redis(host=settings.redis_host, port=settings.redis_port, db=0) from datetime import datetime +import time app = FastAPI() +@app.get("/cache/all/flush") +async def cache_all_flush(request:Request): + rd.flushall() + return {"code":0} + @app.get("/vessels") async def list_vessels(): cache= rd.get(app.url_path_for('list_vessels')) @@ -90,10 +97,14 @@ async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segmen return segment_repository.get_vessel_excursion_segment_by_id(session,vessel_id,excursions_id,segment_id) @app.get("/ports") -async def list_ports(request:Request): +async def list_ports(request:Request,nocache:bool=0): cache= rd.get(app.url_path_for('list_ports')) - if cache: - return json.loads(cache) + start = time.time() + if cache and not nocache: + logger.debug(f"{app.url_path_for('list_ports')} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{app.url_path_for('list_ports')} elapsed Time: {time.time()-start}") + return payload else: use_cases = UseCases() port_repository = use_cases.port_repository() @@ -103,6 +114,7 @@ async def list_ports(request:Request): for p in port_repository.get_all_ports(session)] rd.set(app.url_path_for('list_ports'), json.dumps(json_data)) rd.expire(app.url_path_for('list_ports'),settings.redis_cache_expiration) + logger.debug(f"{app.url_path_for('list_ports')} elapsed Time: {time.time()-start}") return json_data @@ -123,10 +135,14 @@ async def list_vessel_positions(vessel_id: int, date:datetime=datetime.now()): return vessel_position_repository.get_vessel_positions(session,vessel_id) @app.get("/zones") -async def list_zones(): +async def list_zones(request:Request,nocache:bool=0): cache= rd.get(app.url_path_for('list_zones')) - if cache: - return json.loads(cache) + start = time.time() + if cache and not nocache: + logger.debug(f"{app.url_path_for('list_zones')} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{app.url_path_for('list_zones')} elapsed Time: {time.time()-start}") + return payload else: use_cases = UseCases() zone_repository = use_cases.zone_repository() @@ -136,6 +152,7 @@ async def list_zones(): for z in zone_repository.get_all_zones(session)] rd.set(app.url_path_for('list_zones'), json.dumps(json_data)) rd.expire(app.url_path_for('list_zones'),settings.redis_cache_expiration) + logger.debug(f"{app.url_path_for('list_zones')} elapsed Time: {time.time()-start}") return json_data @app.get("/zones/{zones_id}") diff --git a/docker-compose-load-data.yaml b/docker-compose-load-data.yaml index c887e215..490923db 100644 --- a/docker-compose-load-data.yaml +++ b/docker-compose-load-data.yaml @@ -18,7 +18,8 @@ services: - "/venv/bin/python3 backend/bloom/tasks/load_dim_vessel_from_csv.py && /venv/bin/python3 backend/bloom/tasks/load_dim_zone_amp_from_csv.py && /venv/bin/python3 backend/bloom/tasks/load_dim_port_from_csv.py && - /venv/bin/python3 backend/bloom/tasks/load_spire_data_from_csv.py" + /venv/bin/python3 backend/bloom/tasks/load_spire_data_from_csv.py && + /venv/bin/python3 backend/bloom/tasks/clean_positions.py" volumes: - ./:/project/ - ./data:/project/data From 3035ae5f37796709518df97630ba990ea975d7f3 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 13:25:57 +0200 Subject: [PATCH 14/34] feat: api add endpoint /zones/by-category/{category} --- .../infra/repositories/repository_zone.py | 6 +++++ backend/bloom/services/api.py | 26 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index 60ef51c0..04b4a668 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -24,6 +24,12 @@ def get_all_zones(self, session: Session) -> List[Zone]: return [] return [ZoneRepository.map_to_domain(entity) for entity in q] + def get_all_zones_by_category(self, session: Session,category:str) -> List[Zone]: + q = session.query(sql_model.Zone).where(sql_model.Zone.category == category) + if not q: + return [] + return [ZoneRepository.map_to_domain(entity) for entity in q] + def batch_create_zone(self, session: Session, zones: list[Zone]) -> list[Zone]: orm_list = [ZoneRepository.map_to_orm(zone) for zone in zones] session.add_all(orm_list) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index cd660ad9..2a298be0 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -154,7 +154,29 @@ async def list_zones(request:Request,nocache:bool=0): rd.expire(app.url_path_for('list_zones'),settings.redis_cache_expiration) logger.debug(f"{app.url_path_for('list_zones')} elapsed Time: {time.time()-start}") return json_data - + +@app.get("/zones/by-category/{category}") +async def get_zone_all_by_category(category:str="amp",nocache:bool=0): + endpoint=f"/zones/by-category/{category}" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload + else: + use_cases = UseCases() + zone_repository = use_cases.zone_repository() + db = use_cases.db() + with db.session() as session: + json_data = [z.model_dump_json() + for z in zone_repository.get_all_zones_by_category(session,category)] + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return json_data + @app.get("/zones/{zones_id}") async def get_zone(zones_id:int): use_cases = UseCases() @@ -163,6 +185,8 @@ async def get_zone(zones_id:int): with db.session() as session: return zone_repository.get_zone_by_id(session,zones_id) + + @app.get("/statics/{zones}") async def get_statics_zones(): return {} From eace9e50db9e6d87e249b8276b4898f27920aa29 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 13:26:23 +0200 Subject: [PATCH 15/34] feat: + data loading + segments & excursions creation --- docker-compose-load-data.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker-compose-load-data.yaml b/docker-compose-load-data.yaml index 490923db..92c7e369 100644 --- a/docker-compose-load-data.yaml +++ b/docker-compose-load-data.yaml @@ -19,7 +19,8 @@ services: /venv/bin/python3 backend/bloom/tasks/load_dim_zone_amp_from_csv.py && /venv/bin/python3 backend/bloom/tasks/load_dim_port_from_csv.py && /venv/bin/python3 backend/bloom/tasks/load_spire_data_from_csv.py && - /venv/bin/python3 backend/bloom/tasks/clean_positions.py" + /venv/bin/python3 backend/bloom/tasks/clean_positions.py --batch-time 100000 && + /venv/bin/python3 python bloom/tasks/create_update_excursions_segments.py" volumes: - ./:/project/ - ./data:/project/data From fd5a9dac1f425ab5bb0046e5653134842f85cd76 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 13:53:19 +0200 Subject: [PATCH 16/34] =?UTF-8?q?feat:=20ajout=20endpoint=20/zones/all/cat?= =?UTF-8?q?egories=20pour=20avoir=20la=20liste=20des=20cat=C3=A9gories=20d?= =?UTF-8?q?isponibles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/repositories/repository_zone.py | 16 ++++++++ backend/bloom/services/api.py | 37 +++++++++++++++---- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index 04b4a668..885ff233 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -2,6 +2,7 @@ from typing import Any, List, Union from bloom.domain.zone import Zone +from bloom.domain.zone_category import ZoneCategory from bloom.infra.database import sql_model from dependency_injector.providers import Callable from geoalchemy2.shape import from_shape, to_shape @@ -20,10 +21,19 @@ def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: def get_all_zones(self, session: Session) -> List[Zone]: q = session.query(sql_model.Zone) + q=session.execute(q).scalars() if not q: return [] return [ZoneRepository.map_to_domain(entity) for entity in q] + def get_all_zone_categories(self, session: Session) -> List[Zone]: + q = session.query(sql_model.Zone.category, + sql_model.Zone.sub_category).distinct() + q=session.execute(q) + if not q: + return [] + return [ZoneRepository.map_to_domain(ZoneCategory(category=cat,sub_category=sub)) for cat,sub in q] + def get_all_zones_by_category(self, session: Session,category:str) -> List[Zone]: q = session.query(sql_model.Zone).where(sql_model.Zone.category == category) if not q: @@ -60,3 +70,9 @@ def map_to_domain(zone: sql_model.Zone) -> Zone: json_data=zone.json_data, created_at=zone.created_at, ) + @staticmethod + def map_to_domain(category: ZoneCategory) -> Zone: + return ZoneCategory( + category=category.category, + sub_category=category.sub_category + ) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 2a298be0..580a4ceb 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -136,12 +136,13 @@ async def list_vessel_positions(vessel_id: int, date:datetime=datetime.now()): @app.get("/zones") async def list_zones(request:Request,nocache:bool=0): - cache= rd.get(app.url_path_for('list_zones')) + endpoint=f"/zones" + cache= rd.get(endpoint) start = time.time() if cache and not nocache: - logger.debug(f"{app.url_path_for('list_zones')} cached ({settings.redis_cache_expiration})s") + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") payload=json.loads(cache) - logger.debug(f"{app.url_path_for('list_zones')} elapsed Time: {time.time()-start}") + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") return payload else: use_cases = UseCases() @@ -150,11 +151,33 @@ async def list_zones(request:Request,nocache:bool=0): with db.session() as session: json_data = [z.model_dump_json() for z in zone_repository.get_all_zones(session)] - rd.set(app.url_path_for('list_zones'), json.dumps(json_data)) - rd.expire(app.url_path_for('list_zones'),settings.redis_cache_expiration) - logger.debug(f"{app.url_path_for('list_zones')} elapsed Time: {time.time()-start}") + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") return json_data - + +@app.get("/zones/all/categories") +async def list_zone_categories(request:Request,nocache:bool=0): + endpoint=f"/zones/all/categories" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload + else: + use_cases = UseCases() + zone_repository = use_cases.zone_repository() + db = use_cases.db() + with db.session() as session: + json_data = [z.model_dump_json() + for z in zone_repository.get_all_zone_categories(session)] + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return json_data + @app.get("/zones/by-category/{category}") async def get_zone_all_by_category(category:str="amp",nocache:bool=0): endpoint=f"/zones/by-category/{category}" From 62bd8f7c5ebcf9da9021c987ac874495f21cbebc Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 13:59:07 +0200 Subject: [PATCH 17/34] fix: endpoint excursions --- backend/bloom/domain/excursion.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/bloom/domain/excursion.py b/backend/bloom/domain/excursion.py index f331bf65..51aebcbd 100644 --- a/backend/bloom/domain/excursion.py +++ b/backend/bloom/domain/excursion.py @@ -2,11 +2,16 @@ from typing import Union from pydantic import BaseModel, ConfigDict -from shapely import Point +from shapely import Geometry, Point, MultiPolygon,Polygon +from shapely.geometry import mapping, shape class Excursion(BaseModel): - model_config = ConfigDict(arbitrary_types_allowed=True) + model_config = ConfigDict(arbitrary_types_allowed=True, + json_encoders = { + #Point: lambda point: mapping(point) if point != None else None, + Geometry: lambda p: mapping(p), + },) id: Union[int, None] = None vessel_id: int departure_port_id: Union[int, None] = None From 475d6679c7ee1518e9cfb866201eb7e8f4bd4208 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 14:17:20 +0200 Subject: [PATCH 18/34] fix: endpoint /vessels/{vessil_id}/excursions/{excursion_id} --- backend/bloom/infra/repositories/repository_excursion.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_excursion.py b/backend/bloom/infra/repositories/repository_excursion.py index 85070431..22fd88d2 100644 --- a/backend/bloom/infra/repositories/repository_excursion.py +++ b/backend/bloom/infra/repositories/repository_excursion.py @@ -46,10 +46,10 @@ def get_vessel_excursion_by_id(self, session: Session, vessel_id: int, excursion """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" stmt = select(sql_model.Excursion).where( (sql_model.Excursion.vessel_id == vessel_id ) & (sql_model.Excursion.id == excursion_id )) - result = session.execute(stmt) - if result is None: + result = session.execute(stmt).fetchone() + if not result : return None - return [ ExcursionRepository.map_to_domain(r) for r in result.scalars()][0] + return ExcursionRepository.map_to_domain(result[0]) From 4fe80eacdd78fbabc1979cebb6ab02d33f910d5d Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 14:22:12 +0200 Subject: [PATCH 19/34] fix: nocache=false au lieu de nocache=0 --- backend/bloom/services/api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 580a4ceb..391002ad 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -97,7 +97,7 @@ async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segmen return segment_repository.get_vessel_excursion_segment_by_id(session,vessel_id,excursions_id,segment_id) @app.get("/ports") -async def list_ports(request:Request,nocache:bool=0): +async def list_ports(request:Request,nocache:bool=False): cache= rd.get(app.url_path_for('list_ports')) start = time.time() if cache and not nocache: @@ -135,7 +135,7 @@ async def list_vessel_positions(vessel_id: int, date:datetime=datetime.now()): return vessel_position_repository.get_vessel_positions(session,vessel_id) @app.get("/zones") -async def list_zones(request:Request,nocache:bool=0): +async def list_zones(request:Request,nocache:bool=False): endpoint=f"/zones" cache= rd.get(endpoint) start = time.time() @@ -157,7 +157,7 @@ async def list_zones(request:Request,nocache:bool=0): return json_data @app.get("/zones/all/categories") -async def list_zone_categories(request:Request,nocache:bool=0): +async def list_zone_categories(request:Request,nocache:bool=False): endpoint=f"/zones/all/categories" cache= rd.get(endpoint) start = time.time() @@ -179,7 +179,7 @@ async def list_zone_categories(request:Request,nocache:bool=0): return json_data @app.get("/zones/by-category/{category}") -async def get_zone_all_by_category(category:str="amp",nocache:bool=0): +async def get_zone_all_by_category(category:str="amp",nocache:bool=False): endpoint=f"/zones/by-category/{category}" cache= rd.get(endpoint) start = time.time() From cc6f5a315d271b91b56e74cc6e9dfd7a0c8cfdf9 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 14:47:23 +0200 Subject: [PATCH 20/34] fix: /vessels/all/positions/last --- .../infra/repositories/repository_segment.py | 3 + backend/bloom/services/api.py | 60 ++++++++++++------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_segment.py b/backend/bloom/infra/repositories/repository_segment.py index 05d6839d..564f25c3 100644 --- a/backend/bloom/infra/repositories/repository_segment.py +++ b/backend/bloom/infra/repositories/repository_segment.py @@ -50,6 +50,9 @@ def get_all_vessels_last_position(self, session: Session) -> List[Segment]: ).join( sql_model.Vessel, sql_model.Excursion.vessel_id == sql_model.Vessel.id + ).join( + sql_model.Segment, + sql_model.Segment.excursion_id == sql_model.Excursion.id ).filter( sql_model.Segment.last_vessel_segment == True ) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 391002ad..5d66a39b 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -47,20 +47,48 @@ async def get_vessel(vessel_id: int): return vessel_repository.get_vessel_by_id(session,vessel_id) @app.get("/vessels/all/positions/last") -async def list_all_vessel_last_position(): - use_cases = UseCases() - segment_repository = use_cases.segment_repository() - db = use_cases.db() - with db.session() as session: - return segment_repository.get_all_vessels_last_position(session) +async def list_all_vessel_last_position(nocache:bool=False): + endpoint=f"/vessels/all/positions/last" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload + else: + use_cases = UseCases() + segment_repository = use_cases.segment_repository() + db = use_cases.db() + with db.session() as session: + json_data = [p.model_dump_json() + for p in segment_repository.get_all_vessels_last_position(session)] + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return json_data @app.get("/vessels/{vessel_id}/positions/last") -async def get_vessel_last_position(vessel_id: int): - use_cases = UseCases() - segment_repository = use_cases.segment_repository() - db = use_cases.db() - with db.session() as session: - return segment_repository.get_vessel_last_position(session,vessel_id) +async def get_vessel_last_position(vessel_id: int, nocache:bool=False): + endpoint=f"/vessels/{vessel_id}/positions/last" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload + else: + use_cases = UseCases() + segment_repository = use_cases.segment_repository() + db = use_cases.db() + with db.session() as session: + json_data = [p.model_dump_json() + for p in segment_repository.get_vessel_last_position(session)] + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return json_data @app.get("/vessels/{vessel_id}/excursions") async def list_vessel_excursions(vessel_id: int): @@ -126,14 +154,6 @@ async def get_port(port_id:int): with db.session() as session: return port_repository.get_port_by_id(session,port_id) -@app.get("/vessels/all/positions/last") -async def list_vessel_positions(vessel_id: int, date:datetime=datetime.now()): - use_cases = UseCases() - vessel_position_repository = use_cases.vessel_position_repository() - db = use_cases.db() - with db.session() as session: - return vessel_position_repository.get_vessel_positions(session,vessel_id) - @app.get("/zones") async def list_zones(request:Request,nocache:bool=False): endpoint=f"/zones" From 6923b8eced888028905bdcd32de0aafad01048d1 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 14:48:13 +0200 Subject: [PATCH 21/34] feat: add redis cache for endpoints /vessels /vessels/{vessel_id}/excursions --- backend/bloom/services/api.py | 55 +++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 5d66a39b..9101cc4d 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -22,10 +22,15 @@ async def cache_all_flush(request:Request): return {"code":0} @app.get("/vessels") -async def list_vessels(): - cache= rd.get(app.url_path_for('list_vessels')) - if cache: - return json.loads(cache) +async def list_vessels(nocache:bool=False): + endpoint=f"/vessels" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload else: use_cases = UseCases() vessel_repository = use_cases.vessel_repository() @@ -34,8 +39,8 @@ async def list_vessels(): json_data = [v.model_dump_json() for v in vessel_repository.get_vessels_list(session)] - rd.set(app.url_path_for('list_vessels'), json.dumps(json_data)) - rd.expire(app.url_path_for('list_vessels'),settings.redis_cache_expiration) + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) return json_data @app.get("/vessels/{vessel_id}") @@ -91,12 +96,25 @@ async def get_vessel_last_position(vessel_id: int, nocache:bool=False): return json_data @app.get("/vessels/{vessel_id}/excursions") -async def list_vessel_excursions(vessel_id: int): - use_cases = UseCases() - excursion_repository = use_cases.excursion_repository() - db = use_cases.db() - with db.session() as session: - return excursion_repository.get_excursions_by_vessel_id(session,vessel_id) +async def list_vessel_excursions(vessel_id: int, nocache:bool=False): + endpoint=f"/vessels/{vessel_id}/excursions" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload + else: + use_cases = UseCases() + excursion_repository = use_cases.excursion_repository() + db = use_cases.db() + with db.session() as session: + json_data = [p.model_dump_json() + for p in excursion_repository.get_excursions_by_vessel_id(session)] + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") @app.get("/vessels/{vessel_id}/excursions/{excursions_id}") @@ -126,12 +144,13 @@ async def get_vessel_excursion_segment(vessel_id: int,excursions_id: int, segmen @app.get("/ports") async def list_ports(request:Request,nocache:bool=False): - cache= rd.get(app.url_path_for('list_ports')) + endpoint=f"/ports" + cache= rd.get(endpoint) start = time.time() if cache and not nocache: - logger.debug(f"{app.url_path_for('list_ports')} cached ({settings.redis_cache_expiration})s") + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") payload=json.loads(cache) - logger.debug(f"{app.url_path_for('list_ports')} elapsed Time: {time.time()-start}") + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") return payload else: use_cases = UseCases() @@ -140,9 +159,9 @@ async def list_ports(request:Request,nocache:bool=False): with db.session() as session: json_data = [p.model_dump_json() for p in port_repository.get_all_ports(session)] - rd.set(app.url_path_for('list_ports'), json.dumps(json_data)) - rd.expire(app.url_path_for('list_ports'),settings.redis_cache_expiration) - logger.debug(f"{app.url_path_for('list_ports')} elapsed Time: {time.time()-start}") + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") return json_data From 7c3df5aa1029cf4b55a9adeae235c087469cb74d Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 15:12:04 +0200 Subject: [PATCH 22/34] fix: endpoint /vessels/all|id/positions/last format string => json --- .../infra/repositories/repository_segment.py | 28 +++++++++++-------- backend/bloom/services/api.py | 6 ++-- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_segment.py b/backend/bloom/infra/repositories/repository_segment.py index 564f25c3..612fa5a0 100644 --- a/backend/bloom/infra/repositories/repository_segment.py +++ b/backend/bloom/infra/repositories/repository_segment.py @@ -10,6 +10,7 @@ from sqlalchemy import and_, or_, select, update, text from sqlalchemy.orm import Session +from bloom.logger import logger from bloom.domain.segment import Segment from bloom.domain.vessel_last_position import VesselLastPosition from bloom.domain.zone import Zone @@ -82,23 +83,26 @@ def get_vessel_last_position(self, session: Session,vessel_id:int) -> List[Segme ).join( sql_model.Vessel, sql_model.Excursion.vessel_id == sql_model.Vessel.id + ).join( + sql_model.Segment, + sql_model.Excursion.id == sql_model.Segment.excursion_id ).filter( sql_model.Segment.last_vessel_segment == True, sql_model.Vessel.id == vessel_id, ) - result = session.execute(stmt) - if result is not None: - return [VesselLastPosition( - vessel=VesselRepository.map_to_domain(record[0]), - excursion_id=record[1], - position=to_shape(record[2]), - timestamp=record[3], - heading=record[4], - speed=record[5], - arrival_port_id=record[6], - ) for record in result][0] + result = session.execute(stmt).fetchone() + if result is not None : + return VesselLastPosition( + vessel=VesselRepository.map_to_domain(result[0]), + excursion_id=result[1], + position=to_shape(result[2]), + timestamp=result[3], + heading=result[4], + speed=result[5], + arrival=result[6], + ) else: - return None + return [] def list_vessel_excursion_segments(self,session,vessel_id:int,excursions_id: int) -> List[Segment]: stmt = select( diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 9101cc4d..88dd1415 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -66,7 +66,7 @@ async def list_all_vessel_last_position(nocache:bool=False): segment_repository = use_cases.segment_repository() db = use_cases.db() with db.session() as session: - json_data = [p.model_dump_json() + json_data = [json.loads(p.model_dump_json() if p else "{}") for p in segment_repository.get_all_vessels_last_position(session)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) @@ -88,8 +88,8 @@ async def get_vessel_last_position(vessel_id: int, nocache:bool=False): segment_repository = use_cases.segment_repository() db = use_cases.db() with db.session() as session: - json_data = [p.model_dump_json() - for p in segment_repository.get_vessel_last_position(session)] + result=segment_repository.get_vessel_last_position(session,vessel_id) + json_data = json.loads(result.model_dump_json() if result else "{}") rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") From 5aa4bbc2438e2fc67bdee9955aa6fa6f4a7564b4 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 15:35:43 +0200 Subject: [PATCH 23/34] fix: api endpoint /vessels/id/excursions --- .../infra/repositories/repository_excursion.py | 7 ++++--- backend/bloom/services/api.py | 15 ++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_excursion.py b/backend/bloom/infra/repositories/repository_excursion.py index 22fd88d2..524e1e80 100644 --- a/backend/bloom/infra/repositories/repository_excursion.py +++ b/backend/bloom/infra/repositories/repository_excursion.py @@ -37,10 +37,11 @@ def get_param_from_last_excursion(self, session: Session, vessel_id: int) -> Uni def get_excursions_by_vessel_id(self, session: Session, vessel_id: int) -> List[Excursion]: """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" stmt = select(sql_model.Excursion).where(sql_model.Excursion.vessel_id == vessel_id) - result = session.execute(stmt).scalars() - if result is None: + result = session.execute(stmt).all() + print(result) + if not result: return [] - return [ ExcursionRepository.map_to_domain(r) for r in result] + return [ ExcursionRepository.map_to_domain(r[0]) for r in result] def get_vessel_excursion_by_id(self, session: Session, vessel_id: int, excursion_id:int) -> Union[Excursion,None]: """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 88dd1415..10012087 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -37,7 +37,7 @@ async def list_vessels(nocache:bool=False): db = use_cases.db() with db.session() as session: - json_data = [v.model_dump_json() + json_data = [json.loads(v.model_dump_json() if v else "{}") for v in vessel_repository.get_vessels_list(session)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) @@ -110,11 +110,12 @@ async def list_vessel_excursions(vessel_id: int, nocache:bool=False): excursion_repository = use_cases.excursion_repository() db = use_cases.db() with db.session() as session: - json_data = [p.model_dump_json() - for p in excursion_repository.get_excursions_by_vessel_id(session)] + json_data = [json.loads(p.model_dump_json() if p else "{}") + for p in excursion_repository.get_excursions_by_vessel_id(session,vessel_id)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return json_data @app.get("/vessels/{vessel_id}/excursions/{excursions_id}") @@ -157,7 +158,7 @@ async def list_ports(request:Request,nocache:bool=False): port_repository = use_cases.port_repository() db = use_cases.db() with db.session() as session: - json_data = [p.model_dump_json() + json_data = [json.loads(p.model_dump_json() if p else "{}") for p in port_repository.get_all_ports(session)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) @@ -188,7 +189,7 @@ async def list_zones(request:Request,nocache:bool=False): zone_repository = use_cases.zone_repository() db = use_cases.db() with db.session() as session: - json_data = [z.model_dump_json() + json_data = [json.loads(z.model_dump_json() if z else "{}") for z in zone_repository.get_all_zones(session)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) @@ -210,7 +211,7 @@ async def list_zone_categories(request:Request,nocache:bool=False): zone_repository = use_cases.zone_repository() db = use_cases.db() with db.session() as session: - json_data = [z.model_dump_json() + json_data = [json.loads(z.model_dump_json() if z else "{}") for z in zone_repository.get_all_zone_categories(session)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) @@ -232,7 +233,7 @@ async def get_zone_all_by_category(category:str="amp",nocache:bool=False): zone_repository = use_cases.zone_repository() db = use_cases.db() with db.session() as session: - json_data = [z.model_dump_json() + json_data = [json.loads(z.model_dump_json() if z else "{}") for z in zone_repository.get_all_zones_by_category(session,category)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) From f3d74ca8d00ea06ccdbaaedc31fb8952314384cc Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 16:28:40 +0200 Subject: [PATCH 24/34] fix/temp: remove frontend, problem of compilation --- docker/Dockerfile | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 89f03bdb..5f03f3dc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -40,21 +40,21 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get -y --no-install-recommends install -y && rm -rf /etc/cron.*/* # FRONTEND -ARG NPM_VERSION=v0.39.7 -ENV NPM_VERSION=${NPM_VERSION} -ARG NODE_VERSION=18 -ENV NODE_VERSION=${NODE_VERSION} -COPY frontend ${PROJECT_DIR}/frontend +#ARG NPM_VERSION=v0.39.7 +#ENV NPM_VERSION=${NPM_VERSION} +#ARG NODE_VERSION=18 +#ENV NODE_VERSION=${NODE_VERSION} +#COPY frontend ${PROJECT_DIR}/frontend # installs NVM (Node Version Manager) # download and install Node.js -RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NPM_VERSION}/install.sh | bash &&\ - . /root/.bashrc &&\ - nvm install $NODE_VERSION &&\ - ln -sf `nvm which node` /usr/local/bin/node &&\ - ln -sf ${PROJECT_DIR}/frontend/node_modules/next/dist/bin/next /usr/local/bin/next &&\ - cd frontend &&\ - npm install && (echo "NPM: Install OK") || (echo "NPM: Install error"; exit 1) &&\ - npm run build && (echo "NPM: Build OK") || (echo "NPM: Build error"; exit 1) +#RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NPM_VERSION}/install.sh | bash &&\ +# . /root/.bashrc &&\ +# nvm install $NODE_VERSION &&\ +# ln -sf `nvm which node` /usr/local/bin/node &&\ +# ln -sf ${PROJECT_DIR}/frontend/node_modules/next/dist/bin/next /usr/local/bin/next &&\ +# cd frontend &&\ +# npm install && (echo "NPM: Install OK") || (echo "NPM: Install error"; exit 1) &&\ +# npm run build && (echo "NPM: Build OK") || (echo "NPM: Build error"; exit 1) COPY docker/entrypoint.sh /entrypoint.sh RUN ["chmod", "+x", "/entrypoint.sh"] From f163e05d0d63fc0ff0f87a86a9942ec8d7608d93 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 16:27:33 +0200 Subject: [PATCH 25/34] fix: ajout ZoneCategory --- backend/bloom/domain/zone_category.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 backend/bloom/domain/zone_category.py diff --git a/backend/bloom/domain/zone_category.py b/backend/bloom/domain/zone_category.py new file mode 100644 index 00000000..4da34945 --- /dev/null +++ b/backend/bloom/domain/zone_category.py @@ -0,0 +1,12 @@ +from datetime import datetime +from typing import Union + +from pydantic import BaseModel, ConfigDict +from shapely import Geometry, Point, MultiPolygon,Polygon +from shapely.geometry import mapping, shape + + +class ZoneCategory(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True) + category: str + sub_category: Union[str, None] From 816f92c5ecb9de7120af08772f3a82bcd8733d35 Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 17:08:06 +0200 Subject: [PATCH 26/34] fix: up with data --- docker-compose-load-data.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-load-data.yaml b/docker-compose-load-data.yaml index 92c7e369..d2821772 100644 --- a/docker-compose-load-data.yaml +++ b/docker-compose-load-data.yaml @@ -20,7 +20,7 @@ services: /venv/bin/python3 backend/bloom/tasks/load_dim_port_from_csv.py && /venv/bin/python3 backend/bloom/tasks/load_spire_data_from_csv.py && /venv/bin/python3 backend/bloom/tasks/clean_positions.py --batch-time 100000 && - /venv/bin/python3 python bloom/tasks/create_update_excursions_segments.py" + /venv/bin/python3 backend/bloom/tasks/create_update_excursions_segments.py" volumes: - ./:/project/ - ./data:/project/data From c67278ca31b780be292b94ba4ce89ff71234665f Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 17:18:50 +0200 Subject: [PATCH 27/34] fix: map to domain rename for ZoneCategory --- backend/bloom/infra/repositories/repository_zone.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index 885ff233..a1670a5d 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -21,6 +21,7 @@ def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: def get_all_zones(self, session: Session) -> List[Zone]: q = session.query(sql_model.Zone) + print(q) q=session.execute(q).scalars() if not q: return [] @@ -32,7 +33,7 @@ def get_all_zone_categories(self, session: Session) -> List[Zone]: q=session.execute(q) if not q: return [] - return [ZoneRepository.map_to_domain(ZoneCategory(category=cat,sub_category=sub)) for cat,sub in q] + return [ZoneRepository.map_zonecategory_to_domain(ZoneCategory(category=cat,sub_category=sub)) for cat,sub in q] def get_all_zones_by_category(self, session: Session,category:str) -> List[Zone]: q = session.query(sql_model.Zone).where(sql_model.Zone.category == category) @@ -71,7 +72,7 @@ def map_to_domain(zone: sql_model.Zone) -> Zone: created_at=zone.created_at, ) @staticmethod - def map_to_domain(category: ZoneCategory) -> Zone: + def map_zonecategory_to_domain(category: ZoneCategory) -> Zone: return ZoneCategory( category=category.category, sub_category=category.sub_category From 4b5ce06a6b71811bf65e659234c45253bfcc5adf Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 17:46:38 +0200 Subject: [PATCH 28/34] feat: add endpoint /zones/by-category/{cat|all}/by-sub-category/{sub} --- .../infra/repositories/repository_zone.py | 9 +++++--- backend/bloom/services/api.py | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index a1670a5d..f07af38f 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -21,7 +21,6 @@ def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: def get_all_zones(self, session: Session) -> List[Zone]: q = session.query(sql_model.Zone) - print(q) q=session.execute(q).scalars() if not q: return [] @@ -35,8 +34,12 @@ def get_all_zone_categories(self, session: Session) -> List[Zone]: return [] return [ZoneRepository.map_zonecategory_to_domain(ZoneCategory(category=cat,sub_category=sub)) for cat,sub in q] - def get_all_zones_by_category(self, session: Session,category:str) -> List[Zone]: - q = session.query(sql_model.Zone).where(sql_model.Zone.category == category) + def get_all_zones_by_category(self, session: Session,category:str=None, sub:str=None) -> List[Zone]: + q = session.query(sql_model.Zone) + if category: + q=q.filter(sql_model.Zone.category == category) + if sub: + q=q.filter(sql_model.Zone.sub_category == sub) if not q: return [] return [ZoneRepository.map_to_domain(entity) for entity in q] diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 10012087..22c82fb3 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -218,6 +218,28 @@ async def list_zone_categories(request:Request,nocache:bool=False): logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") return json_data +@app.get("/zones/by-category/{category}/by-sub-category/{sub}") +async def get_zone_all_by_category(category:str,sub:str=None,nocache:bool=False): + endpoint=f"/zones/by-category/{category}/by-sub-category/{sub}" + cache= rd.get(endpoint) + start = time.time() + if cache and not nocache: + logger.debug(f"{endpoint} cached ({settings.redis_cache_expiration})s") + payload=json.loads(cache) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return payload + else: + use_cases = UseCases() + zone_repository = use_cases.zone_repository() + db = use_cases.db() + with db.session() as session: + json_data = [json.loads(z.model_dump_json() if z else "{}") + for z in zone_repository.get_all_zones_by_category(session,category if category != 'all' else None,sub)] + rd.set(endpoint, json.dumps(json_data)) + rd.expire(endpoint,settings.redis_cache_expiration) + logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") + return json_data + @app.get("/zones/by-category/{category}") async def get_zone_all_by_category(category:str="amp",nocache:bool=False): endpoint=f"/zones/by-category/{category}" From 138970bacb4e71e1d43d9b227ecff8817801c53e Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 17:52:09 +0200 Subject: [PATCH 29/34] =?UTF-8?q?clean:=20endpoint=20non=20r=C3=A9alis?= =?UTF-8?q?=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/bloom/services/api.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index 22c82fb3..f751d5e9 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -270,36 +270,6 @@ async def get_zone(zones_id:int): with db.session() as session: return zone_repository.get_zone_by_id(session,zones_id) - - -@app.get("/statics/{zones}") -async def get_statics_zones(): - return {} - -@app.get("/maptiles/mpa") -async def get_maptile_mpa(): - return {"data":{}} - -@app.get("/maptiles/territorial") -async def get_maptile_territorial(): - return {"data":{}} - -@app.get("/maptiles/coastal") -async def get_maptile_coastal(): - return {"data":{}} - -@app.get("/maptiles") -async def list_maptiles(request:Request): - return { - "mpa": f"{request.url_for('get_maptile_mpa')}", - "territorial": f"{request.url_for('get_maptile_territorial')}", - "coastal": f"{request.url_for('get_maptile_coastal')}", - } - -@app.get("/maptiles") -async def list_maptiles(): - return {"data":{}} - @app.get("/") async def root(request:Request): return { From 81b379f3d29325f14dc06ac7bfe4814a29cc613e Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Fri, 7 Jun 2024 17:58:31 +0200 Subject: [PATCH 30/34] feat: endpoint category & sub category defaut "all" --- backend/bloom/services/api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/bloom/services/api.py b/backend/bloom/services/api.py index f751d5e9..71bd474e 100644 --- a/backend/bloom/services/api.py +++ b/backend/bloom/services/api.py @@ -219,7 +219,7 @@ async def list_zone_categories(request:Request,nocache:bool=False): return json_data @app.get("/zones/by-category/{category}/by-sub-category/{sub}") -async def get_zone_all_by_category(category:str,sub:str=None,nocache:bool=False): +async def get_zone_all_by_category(category:str="all",sub:str=None,nocache:bool=False): endpoint=f"/zones/by-category/{category}/by-sub-category/{sub}" cache= rd.get(endpoint) start = time.time() @@ -241,7 +241,7 @@ async def get_zone_all_by_category(category:str,sub:str=None,nocache:bool=False) return json_data @app.get("/zones/by-category/{category}") -async def get_zone_all_by_category(category:str="amp",nocache:bool=False): +async def get_zone_all_by_category(category:str="all",nocache:bool=False): endpoint=f"/zones/by-category/{category}" cache= rd.get(endpoint) start = time.time() @@ -256,7 +256,7 @@ async def get_zone_all_by_category(category:str="amp",nocache:bool=False): db = use_cases.db() with db.session() as session: json_data = [json.loads(z.model_dump_json() if z else "{}") - for z in zone_repository.get_all_zones_by_category(session,category)] + for z in zone_repository.get_all_zones_by_category(session,category if category != 'all' else None)] rd.set(endpoint, json.dumps(json_data)) rd.expire(endpoint,settings.redis_cache_expiration) logger.debug(f"{endpoint} elapsed Time: {time.time()-start}") From c8779d46e6f55c4bfef1d2fae9f01a32a8b42bda Mon Sep 17 00:00:00 2001 From: njouanin Date: Sat, 8 Jun 2024 18:53:18 +0200 Subject: [PATCH 31/34] Quelques petites corrections --- .../repositories/repository_excursion.py | 21 ++++++++---------- .../infra/repositories/repository_zone.py | 22 ++++++++++--------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_excursion.py b/backend/bloom/infra/repositories/repository_excursion.py index 524e1e80..5f869585 100644 --- a/backend/bloom/infra/repositories/repository_excursion.py +++ b/backend/bloom/infra/repositories/repository_excursion.py @@ -37,22 +37,19 @@ def get_param_from_last_excursion(self, session: Session, vessel_id: int) -> Uni def get_excursions_by_vessel_id(self, session: Session, vessel_id: int) -> List[Excursion]: """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" stmt = select(sql_model.Excursion).where(sql_model.Excursion.vessel_id == vessel_id) - result = session.execute(stmt).all() - print(result) + result = session.execute(stmt).scalars() if not result: return [] - return [ ExcursionRepository.map_to_domain(r[0]) for r in result] - - def get_vessel_excursion_by_id(self, session: Session, vessel_id: int, excursion_id:int) -> Union[Excursion,None]: + return [ExcursionRepository.map_to_domain(r) for r in result] + + def get_vessel_excursion_by_id(self, session: Session, vessel_id: int, excursion_id: int) -> Union[Excursion, None]: """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" - stmt = select(sql_model.Excursion).where( (sql_model.Excursion.vessel_id == vessel_id ) - & (sql_model.Excursion.id == excursion_id )) - result = session.execute(stmt).fetchone() - if not result : + stmt = select(sql_model.Excursion).where((sql_model.Excursion.vessel_id == vessel_id) + & (sql_model.Excursion.id == excursion_id)) + result = session.execute(stmt).scalar() + if not result: return None - return ExcursionRepository.map_to_domain(result[0]) - - + return ExcursionRepository.map_to_domain(result) def get_excursion_by_id(self, session: Session, id: int) -> Union[Excursion, None]: """Recheche l'excursion en cours d'un bateau, c'est-à-dire l'excursion qui n'a pas de date d'arrivée""" diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index f07af38f..7b1c55b4 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -21,29 +21,30 @@ def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: def get_all_zones(self, session: Session) -> List[Zone]: q = session.query(sql_model.Zone) - q=session.execute(q).scalars() + q = session.execute(q).scalars() if not q: return [] return [ZoneRepository.map_to_domain(entity) for entity in q] - + def get_all_zone_categories(self, session: Session) -> List[Zone]: q = session.query(sql_model.Zone.category, sql_model.Zone.sub_category).distinct() - q=session.execute(q) + q = session.execute(q) if not q: return [] - return [ZoneRepository.map_zonecategory_to_domain(ZoneCategory(category=cat,sub_category=sub)) for cat,sub in q] - - def get_all_zones_by_category(self, session: Session,category:str=None, sub:str=None) -> List[Zone]: + return [ZoneRepository.map_zonecategory_to_domain(ZoneCategory(category=cat, sub_category=sub)) for cat, sub in + q] + + def get_all_zones_by_category(self, session: Session, category: str = None, sub: str = None) -> List[Zone]: q = session.query(sql_model.Zone) if category: - q=q.filter(sql_model.Zone.category == category) + q = q.filter(sql_model.Zone.category == category) if sub: - q=q.filter(sql_model.Zone.sub_category == sub) + q = q.filter(sql_model.Zone.sub_category == sub) if not q: return [] - return [ZoneRepository.map_to_domain(entity) for entity in q] - + return [ZoneRepository.map_to_domain(entity) for entity in session.execute(q).scalars()] + def batch_create_zone(self, session: Session, zones: list[Zone]) -> list[Zone]: orm_list = [ZoneRepository.map_to_orm(zone) for zone in zones] session.add_all(orm_list) @@ -74,6 +75,7 @@ def map_to_domain(zone: sql_model.Zone) -> Zone: json_data=zone.json_data, created_at=zone.created_at, ) + @staticmethod def map_zonecategory_to_domain(category: ZoneCategory) -> Zone: return ZoneCategory( From 1bde468c43f366361770791ba78f273154558289 Mon Sep 17 00:00:00 2001 From: njouanin Date: Sat, 8 Jun 2024 19:01:38 +0200 Subject: [PATCH 32/34] Corrections de types --- backend/bloom/infra/repositories/repository_zone.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/bloom/infra/repositories/repository_zone.py b/backend/bloom/infra/repositories/repository_zone.py index 7b1c55b4..aa9c2472 100644 --- a/backend/bloom/infra/repositories/repository_zone.py +++ b/backend/bloom/infra/repositories/repository_zone.py @@ -19,14 +19,14 @@ def __init__( def get_zone_by_id(self, session: Session, zone_id: int) -> Union[Zone, None]: return ZoneRepository.map_to_domain(session.get(sql_model.Zone, zone_id)) - def get_all_zones(self, session: Session) -> List[Zone]: + def get_all_zones(self, session: Session) -> list[Zone]: q = session.query(sql_model.Zone) q = session.execute(q).scalars() if not q: return [] return [ZoneRepository.map_to_domain(entity) for entity in q] - def get_all_zone_categories(self, session: Session) -> List[Zone]: + def get_all_zone_categories(self, session: Session) -> list[ZoneCategory]: q = session.query(sql_model.Zone.category, sql_model.Zone.sub_category).distinct() q = session.execute(q) @@ -35,7 +35,7 @@ def get_all_zone_categories(self, session: Session) -> List[Zone]: return [ZoneRepository.map_zonecategory_to_domain(ZoneCategory(category=cat, sub_category=sub)) for cat, sub in q] - def get_all_zones_by_category(self, session: Session, category: str = None, sub: str = None) -> List[Zone]: + def get_all_zones_by_category(self, session: Session, category: str = None, sub: str = None) -> list[Zone]: q = session.query(sql_model.Zone) if category: q = q.filter(sql_model.Zone.category == category) @@ -77,7 +77,7 @@ def map_to_domain(zone: sql_model.Zone) -> Zone: ) @staticmethod - def map_zonecategory_to_domain(category: ZoneCategory) -> Zone: + def map_zonecategory_to_domain(category: ZoneCategory) -> ZoneCategory: return ZoneCategory( category=category.category, sub_category=category.sub_category From 141847a0fa4c1a371e9f9aef04a7494c4358833f Mon Sep 17 00:00:00 2001 From: njouanin Date: Mon, 10 Jun 2024 21:42:45 +0200 Subject: [PATCH 33/34] MAJ poetry.lock --- backend/poetry.lock | 425 +++++++++++++++++++++----------------------- 1 file changed, 205 insertions(+), 220 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 87fac669..a825f673 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -21,24 +21,24 @@ tz = ["backports.zoneinfo"] [[package]] name = "annotated-types" -version = "0.6.0" +version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [[package]] name = "anyio" -version = "4.3.0" +version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, ] [package.dependencies] @@ -167,13 +167,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -511,43 +511,43 @@ files = [ [[package]] name = "cryptography" -version = "42.0.7" +version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, + {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, + {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, + {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, + {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, + {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, + {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, ] [package.dependencies] @@ -959,53 +959,53 @@ test = ["fiona[s3]", "pytest (>=7)", "pytest-cov", "pytz"] [[package]] name = "fonttools" -version = "4.51.0" +version = "4.53.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" files = [ - {file = "fonttools-4.51.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:84d7751f4468dd8cdd03ddada18b8b0857a5beec80bce9f435742abc9a851a74"}, - {file = "fonttools-4.51.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8b4850fa2ef2cfbc1d1f689bc159ef0f45d8d83298c1425838095bf53ef46308"}, - {file = "fonttools-4.51.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5b48a1121117047d82695d276c2af2ee3a24ffe0f502ed581acc2673ecf1037"}, - {file = "fonttools-4.51.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:180194c7fe60c989bb627d7ed5011f2bef1c4d36ecf3ec64daec8302f1ae0716"}, - {file = "fonttools-4.51.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:96a48e137c36be55e68845fc4284533bda2980f8d6f835e26bca79d7e2006438"}, - {file = "fonttools-4.51.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:806e7912c32a657fa39d2d6eb1d3012d35f841387c8fc6cf349ed70b7c340039"}, - {file = "fonttools-4.51.0-cp310-cp310-win32.whl", hash = "sha256:32b17504696f605e9e960647c5f64b35704782a502cc26a37b800b4d69ff3c77"}, - {file = "fonttools-4.51.0-cp310-cp310-win_amd64.whl", hash = "sha256:c7e91abdfae1b5c9e3a543f48ce96013f9a08c6c9668f1e6be0beabf0a569c1b"}, - {file = "fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74"}, - {file = "fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2"}, - {file = "fonttools-4.51.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e19bd9e9964a09cd2433a4b100ca7f34e34731e0758e13ba9a1ed6e5468cc0f"}, - {file = "fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2b92381f37b39ba2fc98c3a45a9d6383bfc9916a87d66ccb6553f7bdd129097"}, - {file = "fonttools-4.51.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5f6bc991d1610f5c3bbe997b0233cbc234b8e82fa99fc0b2932dc1ca5e5afec0"}, - {file = "fonttools-4.51.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9696fe9f3f0c32e9a321d5268208a7cc9205a52f99b89479d1b035ed54c923f1"}, - {file = "fonttools-4.51.0-cp311-cp311-win32.whl", hash = "sha256:3bee3f3bd9fa1d5ee616ccfd13b27ca605c2b4270e45715bd2883e9504735034"}, - {file = "fonttools-4.51.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1"}, - {file = "fonttools-4.51.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4060acc2bfa2d8e98117828a238889f13b6f69d59f4f2d5857eece5277b829ba"}, - {file = "fonttools-4.51.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1250e818b5f8a679ad79660855528120a8f0288f8f30ec88b83db51515411fcc"}, - {file = "fonttools-4.51.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76f1777d8b3386479ffb4a282e74318e730014d86ce60f016908d9801af9ca2a"}, - {file = "fonttools-4.51.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b5ad456813d93b9c4b7ee55302208db2b45324315129d85275c01f5cb7e61a2"}, - {file = "fonttools-4.51.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:68b3fb7775a923be73e739f92f7e8a72725fd333eab24834041365d2278c3671"}, - {file = "fonttools-4.51.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8e2f1a4499e3b5ee82c19b5ee57f0294673125c65b0a1ff3764ea1f9db2f9ef5"}, - {file = "fonttools-4.51.0-cp312-cp312-win32.whl", hash = "sha256:278e50f6b003c6aed19bae2242b364e575bcb16304b53f2b64f6551b9c000e15"}, - {file = "fonttools-4.51.0-cp312-cp312-win_amd64.whl", hash = "sha256:b3c61423f22165541b9403ee39874dcae84cd57a9078b82e1dce8cb06b07fa2e"}, - {file = "fonttools-4.51.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:1621ee57da887c17312acc4b0e7ac30d3a4fb0fec6174b2e3754a74c26bbed1e"}, - {file = "fonttools-4.51.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d9298be7a05bb4801f558522adbe2feea1b0b103d5294ebf24a92dd49b78e5"}, - {file = "fonttools-4.51.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee1af4be1c5afe4c96ca23badd368d8dc75f611887fb0c0dac9f71ee5d6f110e"}, - {file = "fonttools-4.51.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c18b49adc721a7d0b8dfe7c3130c89b8704baf599fb396396d07d4aa69b824a1"}, - {file = "fonttools-4.51.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de7c29bdbdd35811f14493ffd2534b88f0ce1b9065316433b22d63ca1cd21f14"}, - {file = "fonttools-4.51.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cadf4e12a608ef1d13e039864f484c8a968840afa0258b0b843a0556497ea9ed"}, - {file = "fonttools-4.51.0-cp38-cp38-win32.whl", hash = "sha256:aefa011207ed36cd280babfaa8510b8176f1a77261833e895a9d96e57e44802f"}, - {file = "fonttools-4.51.0-cp38-cp38-win_amd64.whl", hash = "sha256:865a58b6e60b0938874af0968cd0553bcd88e0b2cb6e588727117bd099eef836"}, - {file = "fonttools-4.51.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:60a3409c9112aec02d5fb546f557bca6efa773dcb32ac147c6baf5f742e6258b"}, - {file = "fonttools-4.51.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7e89853d8bea103c8e3514b9f9dc86b5b4120afb4583b57eb10dfa5afbe0936"}, - {file = "fonttools-4.51.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56fc244f2585d6c00b9bcc59e6593e646cf095a96fe68d62cd4da53dd1287b55"}, - {file = "fonttools-4.51.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d145976194a5242fdd22df18a1b451481a88071feadf251221af110ca8f00ce"}, - {file = "fonttools-4.51.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5b8cab0c137ca229433570151b5c1fc6af212680b58b15abd797dcdd9dd5051"}, - {file = "fonttools-4.51.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:54dcf21a2f2d06ded676e3c3f9f74b2bafded3a8ff12f0983160b13e9f2fb4a7"}, - {file = "fonttools-4.51.0-cp39-cp39-win32.whl", hash = "sha256:0118ef998a0699a96c7b28457f15546815015a2710a1b23a7bf6c1be60c01636"}, - {file = "fonttools-4.51.0-cp39-cp39-win_amd64.whl", hash = "sha256:599bdb75e220241cedc6faebfafedd7670335d2e29620d207dd0378a4e9ccc5a"}, - {file = "fonttools-4.51.0-py3-none-any.whl", hash = "sha256:15c94eeef6b095831067f72c825eb0e2d48bb4cea0647c1b05c981ecba2bf39f"}, - {file = "fonttools-4.51.0.tar.gz", hash = "sha256:dc0673361331566d7a663d7ce0f6fdcbfbdc1f59c6e3ed1165ad7202ca183c68"}, + {file = "fonttools-4.53.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:52a6e0a7a0bf611c19bc8ec8f7592bdae79c8296c70eb05917fd831354699b20"}, + {file = "fonttools-4.53.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:099634631b9dd271d4a835d2b2a9e042ccc94ecdf7e2dd9f7f34f7daf333358d"}, + {file = "fonttools-4.53.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e40013572bfb843d6794a3ce076c29ef4efd15937ab833f520117f8eccc84fd6"}, + {file = "fonttools-4.53.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:715b41c3e231f7334cbe79dfc698213dcb7211520ec7a3bc2ba20c8515e8a3b5"}, + {file = "fonttools-4.53.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74ae2441731a05b44d5988d3ac2cf784d3ee0a535dbed257cbfff4be8bb49eb9"}, + {file = "fonttools-4.53.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:95db0c6581a54b47c30860d013977b8a14febc206c8b5ff562f9fe32738a8aca"}, + {file = "fonttools-4.53.0-cp310-cp310-win32.whl", hash = "sha256:9cd7a6beec6495d1dffb1033d50a3f82dfece23e9eb3c20cd3c2444d27514068"}, + {file = "fonttools-4.53.0-cp310-cp310-win_amd64.whl", hash = "sha256:daaef7390e632283051e3cf3e16aff2b68b247e99aea916f64e578c0449c9c68"}, + {file = "fonttools-4.53.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a209d2e624ba492df4f3bfad5996d1f76f03069c6133c60cd04f9a9e715595ec"}, + {file = "fonttools-4.53.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f520d9ac5b938e6494f58a25c77564beca7d0199ecf726e1bd3d56872c59749"}, + {file = "fonttools-4.53.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eceef49f457253000e6a2d0f7bd08ff4e9fe96ec4ffce2dbcb32e34d9c1b8161"}, + {file = "fonttools-4.53.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1f3e34373aa16045484b4d9d352d4c6b5f9f77ac77a178252ccbc851e8b2ee"}, + {file = "fonttools-4.53.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:28d072169fe8275fb1a0d35e3233f6df36a7e8474e56cb790a7258ad822b6fd6"}, + {file = "fonttools-4.53.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4a2a6ba400d386e904fd05db81f73bee0008af37799a7586deaa4aef8cd5971e"}, + {file = "fonttools-4.53.0-cp311-cp311-win32.whl", hash = "sha256:bb7273789f69b565d88e97e9e1da602b4ee7ba733caf35a6c2affd4334d4f005"}, + {file = "fonttools-4.53.0-cp311-cp311-win_amd64.whl", hash = "sha256:9fe9096a60113e1d755e9e6bda15ef7e03391ee0554d22829aa506cdf946f796"}, + {file = "fonttools-4.53.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d8f191a17369bd53a5557a5ee4bab91d5330ca3aefcdf17fab9a497b0e7cff7a"}, + {file = "fonttools-4.53.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93156dd7f90ae0a1b0e8871032a07ef3178f553f0c70c386025a808f3a63b1f4"}, + {file = "fonttools-4.53.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bff98816cb144fb7b85e4b5ba3888a33b56ecef075b0e95b95bcd0a5fbf20f06"}, + {file = "fonttools-4.53.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:973d030180eca8255b1bce6ffc09ef38a05dcec0e8320cc9b7bcaa65346f341d"}, + {file = "fonttools-4.53.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c4ee5a24e281fbd8261c6ab29faa7fd9a87a12e8c0eed485b705236c65999109"}, + {file = "fonttools-4.53.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd5bc124fae781a4422f61b98d1d7faa47985f663a64770b78f13d2c072410c2"}, + {file = "fonttools-4.53.0-cp312-cp312-win32.whl", hash = "sha256:a239afa1126b6a619130909c8404070e2b473dd2b7fc4aacacd2e763f8597fea"}, + {file = "fonttools-4.53.0-cp312-cp312-win_amd64.whl", hash = "sha256:45b4afb069039f0366a43a5d454bc54eea942bfb66b3fc3e9a2c07ef4d617380"}, + {file = "fonttools-4.53.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:93bc9e5aaa06ff928d751dc6be889ff3e7d2aa393ab873bc7f6396a99f6fbb12"}, + {file = "fonttools-4.53.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2367d47816cc9783a28645bc1dac07f8ffc93e0f015e8c9fc674a5b76a6da6e4"}, + {file = "fonttools-4.53.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:907fa0b662dd8fc1d7c661b90782ce81afb510fc4b7aa6ae7304d6c094b27bce"}, + {file = "fonttools-4.53.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e0ad3c6ea4bd6a289d958a1eb922767233f00982cf0fe42b177657c86c80a8f"}, + {file = "fonttools-4.53.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:73121a9b7ff93ada888aaee3985a88495489cc027894458cb1a736660bdfb206"}, + {file = "fonttools-4.53.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ee595d7ba9bba130b2bec555a40aafa60c26ce68ed0cf509983e0f12d88674fd"}, + {file = "fonttools-4.53.0-cp38-cp38-win32.whl", hash = "sha256:fca66d9ff2ac89b03f5aa17e0b21a97c21f3491c46b583bb131eb32c7bab33af"}, + {file = "fonttools-4.53.0-cp38-cp38-win_amd64.whl", hash = "sha256:31f0e3147375002aae30696dd1dc596636abbd22fca09d2e730ecde0baad1d6b"}, + {file = "fonttools-4.53.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7d6166192dcd925c78a91d599b48960e0a46fe565391c79fe6de481ac44d20ac"}, + {file = "fonttools-4.53.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef50ec31649fbc3acf6afd261ed89d09eb909b97cc289d80476166df8438524d"}, + {file = "fonttools-4.53.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f193f060391a455920d61684a70017ef5284ccbe6023bb056e15e5ac3de11d1"}, + {file = "fonttools-4.53.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba9f09ff17f947392a855e3455a846f9855f6cf6bec33e9a427d3c1d254c712f"}, + {file = "fonttools-4.53.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c555e039d268445172b909b1b6bdcba42ada1cf4a60e367d68702e3f87e5f64"}, + {file = "fonttools-4.53.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a4788036201c908079e89ae3f5399b33bf45b9ea4514913f4dbbe4fac08efe0"}, + {file = "fonttools-4.53.0-cp39-cp39-win32.whl", hash = "sha256:d1a24f51a3305362b94681120c508758a88f207fa0a681c16b5a4172e9e6c7a9"}, + {file = "fonttools-4.53.0-cp39-cp39-win_amd64.whl", hash = "sha256:1e677bfb2b4bd0e5e99e0f7283e65e47a9814b0486cb64a41adf9ef110e078f2"}, + {file = "fonttools-4.53.0-py3-none-any.whl", hash = "sha256:6b4f04b1fbc01a3569d63359f2227c89ab294550de277fd09d8fca6185669fa4"}, + {file = "fonttools-4.53.0.tar.gz", hash = "sha256:c93ed66d32de1559b6fc348838c7572d5c0ac1e4a258e76763a5caddd8944002"}, ] [package.extras] @@ -1811,6 +1811,7 @@ files = [ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"}, {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] @@ -1915,18 +1916,15 @@ files = [ [[package]] name = "nodeenv" -version = "1.8.0" +version = "1.9.1" description = "Node.js virtual environment builder" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] -[package.dependencies] -setuptools = "*" - [[package]] name = "numpy" version = "1.26.4" @@ -1974,13 +1972,13 @@ files = [ [[package]] name = "openpyxl" -version = "3.1.2" +version = "3.1.3" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = false python-versions = ">=3.6" files = [ - {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, - {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, + {file = "openpyxl-3.1.3-py2.py3-none-any.whl", hash = "sha256:25071b558db709de9e8782c3d3e058af3b23ffb2fc6f40c8f0c45a154eced2c3"}, + {file = "openpyxl-3.1.3.tar.gz", hash = "sha256:8dd482e5350125b2388070bb2477927be2e8ebc27df61178709bc8c8751da2f9"}, ] [package.dependencies] @@ -2227,13 +2225,13 @@ xmp = ["defusedxml"] [[package]] name = "pkginfo" -version = "1.10.0" +version = "1.11.1" description = "Query metadata from sdists / bdists / installed packages." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pkginfo-1.10.0-py3-none-any.whl", hash = "sha256:889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097"}, - {file = "pkginfo-1.10.0.tar.gz", hash = "sha256:5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297"}, + {file = "pkginfo-1.11.1-py3-none-any.whl", hash = "sha256:bfa76a714fdfc18a045fcd684dbfc3816b603d9d075febef17cb6582bea29573"}, + {file = "pkginfo-1.11.1.tar.gz", hash = "sha256:2e0dca1cf4c8e39644eed32408ea9966ee15e0d324c62ba899a393b3c6b467aa"}, ] [package.extras] @@ -2828,101 +2826,104 @@ files = [ [[package]] name = "rapidfuzz" -version = "3.9.0" +version = "3.9.3" description = "rapid fuzzy string matching" optional = false python-versions = ">=3.8" files = [ - {file = "rapidfuzz-3.9.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bd375c4830fee11d502dd93ecadef63c137ae88e1aaa29cc15031fa66d1e0abb"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:55e2c5076f38fc1dbaacb95fa026a3e409eee6ea5ac4016d44fb30e4cad42b20"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:488f74126904db6b1bea545c2f3567ea882099f4c13f46012fe8f4b990c683df"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3f2d1ea7cd57dfcd34821e38b4924c80a31bcf8067201b1ab07386996a9faee"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b11e602987bcb4ea22b44178851f27406fca59b0836298d0beb009b504dba266"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3083512e9bf6ed2bb3d25883922974f55e21ae7f8e9f4e298634691ae1aee583"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b33c6d4b3a1190bc0b6c158c3981535f9434e8ed9ffa40cf5586d66c1819fb4b"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dcb95fde22f98e6d0480db8d6038c45fe2d18a338690e6f9bba9b82323f3469"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:08d8b49b3a4fb8572e480e73fcddc750da9cbb8696752ee12cca4bf8c8220d52"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e721842e6b601ebbeb8cc5e12c75bbdd1d9e9561ea932f2f844c418c31256e82"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7988363b3a415c5194ce1a68d380629247f8713e669ad81db7548eb156c4f365"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2d267d4c982ab7d177e994ab1f31b98ff3814f6791b90d35dda38307b9e7c989"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0bb28ab5300cf974c7eb68ea21125c493e74b35b1129e629533468b2064ae0a2"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-win32.whl", hash = "sha256:1b1f74997b6d94d66375479fa55f70b1c18e4d865d7afcd13f0785bfd40a9d3c"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:c56d2efdfaa1c642029f3a7a5bb76085c5531f7a530777be98232d2ce142553c"}, - {file = "rapidfuzz-3.9.0-cp310-cp310-win_arm64.whl", hash = "sha256:6a83128d505cac76ea560bb9afcb3f6986e14e50a6f467db9a31faef4bd9b347"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e2218d62ab63f3c5ad48eced898854d0c2c327a48f0fb02e2288d7e5332a22c8"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:36bf35df2d6c7d5820da20a6720aee34f67c15cd2daf8cf92e8141995c640c25"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:905b01a9b633394ff6bb5ebb1c5fd660e0e180c03fcf9d90199cc6ed74b87cf7"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33cfabcb7fd994938a6a08e641613ce5fe46757832edc789c6a5602e7933d6fa"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1179dcd3d150a67b8a678cd9c84f3baff7413ff13c9e8fe85e52a16c97e24c9b"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47d97e28c42f1efb7781993b67c749223f198f6653ef177a0c8f2b1c516efcaf"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28da953eb2ef9ad527e536022da7afff6ace7126cdd6f3e21ac20f8762e76d2c"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:182b4e11de928fb4834e8f8b5ecd971b5b10a86fabe8636ab65d3a9b7e0e9ca7"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c74f2da334ce597f31670db574766ddeaee5d9430c2c00e28d0fbb7f76172036"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:014ac55b03f4074f903248ded181f3000f4cdbd134e6155cbf643f0eceb4f70f"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c4ef34b2ddbf448f1d644b4ec6475df8bbe5b9d0fee173ff2e87322a151663bd"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fc02157f521af15143fae88f92ef3ddcc4e0cff05c40153a9549dc0fbdb9adb3"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ff08081c49b18ba253a99e6a47f492e6ee8019e19bbb6ddc3ed360cd3ecb2f62"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-win32.whl", hash = "sha256:b9bf90b3d96925cbf8ef44e5ee3cf39ef0c422f12d40f7a497e91febec546650"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:d5d5684f54d82d9b0cf0b2701e55a630527a9c3dd5ddcf7a2e726a475ac238f2"}, - {file = "rapidfuzz-3.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:a2de844e0e971d7bd8aa41284627dbeacc90e750b90acfb016836553c7a63192"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f81fe99a69ac8ee3fd905e70c62f3af033901aeb60b69317d1d43d547b46e510"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:633b9d03fc04abc585c197104b1d0af04b1f1db1abc99f674d871224cd15557a"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab872cb57ae97c54ba7c71a9e3c9552beb57cb907c789b726895576d1ea9af6f"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdd8c15c3a14e409507fdf0c0434ec481d85c6cbeec8bdcd342a8cd1eda03825"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2444d8155d9846f206e2079bb355b85f365d9457480b0d71677a112d0a7f7128"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f83bd3d01f04061c3660742dc85143a89d49fd23eb31eccbf60ad56c4b955617"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ca799f882364e69d0872619afb19efa3652b7133c18352e4a3d86a324fb2bb1"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6993d361f28b9ef5f0fa4e79b8541c2f3507be7471b9f9cb403a255e123b31e1"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:170822a1b1719f02b58e3dce194c8ad7d4c5b39be38c0fdec603bd19c6f9cf81"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e86e39c1c1a0816ceda836e6f7bd3743b930cbc51a43a81bb433b552f203f25"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:731269812ea837e0b93d913648e404736407408e33a00b75741e8f27c590caa2"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8e5ff882d3a3d081157ceba7e0ebc7fac775f95b08cbb143accd4cece6043819"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2003071aa633477a01509890c895f9ef56cf3f2eaa72c7ec0b567f743c1abcba"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-win32.whl", hash = "sha256:13857f9070600ea1f940749f123b02d0b027afbaa45e72186df0f278915761d0"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:134b7098ac109834eeea81424b6822f33c4c52bf80b81508295611e7a21be12a"}, - {file = "rapidfuzz-3.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:2a96209f046fe328be30fc43f06e3d4b91f0d5b74e9dcd627dbfd65890fa4a5e"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:544b0bf9d17170720809918e9ccd0d482d4a3a6eca35630d8e1459f737f71755"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d536f8beb8dd82d6efb20fe9f82c2cfab9ffa0384b5d184327e393a4edde91d"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:30f7609da871510583f87484a10820b26555a473a90ab356cdda2f3b4456256c"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f4a2468432a1db491af6f547fad8f6d55fa03e57265c2f20e5eaceb68c7907e"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a7ec4676242c8a430509cff42ce98bca2fbe30188a63d0f60fdcbfd7e84970"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dcb523243e988c849cf81220164ec3bbed378a699e595a8914fffe80596dc49f"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4eea3bf72c4fe68e957526ffd6bcbb403a21baa6b3344aaae2d3252313df6199"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4514980a5d204c076dd5b756960f6b1b7598f030009456e6109d76c4c331d03c"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9a06a99f1335fe43464d7121bc6540de7cd9c9475ac2025babb373fe7f27846b"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6c1ed63345d1581c39d4446b1a8c8f550709656ce2a3c88c47850b258167f3c2"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cd2e6e97daf17ebb3254285cf8dd86c60d56d6cf35c67f0f9a557ef26bd66290"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9bc0f7e6256a9c668482c41c8a3de5d0aa12e8ca346dcc427b97c7edb82cba48"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c09f4e87e82a164c9db769474bc61f8c8b677f2aeb0234b8abac73d2ecf9799"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-win32.whl", hash = "sha256:e65b8f7921bf60cbb207c132842a6b45eefef48c4c3b510eb16087d6c08c70af"}, - {file = "rapidfuzz-3.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9d6478957fb35c7844ad08f2442b62ba76c1857a56370781a707eefa4f4981e1"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65d9250a4b0bf86320097306084bc3ca479c8f5491927c170d018787793ebe95"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47b7c0840afa724db3b1a070bc6ed5beab73b4e659b1d395023617fc51bf68a2"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a16c48c6df8fb633efbbdea744361025d01d79bca988f884a620e63e782fe5b"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48105991ff6e4a51c7f754df500baa070270ed3d41784ee0d097549bc9fcb16d"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a7f273906b3c7cc6d63a76e088200805947aa0bc1ada42c6a0e582e19c390d7"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c396562d304e974b4b0d5cd3afc4f92c113ea46a36e6bc62e45333d6aa8837e"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68da1b70458fea5290ec9a169fcffe0c17ff7e5bb3c3257e63d7021a50601a8e"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c5b8f9a7b177af6ce7c6ad5b95588b4b73e37917711aafa33b2e79ee80fe709"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3c42a238bf9dd48f4ccec4c6934ac718225b00bb3a438a008c219e7ccb3894c7"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a365886c42177b2beab475a50ba311b59b04f233ceaebc4c341f6f91a86a78e2"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ce897b5dafb7fb7587a95fe4d449c1ea0b6d9ac4462fbafefdbbeef6eee4cf6a"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:413ac49bae291d7e226a5c9be65c71b2630b3346bce39268d02cb3290232e4b7"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8982fc3bd49d55a91569fc8a3feba0de4cef0b391ff9091be546e9df075b81"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-win32.whl", hash = "sha256:3904d0084ab51f82e9f353031554965524f535522a48ec75c30b223eb5a0a488"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:3733aede16ea112728ffeafeb29ccc62e095ed8ec816822fa2a82e92e2c08696"}, - {file = "rapidfuzz-3.9.0-cp39-cp39-win_arm64.whl", hash = "sha256:fc4e26f592b51f97acf0a3f8dfed95e4d830c6a8fbf359361035df836381ab81"}, - {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e33362e98c7899b5f60dcb06ada00acd8673ce0d59aefe9a542701251fd00423"}, - {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb67cf43ad83cb886cbbbff4df7dcaad7aedf94d64fca31aea0da7d26684283c"}, - {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e2e106cc66453bb80d2ad9c0044f8287415676df5c8036d737d05d4b9cdbf8e"}, - {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1256915f7e7a5cf2c151c9ac44834b37f9bd1c97e8dec6f936884f01b9dfc7d"}, - {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ae643220584518cbff8bf2974a0494d3e250763af816b73326a512c86ae782ce"}, - {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:491274080742110427f38a6085bb12dffcaff1eef12dccf9e8758398c7e3957e"}, - {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bc5559b9b94326922c096b30ae2d8e5b40b2e9c2c100c2cc396ad91bcb84d30"}, - {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:849160dc0f128acb343af514ca827278005c1d00148d025e4035e034fc2d8c7f"}, - {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:623883fb78e692d54ed7c43b09beec52c6685f10a45a7518128e25746667403b"}, - {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d20ab9abc7e19767f1951772a6ab14cb4eddd886493c2da5ee12014596ad253f"}, - {file = "rapidfuzz-3.9.0.tar.gz", hash = "sha256:b182f0fb61f6ac435e416eb7ab330d62efdbf9b63cf0c7fa12d1f57c2eaaf6f3"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bdb8c5b8e29238ec80727c2ba3b301efd45aa30c6a7001123a6647b8e6f77ea4"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3bd0d9632088c63a241f217742b1cf86e2e8ae573e01354775bd5016d12138c"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:153f23c03d4917f6a1fc2fb56d279cc6537d1929237ff08ee7429d0e40464a18"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a96c5225e840f1587f1bac8fa6f67562b38e095341576e82b728a82021f26d62"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b777cd910ceecd738adc58593d6ed42e73f60ad04ecdb4a841ae410b51c92e0e"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53e06e4b81f552da04940aa41fc556ba39dee5513d1861144300c36c33265b76"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c7ca5b6050f18fdcacdada2dc5fb7619ff998cd9aba82aed2414eee74ebe6cd"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:87bb8d84cb41446a808c4b5f746e29d8a53499381ed72f6c4e456fe0f81c80a8"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:959a15186d18425d19811bea86a8ffbe19fd48644004d29008e636631420a9b7"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a24603dd05fb4e3c09d636b881ce347e5f55f925a6b1b4115527308a323b9f8e"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d055da0e801c71dd74ba81d72d41b2fa32afa182b9fea6b4b199d2ce937450d"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:875b581afb29a7213cf9d98cb0f98df862f1020bce9d9b2e6199b60e78a41d14"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-win32.whl", hash = "sha256:6073a46f61479a89802e3f04655267caa6c14eb8ac9d81a635a13805f735ebc1"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:119c010e20e561249b99ca2627f769fdc8305b07193f63dbc07bca0a6c27e892"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-win_arm64.whl", hash = "sha256:790b0b244f3213581d42baa2fed8875f9ee2b2f9b91f94f100ec80d15b140ba9"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f57e8305c281e8c8bc720515540e0580355100c0a7a541105c6cafc5de71daae"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a4fc7b784cf987dbddc300cef70e09a92ed1bce136f7bb723ea79d7e297fe76d"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b422c0a6fe139d5447a0766268e68e6a2a8c2611519f894b1f31f0a392b9167"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f50fed4a9b0c9825ff37cf0bccafd51ff5792090618f7846a7650f21f85579c9"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b80eb7cbe62348c61d3e67e17057cddfd6defab168863028146e07d5a8b24a89"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f45be77ec82da32ce5709a362e236ccf801615cc7163b136d1778cf9e31b14"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd84b7f652a5610733400307dc732f57c4a907080bef9520412e6d9b55bc9adc"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3e6d27dad8c990218b8cd4a5c99cbc8834f82bb46ab965a7265d5aa69fc7ced7"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:05ee0696ebf0dfe8f7c17f364d70617616afc7dafe366532730ca34056065b8a"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2bc8391749e5022cd9e514ede5316f86e332ffd3cfceeabdc0b17b7e45198a8c"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:93981895602cf5944d89d317ae3b1b4cc684d175a8ae2a80ce5b65615e72ddd0"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:754b719a4990735f66653c9e9261dcf52fd4d925597e43d6b9069afcae700d21"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-win32.whl", hash = "sha256:14c9f268ade4c88cf77ab007ad0fdf63699af071ee69378de89fff7aa3cae134"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc1991b4cde6c9d3c0bbcb83d5581dc7621bec8c666c095c65b4277233265a82"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-win_arm64.whl", hash = "sha256:0c34139df09a61b1b557ab65782ada971b4a3bce7081d1b2bee45b0a52231adb"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d6a210347d6e71234af5c76d55eeb0348b026c9bb98fe7c1cca89bac50fb734"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b300708c917ce52f6075bdc6e05b07c51a085733650f14b732c087dc26e0aaad"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83ea7ca577d76778250421de61fb55a719e45b841deb769351fc2b1740763050"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8319838fb5b7b5f088d12187d91d152b9386ce3979ed7660daa0ed1bff953791"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:505d99131afd21529293a9a7b91dfc661b7e889680b95534756134dc1cc2cd86"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c52970f7784518d7c82b07a62a26e345d2de8c2bd8ed4774e13342e4b3ff4200"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:143caf7247449055ecc3c1e874b69e42f403dfc049fc2f3d5f70e1daf21c1318"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b8ab0fa653d9225195a8ff924f992f4249c1e6fa0aea563f685e71b81b9fcccf"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57e7c5bf7b61c7320cfa5dde1e60e678d954ede9bb7da8e763959b2138391401"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:51fa1ba84653ab480a2e2044e2277bd7f0123d6693051729755addc0d015c44f"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:17ff7f7eecdb169f9236e3b872c96dbbaf116f7787f4d490abd34b0116e3e9c8"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afe7c72d3f917b066257f7ff48562e5d462d865a25fbcabf40fca303a9fa8d35"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-win32.whl", hash = "sha256:e53ed2e9b32674ce96eed80b3b572db9fd87aae6742941fb8e4705e541d861ce"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:35b7286f177e4d8ba1e48b03612f928a3c4bdac78e5651379cec59f95d8651e6"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-win_arm64.whl", hash = "sha256:e6e4b9380ed4758d0cb578b0d1970c3f32dd9e87119378729a5340cb3169f879"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a39890013f6d5b056cc4bfdedc093e322462ece1027a57ef0c636537bdde7531"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b5bc0fdbf419493163c5c9cb147c5fbe95b8e25844a74a8807dcb1a125e630cf"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efe6e200a75a792d37b960457904c4fce7c928a96ae9e5d21d2bd382fe39066e"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de077c468c225d4c18f7188c47d955a16d65f21aab121cbdd98e3e2011002c37"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f917eaadf5388466a95f6a236f678a1588d231e52eda85374077101842e794e"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:858ba57c05afd720db8088a8707079e8d024afe4644001fe0dbd26ef7ca74a65"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d36447d21b05f90282a6f98c5a33771805f9222e5d0441d03eb8824e33e5bbb4"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:acbe4b6f1ccd5b90c29d428e849aa4242e51bb6cab0448d5f3c022eb9a25f7b1"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:53c7f27cdf899e94712972237bda48cfd427646aa6f5d939bf45d084780e4c16"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:6175682a829c6dea4d35ed707f1dadc16513270ef64436568d03b81ccb6bdb74"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5276df395bd8497397197fca2b5c85f052d2e6a66ffc3eb0544dd9664d661f95"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:77b5c4f3e72924d7845f0e189c304270066d0f49635cf8a3938e122c437e58de"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-win32.whl", hash = "sha256:8add34061e5cd561c72ed4febb5c15969e7b25bda2bb5102d02afc3abc1f52d0"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:604e0502a39cf8e67fa9ad239394dddad4cdef6d7008fdb037553817d420e108"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21047f55d674614eb4b0ab34e35c3dc66f36403b9fbfae645199c4a19d4ed447"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a56da3aff97cb56fe85d9ca957d1f55dbac7c27da927a86a2a86d8a7e17f80aa"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:964c08481aec2fe574f0062e342924db2c6b321391aeb73d68853ed42420fd6d"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e2b827258beefbe5d3f958243caa5a44cf46187eff0c20e0b2ab62d1550327a"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6e65a301fcd19fbfbee3a514cc0014ff3f3b254b9fd65886e8a9d6957fb7bca"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe93ba1725a8d47d2b9dca6c1f435174859427fbc054d83de52aea5adc65729"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aca21c0a34adee582775da997a600283e012a608a107398d80a42f9a57ad323d"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:256e07d3465173b2a91c35715a2277b1ee3ae0b9bbab4e519df6af78570741d0"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:802ca2cc8aa6b8b34c6fdafb9e32540c1ba05fca7ad60b3bbd7ec89ed1797a87"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:dd789100fc852cffac1449f82af0da139d36d84fd9faa4f79fc4140a88778343"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:5d0abbacdb06e27ff803d7ae0bd0624020096802758068ebdcab9bd49cf53115"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:378d1744828e27490a823fc6fe6ebfb98c15228d54826bf4e49e4b76eb5f5579"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-win32.whl", hash = "sha256:5d0cb272d43e6d3c0dedefdcd9d00007471f77b52d2787a4695e9dd319bb39d2"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:15e4158ac4b3fb58108072ec35b8a69165f651ba1c8f43559a36d518dbf9fb3f"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-win_arm64.whl", hash = "sha256:58c6a4936190c558d5626b79fc9e16497e5df7098589a7e80d8bff68148ff096"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5410dc848c947a603792f4f51b904a3331cf1dc60621586bfbe7a6de72da1091"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:282d55700a1a3d3a7980746eb2fcd48c9bbc1572ebe0840d0340d548a54d01fe"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc1037507810833646481f5729901a154523f98cbebb1157ba3a821012e16402"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e33f779391caedcba2ba3089fb6e8e557feab540e9149a5c3f7fea7a3a7df37"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41a81a9f311dc83d22661f9b1a1de983b201322df0c4554042ffffd0f2040c37"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a93250bd8fae996350c251e1752f2c03335bb8a0a5b0c7e910a593849121a435"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3617d1aa7716c57d120b6adc8f7c989f2d65bc2b0cbd5f9288f1fc7bf469da11"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad04a3f5384b82933213bba2459f6424decc2823df40098920856bdee5fd6e88"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8709918da8a88ad73c9d4dd0ecf24179a4f0ceba0bee21efc6ea21a8b5290349"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b770f85eab24034e6ef7df04b2bfd9a45048e24f8a808e903441aa5abde8ecdd"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930b4e6fdb4d914390141a2b99a6f77a52beacf1d06aa4e170cba3a98e24c1bc"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c8444e921bfc3757c475c4f4d7416a7aa69b2d992d5114fe55af21411187ab0d"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c1d3ef3878f871abe6826e386c3d61b5292ef5f7946fe646f4206b85836b5da"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d861bf326ee7dabc35c532a40384541578cd1ec1e1b7db9f9ecbba56eb76ca22"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cde6b9d9ba5007077ee321ec722fa714ebc0cbd9a32ccf0f4dd3cc3f20952d71"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bb6546e7b6bed1aefbe24f68a5fb9b891cc5aef61bca6c1a7b1054b7f0359bb"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d8a57261ef7996d5ced7c8cba9189ada3fbeffd1815f70f635e4558d93766cb"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:67201c02efc596923ad950519e0b75ceb78d524177ea557134d6567b9ac2c283"}, + {file = "rapidfuzz-3.9.3.tar.gz", hash = "sha256:b398ea66e8ed50451bce5997c430197d5e4b06ac4aa74602717f792d8d8d06e2"}, ] [package.extras] @@ -2930,13 +2931,13 @@ full = ["numpy"] [[package]] name = "redis" -version = "5.0.4" +version = "5.0.5" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, - {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, + {file = "redis-5.0.5-py3-none-any.whl", hash = "sha256:30b47d4ebb6b7a0b9b40c1275a19b87bb6f46b3bed82a89012cf56dea4024ada"}, + {file = "redis-5.0.5.tar.gz", hash = "sha256:3417688621acf6ee368dec4a04dd95881be24efd34c79f00d31f62bb528800ae"}, ] [package.dependencies] @@ -3082,22 +3083,6 @@ files = [ cryptography = ">=2.0" jeepney = ">=0.6" -[[package]] -name = "setuptools" -version = "69.5.1" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, - {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "shapely" version = "2.0.4" @@ -3358,13 +3343,13 @@ testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-po [[package]] name = "trove-classifiers" -version = "2024.5.17" +version = "2024.5.22" description = "Canonical source for classifiers on PyPI (pypi.org)." optional = false python-versions = "*" files = [ - {file = "trove_classifiers-2024.5.17-py3-none-any.whl", hash = "sha256:2ebdddebd43e749ac6b6e9b9aa158ab489603dff147cba8714787729cdb9ea37"}, - {file = "trove_classifiers-2024.5.17.tar.gz", hash = "sha256:d47a6f1c48803091c3fc81f535fecfeef65b558f2b9e4e83df7a79d17bce8bbf"}, + {file = "trove_classifiers-2024.5.22-py3-none-any.whl", hash = "sha256:c43ade18704823e4afa3d9db7083294bc4708a5e02afbcefacd0e9d03a7a24ef"}, + {file = "trove_classifiers-2024.5.22.tar.gz", hash = "sha256:8a6242bbb5c9ae88d34cf665e816b287d2212973c8777dfaef5ec18d72ac1d03"}, ] [[package]] @@ -3386,13 +3371,13 @@ typing-extensions = ">=3.7.4.3" [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] @@ -3946,18 +3931,18 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.18.2" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.18.2-py3-none-any.whl", hash = "sha256:dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e"}, - {file = "zipp-3.18.2.tar.gz", hash = "sha256:6278d9ddbcfb1f1089a88fde84481528b07b0e10474e09dcfe53dad4069fa059"}, + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0" From e48d34b460480bb96e64c3fbff0c8c6e5de3201e Mon Sep 17 00:00:00 2001 From: "herve.le-bars" Date: Thu, 20 Jun 2024 14:34:29 +0200 Subject: [PATCH 34/34] =?UTF-8?q?feat:=20api=20diminutation=20de=20cache?= =?UTF-8?q?=20=C3=A0=2015=20min?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.template | 2 +- backend/bloom/config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.template b/.env.template index b6429282..24943a43 100644 --- a/.env.template +++ b/.env.template @@ -11,7 +11,7 @@ POSTGRES_PORT=5432 API_PORT=8000 REDIS_HOST=localhost REDIS_PORT=6379 -REDIS_CACHE_EXPIRATION=3600 +REDIS_CACHE_EXPIRATION=900 SPIRE_TOKEN= SLACK_URL= diff --git a/backend/bloom/config.py b/backend/bloom/config.py index 4149de44..a89a4462 100644 --- a/backend/bloom/config.py +++ b/backend/bloom/config.py @@ -47,7 +47,7 @@ class Settings(BaseSettings): redis_host: str = Field(default='localhost') redis_port: int = Field(default=6379) - redis_cache_expiration: int = Field(default=3600) + redis_cache_expiration: int = Field(default=900) logging_level:str=Field( default="INFO",