diff --git a/dockerfile b/dockerfile
index 9337eac..b499ead 100644
--- a/dockerfile
+++ b/dockerfile
@@ -33,4 +33,5 @@ WORKDIR /app
RUN --mount=type=cache,target=/root/.cache \
poetry install --without=dev
+ENV STRAWBERRY_DISABLE_RICH_ERRORS=1
CMD ["poetry", "run", "gunicorn", "main:app", "--bind", "0.0.0.0:8080", "--worker-class", "aiohttp.GunicornWebWorker"]
\ No newline at end of file
diff --git a/justfile b/justfile
index d75e49a..2a337c8 100644
--- a/justfile
+++ b/justfile
@@ -20,7 +20,7 @@ test path="./src/tests" n_workers="8":
docker stop randorm-api-tests-mongo
run-server n_workers="1":
- poetry run gunicorn main:app --bind 0.0.0.0:8080 --workers {{ n_workers }} --worker-class aiohttp.GunicornWebWorker
+ poetry run gunicorn main:app --bind localhost:8080 --workers {{ n_workers }} --worker-class aiohttp.GunicornWebWorker
docker-build:
docker buildx build . -t randorm-api:latest
diff --git a/poetry.lock b/poetry.lock
index 56c27e0..adfc1fc 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -306,63 +306,63 @@ files = [
[[package]]
name = "coverage"
-version = "7.5.4"
+version = "7.6.0"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "coverage-7.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99"},
- {file = "coverage-7.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47"},
- {file = "coverage-7.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2214ee920787d85db1b6a0bd9da5f8503ccc8fcd5814d90796c2f2493a2f4d2e"},
- {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1137f46adb28e3813dec8c01fefadcb8c614f33576f672962e323b5128d9a68d"},
- {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b385d49609f8e9efc885790a5a0e89f2e3ae042cdf12958b6034cc442de428d3"},
- {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b4a474f799456e0eb46d78ab07303286a84a3140e9700b9e154cfebc8f527016"},
- {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5cd64adedf3be66f8ccee418473c2916492d53cbafbfcff851cbec5a8454b136"},
- {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e564c2cf45d2f44a9da56f4e3a26b2236504a496eb4cb0ca7221cd4cc7a9aca9"},
- {file = "coverage-7.5.4-cp310-cp310-win32.whl", hash = "sha256:7076b4b3a5f6d2b5d7f1185fde25b1e54eb66e647a1dfef0e2c2bfaf9b4c88c8"},
- {file = "coverage-7.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:018a12985185038a5b2bcafab04ab833a9a0f2c59995b3cec07e10074c78635f"},
- {file = "coverage-7.5.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db14f552ac38f10758ad14dd7b983dbab424e731588d300c7db25b6f89e335b5"},
- {file = "coverage-7.5.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3257fdd8e574805f27bb5342b77bc65578e98cbc004a92232106344053f319ba"},
- {file = "coverage-7.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a6612c99081d8d6134005b1354191e103ec9705d7ba2754e848211ac8cacc6b"},
- {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d45d3cbd94159c468b9b8c5a556e3f6b81a8d1af2a92b77320e887c3e7a5d080"},
- {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed550e7442f278af76d9d65af48069f1fb84c9f745ae249c1a183c1e9d1b025c"},
- {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a892be37ca35eb5019ec85402c3371b0f7cda5ab5056023a7f13da0961e60da"},
- {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8192794d120167e2a64721d88dbd688584675e86e15d0569599257566dec9bf0"},
- {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:820bc841faa502e727a48311948e0461132a9c8baa42f6b2b84a29ced24cc078"},
- {file = "coverage-7.5.4-cp311-cp311-win32.whl", hash = "sha256:6aae5cce399a0f065da65c7bb1e8abd5c7a3043da9dceb429ebe1b289bc07806"},
- {file = "coverage-7.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:d2e344d6adc8ef81c5a233d3a57b3c7d5181f40e79e05e1c143da143ccb6377d"},
- {file = "coverage-7.5.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:54317c2b806354cbb2dc7ac27e2b93f97096912cc16b18289c5d4e44fc663233"},
- {file = "coverage-7.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:042183de01f8b6d531e10c197f7f0315a61e8d805ab29c5f7b51a01d62782747"},
- {file = "coverage-7.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6bb74ed465d5fb204b2ec41d79bcd28afccf817de721e8a807d5141c3426638"},
- {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3d45ff86efb129c599a3b287ae2e44c1e281ae0f9a9bad0edc202179bcc3a2e"},
- {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5013ed890dc917cef2c9f765c4c6a8ae9df983cd60dbb635df8ed9f4ebc9f555"},
- {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1014fbf665fef86cdfd6cb5b7371496ce35e4d2a00cda501cf9f5b9e6fced69f"},
- {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3684bc2ff328f935981847082ba4fdc950d58906a40eafa93510d1b54c08a66c"},
- {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:581ea96f92bf71a5ec0974001f900db495488434a6928a2ca7f01eee20c23805"},
- {file = "coverage-7.5.4-cp312-cp312-win32.whl", hash = "sha256:73ca8fbc5bc622e54627314c1a6f1dfdd8db69788f3443e752c215f29fa87a0b"},
- {file = "coverage-7.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:cef4649ec906ea7ea5e9e796e68b987f83fa9a718514fe147f538cfeda76d7a7"},
- {file = "coverage-7.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdd31315fc20868c194130de9ee6bfd99755cc9565edff98ecc12585b90be882"},
- {file = "coverage-7.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:02ff6e898197cc1e9fa375581382b72498eb2e6d5fc0b53f03e496cfee3fac6d"},
- {file = "coverage-7.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d05c16cf4b4c2fc880cb12ba4c9b526e9e5d5bb1d81313d4d732a5b9fe2b9d53"},
- {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5986ee7ea0795a4095ac4d113cbb3448601efca7f158ec7f7087a6c705304e4"},
- {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df54843b88901fdc2f598ac06737f03d71168fd1175728054c8f5a2739ac3e4"},
- {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ab73b35e8d109bffbda9a3e91c64e29fe26e03e49addf5b43d85fc426dde11f9"},
- {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:aea072a941b033813f5e4814541fc265a5c12ed9720daef11ca516aeacd3bd7f"},
- {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:16852febd96acd953b0d55fc842ce2dac1710f26729b31c80b940b9afcd9896f"},
- {file = "coverage-7.5.4-cp38-cp38-win32.whl", hash = "sha256:8f894208794b164e6bd4bba61fc98bf6b06be4d390cf2daacfa6eca0a6d2bb4f"},
- {file = "coverage-7.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:e2afe743289273209c992075a5a4913e8d007d569a406ffed0bd080ea02b0633"},
- {file = "coverage-7.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95c3a8cb0463ba9f77383d0fa8c9194cf91f64445a63fc26fb2327e1e1eb088"},
- {file = "coverage-7.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d7564cc09dd91b5a6001754a5b3c6ecc4aba6323baf33a12bd751036c998be4"},
- {file = "coverage-7.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44da56a2589b684813f86d07597fdf8a9c6ce77f58976727329272f5a01f99f7"},
- {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e16f3d6b491c48c5ae726308e6ab1e18ee830b4cdd6913f2d7f77354b33f91c8"},
- {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbc5958cb471e5a5af41b0ddaea96a37e74ed289535e8deca404811f6cb0bc3d"},
- {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a04e990a2a41740b02d6182b498ee9796cf60eefe40cf859b016650147908029"},
- {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ddbd2f9713a79e8e7242d7c51f1929611e991d855f414ca9996c20e44a895f7c"},
- {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b1ccf5e728ccf83acd313c89f07c22d70d6c375a9c6f339233dcf792094bcbf7"},
- {file = "coverage-7.5.4-cp39-cp39-win32.whl", hash = "sha256:56b4eafa21c6c175b3ede004ca12c653a88b6f922494b023aeb1e836df953ace"},
- {file = "coverage-7.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:65e528e2e921ba8fd67d9055e6b9f9e34b21ebd6768ae1c1723f4ea6ace1234d"},
- {file = "coverage-7.5.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:79b356f3dd5b26f3ad23b35c75dbdaf1f9e2450b6bcefc6d0825ea0aa3f86ca5"},
- {file = "coverage-7.5.4.tar.gz", hash = "sha256:a44963520b069e12789d0faea4e9fdb1e410cdc4aab89d94f7f55cbb7fef0353"},
+ {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"},
+ {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"},
+ {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"},
+ {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"},
+ {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"},
+ {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"},
+ {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"},
+ {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"},
+ {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"},
+ {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"},
+ {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"},
+ {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"},
+ {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"},
+ {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"},
+ {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"},
+ {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"},
+ {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"},
+ {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"},
+ {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"},
+ {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"},
+ {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"},
+ {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"},
+ {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"},
+ {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"},
+ {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"},
+ {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"},
+ {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"},
+ {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"},
+ {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"},
+ {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"},
+ {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"},
+ {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"},
+ {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"},
+ {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"},
+ {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"},
+ {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"},
+ {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"},
+ {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"},
+ {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"},
+ {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"},
+ {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"},
+ {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"},
+ {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"},
+ {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"},
+ {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"},
+ {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"},
+ {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"},
+ {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"},
+ {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"},
+ {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"},
+ {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"},
+ {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"},
]
[package.extras]
@@ -585,120 +585,105 @@ files = [
[[package]]
name = "hiredis"
-version = "2.3.2"
+version = "3.0.0"
description = "Python wrapper for hiredis"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "hiredis-2.3.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:742093f33d374098aa21c1696ac6e4874b52658c870513a297a89265a4d08fe5"},
- {file = "hiredis-2.3.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:9e14fb70ca4f7efa924f508975199353bf653f452e4ef0a1e47549e208f943d7"},
- {file = "hiredis-2.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d7302b4b17fcc1cc727ce84ded7f6be4655701e8d58744f73b09cb9ed2b13df"},
- {file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed63e8b75c193c5e5a8288d9d7b011da076cc314fafc3bfd59ec1d8a750d48c8"},
- {file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b4edee59dc089bc3948f4f6fba309f51aa2ccce63902364900aa0a553a85e97"},
- {file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6481c3b7673a86276220140456c2a6fbfe8d1fb5c613b4728293c8634134824"},
- {file = "hiredis-2.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:684840b014ce83541a087fcf2d48227196576f56ae3e944d4dfe14c0a3e0ccb7"},
- {file = "hiredis-2.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c4c0bcf786f0eac9593367b6279e9b89534e008edbf116dcd0de956524702c8"},
- {file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66ab949424ac6504d823cba45c4c4854af5c59306a1531edb43b4dd22e17c102"},
- {file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:322c668ee1c12d6c5750a4b1057e6b4feee2a75b3d25d630922a463cfe5e7478"},
- {file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bfa73e3f163c6e8b2ec26f22285d717a5f77ab2120c97a2605d8f48b26950dac"},
- {file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7f39f28ffc65de577c3bc0c7615f149e35bc927802a0f56e612db9b530f316f9"},
- {file = "hiredis-2.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:55ce31bf4711da879b96d511208efb65a6165da4ba91cb3a96d86d5a8d9d23e6"},
- {file = "hiredis-2.3.2-cp310-cp310-win32.whl", hash = "sha256:3dd63d0bbbe75797b743f35d37a4cca7ca7ba35423a0de742ae2985752f20c6d"},
- {file = "hiredis-2.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:ea002656a8d974daaf6089863ab0a306962c8b715db6b10879f98b781a2a5bf5"},
- {file = "hiredis-2.3.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:adfbf2e9c38b77d0db2fb32c3bdaea638fa76b4e75847283cd707521ad2475ef"},
- {file = "hiredis-2.3.2-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:80b02d27864ebaf9b153d4b99015342382eeaed651f5591ce6f07e840307c56d"},
- {file = "hiredis-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd40d2e2f82a483de0d0a6dfd8c3895a02e55e5c9949610ecbded18188fd0a56"},
- {file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfa904045d7cebfb0f01dad51352551cce1d873d7c3f80c7ded7d42f8cac8f89"},
- {file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28bd184b33e0dd6d65816c16521a4ba1ffbe9ff07d66873c42ea4049a62fed83"},
- {file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f70481213373d44614148f0f2e38e7905be3f021902ae5167289413196de4ba4"},
- {file = "hiredis-2.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8797b528c1ff81eef06713623562b36db3dafa106b59f83a6468df788ff0d1"},
- {file = "hiredis-2.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02fc71c8333586871602db4774d3a3e403b4ccf6446dc4603ec12df563127cee"},
- {file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0da56915bda1e0a49157191b54d3e27689b70960f0685fdd5c415dacdee2fbed"},
- {file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e2674a5a3168349435b08fa0b82998ed2536eb9acccf7087efe26e4cd088a525"},
- {file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:dc1c3fd49930494a67dcec37d0558d99d84eca8eb3f03b17198424538f2608d7"},
- {file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:14c7b43205e515f538a9defb4e411e0f0576caaeeda76bb9993ed505486f7562"},
- {file = "hiredis-2.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7bac7e02915b970c3723a7a7c5df4ba7a11a3426d2a3f181e041aa506a1ff028"},
- {file = "hiredis-2.3.2-cp311-cp311-win32.whl", hash = "sha256:63a090761ddc3c1f7db5e67aa4e247b4b3bb9890080bdcdadd1b5200b8b89ac4"},
- {file = "hiredis-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:70d226ab0306a5b8d408235cabe51d4bf3554c9e8a72d53ce0b3c5c84cf78881"},
- {file = "hiredis-2.3.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:5c614552c6bd1d0d907f448f75550f6b24fb56cbfce80c094908b7990cad9702"},
- {file = "hiredis-2.3.2-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9c431431abf55b64347ddc8df68b3ef840269cb0aa5bc2d26ad9506eb4b1b866"},
- {file = "hiredis-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a45857e87e9d2b005e81ddac9d815a33efd26ec67032c366629f023fe64fb415"},
- {file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e138d141ec5a6ec800b6d01ddc3e5561ce1c940215e0eb9960876bfde7186aae"},
- {file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:387f655444d912a963ab68abf64bf6e178a13c8e4aa945cb27388fd01a02e6f1"},
- {file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4852f4bf88f0e2d9bdf91279892f5740ed22ae368335a37a52b92a5c88691140"},
- {file = "hiredis-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d711c107e83117129b7f8bd08e9820c43ceec6204fff072a001fd82f6d13db9f"},
- {file = "hiredis-2.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92830c16885f29163e1c2da1f3c1edb226df1210ec7e8711aaabba3dd0d5470a"},
- {file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:16b01d9ceae265d4ab9547be0cd628ecaff14b3360357a9d30c029e5ae8b7e7f"},
- {file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5986fb5f380169270a0293bebebd95466a1c85010b4f1afc2727e4d17c452512"},
- {file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:49532d7939cc51f8e99efc326090c54acf5437ed88b9c904cc8015b3c4eda9c9"},
- {file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8f34801b251ca43ad70691fb08b606a2e55f06b9c9fb1fc18fd9402b19d70f7b"},
- {file = "hiredis-2.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7298562a49d95570ab1c7fc4051e72824c6a80e907993a21a41ba204223e7334"},
- {file = "hiredis-2.3.2-cp312-cp312-win32.whl", hash = "sha256:e1d86b75de787481b04d112067a4033e1ecfda2a060e50318a74e4e1c9b2948c"},
- {file = "hiredis-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:6dbfe1887ffa5cf3030451a56a8f965a9da2fa82b7149357752b67a335a05fc6"},
- {file = "hiredis-2.3.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:4fc242e9da4af48714199216eb535b61e8f8d66552c8819e33fc7806bd465a09"},
- {file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e81aa4e9a1fcf604c8c4b51aa5d258e195a6ba81efe1da82dea3204443eba01c"},
- {file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419780f8583ddb544ffa86f9d44a7fcc183cd826101af4e5ffe535b6765f5f6b"},
- {file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6871306d8b98a15e53a5f289ec1106a3a1d43e7ab6f4d785f95fcef9a7bd9504"},
- {file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb0b35b63717ef1e41d62f4f8717166f7c6245064957907cfe177cc144357c"},
- {file = "hiredis-2.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c490191fa1218851f8a80c5a21a05a6f680ac5aebc2e688b71cbfe592f8fec6"},
- {file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4baf4b579b108062e91bd2a991dc98b9dc3dc06e6288db2d98895eea8acbac22"},
- {file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e627d8ef5e100556e09fb44c9571a432b10e11596d3c4043500080ca9944a91a"},
- {file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:ba3dc0af0def8c21ce7d903c59ea1e8ec4cb073f25ece9edaec7f92a286cd219"},
- {file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:56e9b7d6051688ca94e68c0c8a54a243f8db841911b683cedf89a29d4de91509"},
- {file = "hiredis-2.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:380e029bb4b1d34cf560fcc8950bf6b57c2ef0c9c8b7c7ac20b7c524a730fadd"},
- {file = "hiredis-2.3.2-cp37-cp37m-win32.whl", hash = "sha256:948d9f2ca7841794dd9b204644963a4bcd69ced4e959b0d4ecf1b8ce994a6daa"},
- {file = "hiredis-2.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:cfa67afe2269b2d203cd1389c00c5bc35a287cd57860441fb0e53b371ea6a029"},
- {file = "hiredis-2.3.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bcbe47da0aebc00a7cfe3ebdcff0373b86ce2b1856251c003e3d69c9db44b5a7"},
- {file = "hiredis-2.3.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:f2c9c0d910dd3f7df92f0638e7f65d8edd7f442203caf89c62fc79f11b0b73f8"},
- {file = "hiredis-2.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:01b6c24c0840ac7afafbc4db236fd55f56a9a0919a215c25a238f051781f4772"},
- {file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1f567489f422d40c21e53212a73bef4638d9f21043848150f8544ef1f3a6ad1"},
- {file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28adecb308293e705e44087a1c2d557a816f032430d8a2a9bb7873902a1c6d48"},
- {file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27e9619847e9dc70b14b1ad2d0fb4889e7ca18996585c3463cff6c951fd6b10b"},
- {file = "hiredis-2.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a0026cfbf29f07649b0e34509091a2a6016ff8844b127de150efce1c3aff60b"},
- {file = "hiredis-2.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9de7586522e5da6bee83c9cf0dcccac0857a43249cb4d721a2e312d98a684d1"},
- {file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e58494f282215fc461b06709e9a195a24c12ba09570f25bdf9efb036acc05101"},
- {file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3a32b4b76d46f1eb42b24a918d51d8ca52411a381748196241d59a895f7c5c"},
- {file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1979334ccab21a49c544cd1b8d784ffb2747f99a51cb0bd0976eebb517628382"},
- {file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0c0773266e1c38a06e7593bd08870ac1503f5f0ce0f5c63f2b4134b090b5d6a4"},
- {file = "hiredis-2.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bd1cee053416183adcc8e6134704c46c60c3f66b8faaf9e65bf76191ca59a2f7"},
- {file = "hiredis-2.3.2-cp38-cp38-win32.whl", hash = "sha256:5341ce3d01ef3c7418a72e370bf028c7aeb16895e79e115fe4c954fff990489e"},
- {file = "hiredis-2.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:8fc7197ff33047ce43a67851ccf190acb5b05c52fd4a001bb55766358f04da68"},
- {file = "hiredis-2.3.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:f47775e27388b58ce52f4f972f80e45b13c65113e9e6b6bf60148f893871dc9b"},
- {file = "hiredis-2.3.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:9412a06b8a8e09abd6313d96864b6d7713c6003a365995a5c70cfb9209df1570"},
- {file = "hiredis-2.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3020b60e3fc96d08c2a9b011f1c2e2a6bdcc09cb55df93c509b88be5cb791df"},
- {file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53d0f2c59bce399b8010a21bc779b4f8c32d0f582b2284ac8c98dc7578b27bc4"},
- {file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57c0d0c7e308ed5280a4900d4468bbfec51f0e1b4cde1deae7d4e639bc6b7766"},
- {file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d63318ca189fddc7e75f6a4af8eae9c0545863619fb38cfba5f43e81280b286"},
- {file = "hiredis-2.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e741ffe4e2db78a1b9dd6e5d29678ce37fbaaf65dfe132e5b82a794413302ef1"},
- {file = "hiredis-2.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb98038ccd368e0d88bd92ee575c58cfaf33e77f788c36b2a89a84ee1936dc6b"},
- {file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:eae62ed60d53b3561148bcd8c2383e430af38c0deab9f2dd15f8874888ffd26f"},
- {file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca33c175c1cf60222d9c6d01c38fc17ec3a484f32294af781de30226b003e00f"},
- {file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c5f6972d2bdee3cd301d5c5438e31195cf1cabf6fd9274491674d4ceb46914d"},
- {file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a6b54dabfaa5dbaa92f796f0c32819b4636e66aa8e9106c3d421624bd2a2d676"},
- {file = "hiredis-2.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e96cd35df012a17c87ae276196ea8f215e77d6eeca90709eb03999e2d5e3fd8a"},
- {file = "hiredis-2.3.2-cp39-cp39-win32.whl", hash = "sha256:63b99b5ea9fe4f21469fb06a16ca5244307678636f11917359e3223aaeca0b67"},
- {file = "hiredis-2.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:a50c8af811b35b8a43b1590cf890b61ff2233225257a3cad32f43b3ec7ff1b9f"},
- {file = "hiredis-2.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e8bf4444b09419b77ce671088db9f875b26720b5872d97778e2545cd87dba4a"},
- {file = "hiredis-2.3.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bd42d0d45ea47a2f96babd82a659fbc60612ab9423a68e4a8191e538b85542a"},
- {file = "hiredis-2.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80441b55edbef868e2563842f5030982b04349408396e5ac2b32025fb06b5212"},
- {file = "hiredis-2.3.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec444ab8f27562a363672d6a7372bc0700a1bdc9764563c57c5f9efa0e592b5f"},
- {file = "hiredis-2.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f9f606e810858207d4b4287b4ef0dc622c2aa469548bf02b59dcc616f134f811"},
- {file = "hiredis-2.3.2-pp37-pypy37_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c3dde4ca00fe9eee3b76209711f1941bb86db42b8a75d7f2249ff9dfc026ab0e"},
- {file = "hiredis-2.3.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4dd676107a1d3c724a56a9d9db38166ad4cf44f924ee701414751bd18a784a0"},
- {file = "hiredis-2.3.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce42649e2676ad783186264d5ffc788a7612ecd7f9effb62d51c30d413a3eefe"},
- {file = "hiredis-2.3.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e3f8b1733078ac663dad57e20060e16389a60ab542f18a97931f3a2a2dd64a4"},
- {file = "hiredis-2.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:532a84a82156a82529ec401d1c25d677c6543c791e54a263aa139541c363995f"},
- {file = "hiredis-2.3.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d59f88c4daa36b8c38e59ac7bffed6f5d7f68eaccad471484bf587b28ccc478"},
- {file = "hiredis-2.3.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91a14dd95e24dc078204b18b0199226ee44644974c645dc54ee7b00c3157330"},
- {file = "hiredis-2.3.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb777a38797c8c7df0444533119570be18d1a4ce5478dffc00c875684df7bfcb"},
- {file = "hiredis-2.3.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d47c915897a99d0d34a39fad4be97b4b709ab3d0d3b779ebccf2b6024a8c681e"},
- {file = "hiredis-2.3.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:333b5e04866758b11bda5f5315b4e671d15755fc6ed3b7969721bc6311d0ee36"},
- {file = "hiredis-2.3.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c8937f1100435698c18e4da086968c4b5d70e86ea718376f833475ab3277c9aa"},
- {file = "hiredis-2.3.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa45f7d771094b8145af10db74704ab0f698adb682fbf3721d8090f90e42cc49"},
- {file = "hiredis-2.3.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33d5ebc93c39aed4b5bc769f8ce0819bc50e74bb95d57a35f838f1c4378978e0"},
- {file = "hiredis-2.3.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a797d8c7df9944314d309b0d9e1b354e2fa4430a05bb7604da13b6ad291bf959"},
- {file = "hiredis-2.3.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e15a408f71a6c8c87b364f1f15a6cd9c1baca12bbc47a326ac8ab99ec7ad3c64"},
- {file = "hiredis-2.3.2.tar.gz", hash = "sha256:733e2456b68f3f126ddaf2cd500a33b25146c3676b97ea843665717bda0c5d43"},
+ {file = "hiredis-3.0.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:4b182791c41c5eb1d9ed736f0ff81694b06937ca14b0d4dadde5dadba7ff6dae"},
+ {file = "hiredis-3.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:13c275b483a052dd645eb2cb60d6380f1f5215e4c22d6207e17b86be6dd87ffa"},
+ {file = "hiredis-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c1018cc7f12824506f165027eabb302735b49e63af73eb4d5450c66c88f47026"},
+ {file = "hiredis-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83a29cc7b21b746cb6a480189e49f49b2072812c445e66a9e38d2004d496b81c"},
+ {file = "hiredis-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e241fab6332e8fb5f14af00a4a9c6aefa22f19a336c069b7ddbf28ef8341e8d6"},
+ {file = "hiredis-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1fb8de899f0145d6c4d5d4bd0ee88a78eb980a7ffabd51e9889251b8f58f1785"},
+ {file = "hiredis-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b23291951959141173eec10f8573538e9349fa27f47a0c34323d1970bf891ee5"},
+ {file = "hiredis-3.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e421ac9e4b5efc11705a0d5149e641d4defdc07077f748667f359e60dc904420"},
+ {file = "hiredis-3.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:77c8006c12154c37691b24ff293c077300c22944018c3ff70094a33e10c1d795"},
+ {file = "hiredis-3.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:41afc0d3c18b59eb50970479a9c0e5544fb4b95e3a79cf2fbaece6ddefb926fe"},
+ {file = "hiredis-3.0.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:04ccae6dcd9647eae6025425ab64edb4d79fde8b9e6e115ebfabc6830170e3b2"},
+ {file = "hiredis-3.0.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:fe91d62b0594db5ea7d23fc2192182b1a7b6973f628a9b8b2e0a42a2be721ac6"},
+ {file = "hiredis-3.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:99516d99316062824a24d145d694f5b0d030c80da693ea6f8c4ecf71a251d8bb"},
+ {file = "hiredis-3.0.0-cp310-cp310-win32.whl", hash = "sha256:562eaf820de045eb487afaa37e6293fe7eceb5b25e158b5a1974b7e40bf04543"},
+ {file = "hiredis-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a1c81c89ed765198da27412aa21478f30d54ef69bf5e4480089d9c3f77b8f882"},
+ {file = "hiredis-3.0.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:4664dedcd5933364756d7251a7ea86d60246ccf73a2e00912872dacbfcef8978"},
+ {file = "hiredis-3.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:47de0bbccf4c8a9f99d82d225f7672b9dd690d8fd872007b933ef51a302c9fa6"},
+ {file = "hiredis-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e43679eca508ba8240d016d8cca9d27342d70184773c15bea78a23c87a1922f1"},
+ {file = "hiredis-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13c345e7278c210317e77e1934b27b61394fee0dec2e8bd47e71570900f75823"},
+ {file = "hiredis-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00018f22f38530768b73ea86c11f47e8d4df65facd4e562bd78773bd1baef35e"},
+ {file = "hiredis-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ea3a86405baa8eb0d3639ced6926ad03e07113de54cb00fd7510cb0db76a89d"},
+ {file = "hiredis-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c073848d2b1d5561f3903879ccf4e1a70c9b1e7566c7bdcc98d082fa3e7f0a1d"},
+ {file = "hiredis-3.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a8dffb5f5b3415a4669d25de48b617fd9d44b0bccfc4c2ab24b06406ecc9ecb"},
+ {file = "hiredis-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:22c17c96143c2a62dfd61b13803bc5de2ac526b8768d2141c018b965d0333b66"},
+ {file = "hiredis-3.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c3ece960008dab66c6b8bb3a1350764677ee7c74ccd6270aaf1b1caf9ccebb46"},
+ {file = "hiredis-3.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f75999ae00a920f7dce6ecae76fa5e8674a3110e5a75f12c7a2c75ae1af53396"},
+ {file = "hiredis-3.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e069967cbd5e1900aafc4b5943888f6d34937fc59bf8918a1a546cb729b4b1e4"},
+ {file = "hiredis-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0aacc0a78e1d94d843a6d191f224a35893e6bdfeb77a4a89264155015c65f126"},
+ {file = "hiredis-3.0.0-cp311-cp311-win32.whl", hash = "sha256:719c32147ba29528cb451f037bf837dcdda4ff3ddb6cdb12c4216b0973174718"},
+ {file = "hiredis-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:bdc144d56333c52c853c31b4e2e52cfbdb22d3da4374c00f5f3d67c42158970f"},
+ {file = "hiredis-3.0.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:484025d2eb8f6348f7876fc5a2ee742f568915039fcb31b478fd5c242bb0fe3a"},
+ {file = "hiredis-3.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:fcdb552ffd97151dab8e7bc3ab556dfa1512556b48a367db94b5c20253a35ee1"},
+ {file = "hiredis-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bb6f9fd92f147ba11d338ef5c68af4fd2908739c09e51f186e1d90958c68cc1"},
+ {file = "hiredis-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa86bf9a0ed339ec9e8a9a9d0ae4dccd8671625c83f9f9f2640729b15e07fbfd"},
+ {file = "hiredis-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e194a0d5df9456995d8f510eab9f529213e7326af6b94770abf8f8b7952ddcaa"},
+ {file = "hiredis-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a1df39d74ec507d79c7a82c8063eee60bf80537cdeee652f576059b9cdd15c"},
+ {file = "hiredis-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f91456507427ba36fd81b2ca11053a8e112c775325acc74e993201ea912d63e9"},
+ {file = "hiredis-3.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9862db92ef67a8a02e0d5370f07d380e14577ecb281b79720e0d7a89aedb9ee5"},
+ {file = "hiredis-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d10fcd9e0eeab835f492832b2a6edb5940e2f1230155f33006a8dfd3bd2c94e4"},
+ {file = "hiredis-3.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:48727d7d405d03977d01885f317328dc21d639096308de126c2c4e9950cbd3c9"},
+ {file = "hiredis-3.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e0bb6102ebe2efecf8a3292c6660a0e6fac98176af6de67f020bea1c2343717"},
+ {file = "hiredis-3.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:df274e3abb4df40f4c7274dd3e587dfbb25691826c948bc98d5fead019dfb001"},
+ {file = "hiredis-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:034925b5fb514f7b11aac38cd55b3fd7e9d3af23bd6497f3f20aa5b8ba58e232"},
+ {file = "hiredis-3.0.0-cp312-cp312-win32.whl", hash = "sha256:120f2dda469b28d12ccff7c2230225162e174657b49cf4cd119db525414ae281"},
+ {file = "hiredis-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:e584fe5f4e6681d8762982be055f1534e0170f6308a7a90f58d737bab12ff6a8"},
+ {file = "hiredis-3.0.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:122171ff47d96ed8dd4bba6c0e41d8afaba3e8194949f7720431a62aa29d8895"},
+ {file = "hiredis-3.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:ba9fc605ac558f0de67463fb588722878641e6fa1dabcda979e8e69ff581d0bd"},
+ {file = "hiredis-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a631e2990b8be23178f655cae8ac6c7422af478c420dd54e25f2e26c29e766f1"},
+ {file = "hiredis-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63482db3fadebadc1d01ad33afa6045ebe2ea528eb77ccaabd33ee7d9c2bad48"},
+ {file = "hiredis-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f669212c390eebfbe03c4e20181f5970b82c5d0a0ad1df1785f7ffbe7d61150"},
+ {file = "hiredis-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a49ef161739f8018c69b371528bdb47d7342edfdee9ddc75a4d8caddf45a6e"},
+ {file = "hiredis-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98a152052b8878e5e43a2e3a14075218adafc759547c98668a21e9485882696c"},
+ {file = "hiredis-3.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50a196af0ce657fcde9bf8a0bbe1032e22c64d8fcec2bc926a35e7ff68b3a166"},
+ {file = "hiredis-3.0.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f2f312eef8aafc2255e3585dcf94d5da116c43ef837db91db9ecdc1bc930072d"},
+ {file = "hiredis-3.0.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:6ca41fa40fa019cde42c21add74aadd775e71458051a15a352eabeb12eb4d084"},
+ {file = "hiredis-3.0.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:6eecb343c70629f5af55a8b3e53264e44fa04e155ef7989de13668a0cb102a90"},
+ {file = "hiredis-3.0.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:c3fdad75e7837a475900a1d3a5cc09aa024293c3b0605155da2d42f41bc0e482"},
+ {file = "hiredis-3.0.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8854969e7480e8d61ed7549eb232d95082a743e94138d98d7222ba4e9f7ecacd"},
+ {file = "hiredis-3.0.0-cp38-cp38-win32.whl", hash = "sha256:f114a6c86edbf17554672b050cce72abf489fe58d583c7921904d5f1c9691605"},
+ {file = "hiredis-3.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:7d99b91e42217d7b4b63354b15b41ce960e27d216783e04c4a350224d55842a4"},
+ {file = "hiredis-3.0.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:4c6efcbb5687cf8d2aedcc2c3ed4ac6feae90b8547427d417111194873b66b06"},
+ {file = "hiredis-3.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5b5cff42a522a0d81c2ae7eae5e56d0ee7365e0c4ad50c4de467d8957aff4414"},
+ {file = "hiredis-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:82f794d564f4bc76b80c50b03267fe5d6589e93f08e66b7a2f674faa2fa76ebc"},
+ {file = "hiredis-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7a4c1791d7aa7e192f60fe028ae409f18ccdd540f8b1e6aeb0df7816c77e4a4"},
+ {file = "hiredis-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2537b2cd98192323fce4244c8edbf11f3cac548a9d633dbbb12b48702f379f4"},
+ {file = "hiredis-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fed69bbaa307040c62195a269f82fc3edf46b510a17abb6b30a15d7dab548df"},
+ {file = "hiredis-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:869f6d5537d243080f44253491bb30aa1ec3c21754003b3bddeadedeb65842b0"},
+ {file = "hiredis-3.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d435ae89073d7cd51e6b6bf78369c412216261c9c01662e7008ff00978153729"},
+ {file = "hiredis-3.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:204b79b30a0e6be0dc2301a4d385bb61472809f09c49f400497f1cdd5a165c66"},
+ {file = "hiredis-3.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3ea635101b739c12effd189cc19b2671c268abb03013fd1f6321ca29df3ca625"},
+ {file = "hiredis-3.0.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:f359175197fd833c8dd7a8c288f1516be45415bb5c939862ab60c2918e1e1943"},
+ {file = "hiredis-3.0.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ac6d929cb33dd12ad3424b75725975f0a54b5b12dbff95f2a2d660c510aa106d"},
+ {file = "hiredis-3.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:100431e04d25a522ef2c3b94f294c4219c4de3bfc7d557b6253296145a144c11"},
+ {file = "hiredis-3.0.0-cp39-cp39-win32.whl", hash = "sha256:e1a9c14ae9573d172dc050a6f63a644457df5d01ec4d35a6a0f097f812930f83"},
+ {file = "hiredis-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:54a6dd7b478e6eb01ce15b3bb5bf771e108c6c148315bf194eb2ab776a3cac4d"},
+ {file = "hiredis-3.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:50da7a9edf371441dfcc56288d790985ee9840d982750580710a9789b8f4a290"},
+ {file = "hiredis-3.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9b285ef6bf1581310b0d5e8f6ce64f790a1c40e89c660e1320b35f7515433672"},
+ {file = "hiredis-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0dcfa684966f25b335072115de2f920228a3c2caf79d4bfa2b30f6e4f674a948"},
+ {file = "hiredis-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a41be8af1fd78ca97bc948d789a09b730d1e7587d07ca53af05758f31f4b985d"},
+ {file = "hiredis-3.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:038756db735e417ab36ee6fd7725ce412385ed2bd0767e8179a4755ea11b804f"},
+ {file = "hiredis-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:fcecbd39bd42cef905c0b51c9689c39d0cc8b88b1671e7f40d4fb213423aef3a"},
+ {file = "hiredis-3.0.0-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a131377493a59fb0f5eaeb2afd49c6540cafcfba5b0b3752bed707be9e7c4eaf"},
+ {file = "hiredis-3.0.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d22c53f0ec5c18ecb3d92aa9420563b1c5d657d53f01356114978107b00b860"},
+ {file = "hiredis-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8a91e9520fbc65a799943e5c970ffbcd67905744d8becf2e75f9f0a5e8414f0"},
+ {file = "hiredis-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dc8043959b50141df58ab4f398e8ae84c6f9e673a2c9407be65fc789138f4a6"},
+ {file = "hiredis-3.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51b99cfac514173d7b8abdfe10338193e8a0eccdfe1870b646009d2fb7cbe4b5"},
+ {file = "hiredis-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:fa1fcad89d8a41d8dc10b1e54951ec1e161deabd84ed5a2c95c3c7213bdb3514"},
+ {file = "hiredis-3.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:898636a06d9bf575d2c594129085ad6b713414038276a4bfc5db7646b8a5be78"},
+ {file = "hiredis-3.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:466f836dbcf86de3f9692097a7a01533dc9926986022c6617dc364a402b265c5"},
+ {file = "hiredis-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23142a8af92a13fc1e3f2ca1d940df3dcf2af1d176be41fe8d89e30a837a0b60"},
+ {file = "hiredis-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:793c80a3d6b0b0e8196a2d5de37a08330125668c8012922685e17aa9108c33ac"},
+ {file = "hiredis-3.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:467d28112c7faa29b7db743f40803d927c8591e9da02b6ce3d5fadc170a542a2"},
+ {file = "hiredis-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:dc384874a719c767b50a30750f937af18842ee5e288afba95a5a3ed703b1515a"},
+ {file = "hiredis-3.0.0.tar.gz", hash = "sha256:fed8581ae26345dea1f1e0d1a96e05041a727a45e7d8d459164583e23c6ac441"},
]
[[package]]
@@ -946,13 +931,13 @@ files = [
[[package]]
name = "motor"
-version = "3.5.0"
+version = "3.5.1"
description = "Non-blocking MongoDB driver for Tornado or asyncio"
optional = false
python-versions = ">=3.8"
files = [
- {file = "motor-3.5.0-py3-none-any.whl", hash = "sha256:e8f1d7a3370e8dd30eb4c68aaaee46dc608fbac70a757e58f3e828124f5e7693"},
- {file = "motor-3.5.0.tar.gz", hash = "sha256:2b38e405e5a0c52d499edb8d23fa029debdf0158da092c21b44d92cac7f59942"},
+ {file = "motor-3.5.1-py3-none-any.whl", hash = "sha256:f95a9ea0f011464235e0bd72910baa291db3a6009e617ac27b82f57885abafb8"},
+ {file = "motor-3.5.1.tar.gz", hash = "sha256:1622bd7b39c3e6375607c14736f6e1d498128eadf6f5f93f8786cf17d37062ac"},
]
[package.dependencies]
@@ -1069,43 +1054,43 @@ files = [
[[package]]
name = "mypy"
-version = "1.10.1"
+version = "1.11.0"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.8"
files = [
- {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"},
- {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"},
- {file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"},
- {file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"},
- {file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"},
- {file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"},
- {file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"},
- {file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"},
- {file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"},
- {file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"},
- {file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"},
- {file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"},
- {file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"},
- {file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"},
- {file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"},
- {file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"},
- {file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"},
- {file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"},
- {file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"},
- {file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"},
- {file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"},
- {file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"},
- {file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"},
- {file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"},
- {file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"},
- {file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"},
- {file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"},
+ {file = "mypy-1.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3824187c99b893f90c845bab405a585d1ced4ff55421fdf5c84cb7710995229"},
+ {file = "mypy-1.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96f8dbc2c85046c81bcddc246232d500ad729cb720da4e20fce3b542cab91287"},
+ {file = "mypy-1.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a5d8d8dd8613a3e2be3eae829ee891b6b2de6302f24766ff06cb2875f5be9c6"},
+ {file = "mypy-1.11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72596a79bbfb195fd41405cffa18210af3811beb91ff946dbcb7368240eed6be"},
+ {file = "mypy-1.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:35ce88b8ed3a759634cb4eb646d002c4cef0a38f20565ee82b5023558eb90c00"},
+ {file = "mypy-1.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:98790025861cb2c3db8c2f5ad10fc8c336ed2a55f4daf1b8b3f877826b6ff2eb"},
+ {file = "mypy-1.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:25bcfa75b9b5a5f8d67147a54ea97ed63a653995a82798221cca2a315c0238c1"},
+ {file = "mypy-1.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bea2a0e71c2a375c9fa0ede3d98324214d67b3cbbfcbd55ac8f750f85a414e3"},
+ {file = "mypy-1.11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d2b3d36baac48e40e3064d2901f2fbd2a2d6880ec6ce6358825c85031d7c0d4d"},
+ {file = "mypy-1.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:d8e2e43977f0e09f149ea69fd0556623919f816764e26d74da0c8a7b48f3e18a"},
+ {file = "mypy-1.11.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1d44c1e44a8be986b54b09f15f2c1a66368eb43861b4e82573026e04c48a9e20"},
+ {file = "mypy-1.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cea3d0fb69637944dd321f41bc896e11d0fb0b0aa531d887a6da70f6e7473aba"},
+ {file = "mypy-1.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a83ec98ae12d51c252be61521aa5731f5512231d0b738b4cb2498344f0b840cd"},
+ {file = "mypy-1.11.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7b73a856522417beb78e0fb6d33ef89474e7a622db2653bc1285af36e2e3e3d"},
+ {file = "mypy-1.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:f2268d9fcd9686b61ab64f077be7ffbc6fbcdfb4103e5dd0cc5eaab53a8886c2"},
+ {file = "mypy-1.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:940bfff7283c267ae6522ef926a7887305945f716a7704d3344d6d07f02df850"},
+ {file = "mypy-1.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:14f9294528b5f5cf96c721f231c9f5b2733164e02c1c018ed1a0eff8a18005ac"},
+ {file = "mypy-1.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7b54c27783991399046837df5c7c9d325d921394757d09dbcbf96aee4649fe9"},
+ {file = "mypy-1.11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:65f190a6349dec29c8d1a1cd4aa71284177aee5949e0502e6379b42873eddbe7"},
+ {file = "mypy-1.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:dbe286303241fea8c2ea5466f6e0e6a046a135a7e7609167b07fd4e7baf151bf"},
+ {file = "mypy-1.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:104e9c1620c2675420abd1f6c44bab7dd33cc85aea751c985006e83dcd001095"},
+ {file = "mypy-1.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f006e955718ecd8d159cee9932b64fba8f86ee6f7728ca3ac66c3a54b0062abe"},
+ {file = "mypy-1.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:becc9111ca572b04e7e77131bc708480cc88a911adf3d0239f974c034b78085c"},
+ {file = "mypy-1.11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6801319fe76c3f3a3833f2b5af7bd2c17bb93c00026a2a1b924e6762f5b19e13"},
+ {file = "mypy-1.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1a184c64521dc549324ec6ef7cbaa6b351912be9cb5edb803c2808a0d7e85ac"},
+ {file = "mypy-1.11.0-py3-none-any.whl", hash = "sha256:56913ec8c7638b0091ef4da6fcc9136896914a9d60d54670a75880c3e5b99ace"},
+ {file = "mypy-1.11.0.tar.gz", hash = "sha256:93743608c7348772fdc717af4aeee1997293a1ad04bc0ea6efa15bf65385c538"},
]
[package.dependencies]
mypy-extensions = ">=1.0.0"
-typing-extensions = ">=4.1.0"
+typing-extensions = ">=4.6.0"
[package.extras]
dmypy = ["psutil (>=4.0)"]
@@ -1535,13 +1520,13 @@ zstd = ["zstandard"]
[[package]]
name = "pyright"
-version = "1.1.371"
+version = "1.1.372"
description = "Command line wrapper for pyright"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pyright-1.1.371-py3-none-any.whl", hash = "sha256:cce52e42ff73943243e7e5e24f2a59dee81b97d99f4e3cf97370b27e8a1858cd"},
- {file = "pyright-1.1.371.tar.gz", hash = "sha256:777b508b92dda2db476214c400ce043aad8d8f3dd0e10d284c96e79f298308b5"},
+ {file = "pyright-1.1.372-py3-none-any.whl", hash = "sha256:25b15fb8967740f0949fd35b963777187f0a0404c0bd753cc966ec139f3eaa0b"},
+ {file = "pyright-1.1.372.tar.gz", hash = "sha256:a9f5e0daa955daaa17e3d1ef76d3623e75f8afd5e37b437d3ff84d5b38c15420"},
]
[package.dependencies]
@@ -2015,15 +2000,102 @@ files = [
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
+[[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 = "uvicorn"
-version = "0.30.1"
+version = "0.30.3"
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"},
+ {file = "uvicorn-0.30.3-py3-none-any.whl", hash = "sha256:94a3608da0e530cea8f69683aa4126364ac18e3826b6630d1a65f4638aade503"},
+ {file = "uvicorn-0.30.3.tar.gz", hash = "sha256:0d114d0831ff1adbf231d358cbf42f17333413042552a624ea6a9b4c33dcfd81"},
]
[package.dependencies]
@@ -2184,4 +2256,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.12"
-content-hash = "97f35974348b80857746749fa1c58c6a71cad4c7f3fc1672ca3ca031755704db"
+content-hash = "87ba44d67c9daf13a8902f5e46a3baa30877fdc641f21596ba658023871dbd6e"
diff --git a/pyproject.toml b/pyproject.toml
index a3e2597..659a028 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,6 +24,7 @@ loguru = "^0.7.2"
redis = { extras = ["hiredis"], version = "^5.0.7" }
strawberry-graphql = { extras = ["debug-server"], version = "^0.236.0" }
gunicorn = "^22.0.0"
+ujson = "^5.10.0"
[tool.poetry.group.dev.dependencies]
black = "^24.4.2" # formatter
diff --git a/src/adapter/external/auth/telegram.py b/src/adapter/external/auth/telegram.py
index b362d4b..1464acb 100644
--- a/src/adapter/external/auth/telegram.py
+++ b/src/adapter/external/auth/telegram.py
@@ -16,6 +16,9 @@
from src.protocol.external.auth.oauth import OAuthContainer, OAuthDTO, OauthProtocol
from src.protocol.internal.database.user import CreateUser, ReadUser
from src.service.user import UserService
+from src.utils.logger.logger import Logger
+
+log = Logger("telegram-auth-adapter")
class TgUserProfileMixin(Profile): ...
@@ -94,30 +97,43 @@ def __check_hash(
data.to_data_string().encode(),
hashlib.sha256,
)
+
if signing.hexdigest() != data.hash:
+ log.error("callback data validation faiked: hash mismatch")
raise auth_exception.InvalidCredentialsException(
"data is malformed since the hash does not match"
)
+ log.debug("callback data validation passed")
+
async def register(self, data: Any) -> TgOauthContainer:
try:
+ log.debug("building callback data from custom data")
request: TgOauthRegisterCallback = TgOauthRegisterCallback.model_validate(
data, from_attributes=True
)
+
+ log.debug("checking callback data hash")
self.__check_hash(request)
+ log.debug(f"creating new user with telegram_id={request.id}")
user = await self.__service.create(
CreateUser(telegram_id=request.id, profile=request.profile)
)
except (ValidationError, database_exception.ReflectUserException) as e:
+ log.error(
+ f"failed to build callback data or reflect user data to create user with exception: {e}"
+ )
raise auth_exception.InvalidCredentialsException(
"failed to reflect user data to create user"
) from e
except service_exception.CreateUserException as e:
+ log.error(f"creating new user failed with service exception: {e}")
raise auth_exception.UserAlreadyExistsException(
"creating new user failed"
) from e
except auth_exception.AuthException as e:
+ log.error(f"authentiocation failed with auth exception: {e}")
raise e
return TgOauthContainer.construct(
@@ -126,17 +142,25 @@ async def register(self, data: Any) -> TgOauthContainer:
async def login(self, data: Any) -> TgOauthContainer:
try:
+ log.debug("building callback data from custom data")
request = TgOauthLoginCallback.model_validate(data, from_attributes=True)
+
+ log.debug("checking callback data hash")
self.__check_hash(request)
user = await self.__service.find_by_telegram_id(request.id)
except (ValidationError, database_exception.ReflectUserException) as e:
+ log.error(
+ "failed to build callback data or reflect user data to read user with exception: {e}"
+ )
raise auth_exception.InvalidCredentialsException(
"failed to reflect user data to read user"
) from e
except service_exception.ReadUserException as e:
+ log.error(f"reading user failed with service exception: {e}")
raise auth_exception.UserNotFoundException("reading user failed") from e
except auth_exception.AuthException as e:
+ log.error(f"authentiocation failed with auth exception: {e}")
raise e
return TgOauthContainer.construct(
@@ -146,19 +170,32 @@ async def login(self, data: Any) -> TgOauthContainer:
async def retrieve_user(self, data: TgOauthContainer) -> User:
try:
if not isinstance(data, TgOauthContainer):
+ log.error(
+ "invalid data type was passed to retrieve user function. "
+ f"expected TgOauthContainer, got {type(data)}"
+ )
raise auth_exception.InvalidCredentialsException("invalid data type")
try:
+ log.debug("building dto from container")
dto = data.to_dto(self.__jwt_secret)
except Exception as e:
+ log.error(f"failed to build dto from container with exception: {e}")
raise auth_exception.InvalidCredentialsException(
"invalid data type"
) from e
user = await self.__service.read(ReadUser(_id=dto.id))
except (ValidationError, AttributeError) as e:
+ log.error(
+ f"failed to construct dto or reflect to read user with exception: {e}"
+ )
raise auth_exception.InvalidCredentialsException("invalid data type") from e
except service_exception.ReadUserException as e:
+ log.error(f"reading user failed with service exception: {e}")
raise auth_exception.UserNotFoundException("user not found") from e
else:
+ log.debug(
+ f"user id={user.id}, telegram_id={user.telegram_id} was retrieved"
+ )
return user
diff --git a/src/adapter/external/graphql/__init__.py b/src/adapter/external/graphql/__init__.py
index 951947f..4b34652 100644
--- a/src/adapter/external/graphql/__init__.py
+++ b/src/adapter/external/graphql/__init__.py
@@ -4,8 +4,8 @@
from src.adapter.external.graphql import (
operation,
- query,
scalar,
+ schema,
tool,
type,
update,
diff --git a/src/adapter/external/graphql/operation/allocation.py b/src/adapter/external/graphql/operation/allocation.py
index bf64f8c..79bdf9b 100644
--- a/src/adapter/external/graphql/operation/allocation.py
+++ b/src/adapter/external/graphql/operation/allocation.py
@@ -9,6 +9,9 @@
from src.adapter.external.graphql import scalar
from src.adapter.external.graphql.tool.context import Info
from src.adapter.external.graphql.tool.permission import DefaultPermissions
+from src.utils.logger.logger import Logger
+
+log = Logger("graphql-allocation-ops")
@sb.type
@@ -17,33 +20,39 @@ class AllocationQuery:
async def allocation(
root: AllocationQuery, info: Info[AllocationQuery], id: scalar.ObjectID
) -> graphql.AllocationType: # type: ignore
- return await info.context.allocation.loader.load(id)
+ with log.activity(f"loading allocation {id}"):
+ return await info.context.allocation.loader.load(id)
+
+@sb.type
+class AllocationMutation:
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_creating_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
name: str,
creator_id: scalar.ObjectID,
due: datetime | None = None,
form_fields_ids: list[scalar.ObjectID] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.CreatingAllocationType:
- request = proto.CreateCreatingAllocation(
- name=name,
- creator_id=creator_id,
- due=due,
- form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.allocation.service.create(request)
- return graphql.domain_to_allocation(data)
+ with log.activity("creating new allocation with state CREATING"):
+ request = proto.CreateCreatingAllocation(
+ name=name,
+ creator_id=creator_id,
+ due=due,
+ form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.allocation.service.create(request)
+ log.info(f"created allocation {data.id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_created_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
name: str,
creator_id: scalar.ObjectID,
participants_ids: list[scalar.ObjectID],
@@ -51,22 +60,24 @@ async def new_created_allocation(
form_fields_ids: list[scalar.ObjectID] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.CreatedAllocationType:
- request = proto.CreateCreatedAllocation(
- name=name,
- creator_id=creator_id,
- participants_ids=set(participants_ids),
- due=due,
- form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.allocation.service.create(request)
- return graphql.domain_to_allocation(data)
+ with log.activity("creating new allocation with state CREATED"):
+ request = proto.CreateCreatedAllocation(
+ name=name,
+ creator_id=creator_id,
+ participants_ids=set(participants_ids),
+ due=due,
+ form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.allocation.service.create(request)
+ log.info(f"created allocation {data.id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_open_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
name: str,
creator_id: scalar.ObjectID,
participants_ids: list[scalar.ObjectID],
@@ -74,22 +85,24 @@ async def new_open_allocation(
form_fields_ids: list[scalar.ObjectID] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.OpenAllocationType:
- request = proto.CreateOpenAllocation(
- name=name,
- creator_id=creator_id,
- participants_ids=set(participants_ids),
- due=due,
- form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.allocation.service.create(request)
- return graphql.domain_to_allocation(data)
+ with log.activity("creating new allocation with state OPEN"):
+ request = proto.CreateOpenAllocation(
+ name=name,
+ creator_id=creator_id,
+ participants_ids=set(participants_ids),
+ due=due,
+ form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.allocation.service.create(request)
+ log.info(f"created allocation {data.id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_rooming_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
name: str,
creator_id: scalar.ObjectID,
participants_ids: list[scalar.ObjectID],
@@ -97,22 +110,24 @@ async def new_rooming_allocation(
form_fields_ids: list[scalar.ObjectID] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.RoomingAllocationType:
- request = proto.CreateRoomingAllocation(
- name=name,
- creator_id=creator_id,
- participants_ids=set(participants_ids),
- due=due,
- form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.allocation.service.create(request)
- return graphql.domain_to_allocation(data)
+ with log.activity("creating new allocation with state ROOMING"):
+ request = proto.CreateRoomingAllocation(
+ name=name,
+ creator_id=creator_id,
+ participants_ids=set(participants_ids),
+ due=due,
+ form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.allocation.service.create(request)
+ log.info(f"created allocation {data.id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_roomed_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
name: str,
creator_id: scalar.ObjectID,
participants_ids: list[scalar.ObjectID],
@@ -120,22 +135,24 @@ async def new_roomed_allocation(
form_fields_ids: list[scalar.ObjectID] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.RoomedAllocationType:
- request = proto.CreateRoomedAllocation(
- name=name,
- creator_id=creator_id,
- participants_ids=set(participants_ids),
- due=due,
- form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.allocation.service.create(request)
- return graphql.domain_to_allocation(data)
+ with log.activity("creating new allocation with state ROOMED"):
+ request = proto.CreateRoomedAllocation(
+ name=name,
+ creator_id=creator_id,
+ participants_ids=set(participants_ids),
+ due=due,
+ form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.allocation.service.create(request)
+ log.info(f"created allocation {data.id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_closed_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
name: str,
creator_id: scalar.ObjectID,
participants_ids: list[scalar.ObjectID],
@@ -143,22 +160,24 @@ async def new_closed_allocation(
form_fields_ids: list[scalar.ObjectID] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.ClosedAllocationType:
- request = proto.CreateClosedAllocation(
- name=name,
- creator_id=creator_id,
- participants_ids=set(participants_ids),
- due=due,
- form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.allocation.service.create(request)
- return graphql.domain_to_allocation(data)
+ with log.activity("creating new allocation with state CLOSED"):
+ request = proto.CreateClosedAllocation(
+ name=name,
+ creator_id=creator_id,
+ participants_ids=set(participants_ids),
+ due=due,
+ form_fields_ids=set(form_fields_ids) if form_fields_ids else set(),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.allocation.service.create(request)
+ log.info(f"created allocation {data.id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def update_allocation(
- root: AllocationQuery,
- info: Info[AllocationQuery],
+ root: AllocationMutation,
+ info: Info[AllocationMutation],
id: scalar.ObjectID,
name: str | None = None,
due: datetime | None = None,
@@ -168,28 +187,32 @@ async def update_allocation(
editors_ids: list[scalar.ObjectID] | None = None,
participants_ids: list[scalar.ObjectID] | None = None,
) -> graphql.AllocationType: # type: ignore
- request = proto.UpdateAllocation.model_validate(
- {
- "_id": id,
- "name": name,
- "due": due,
- "state": state,
- "form_fields_ids": form_fields_ids,
- "creator_id": creator_id,
- "editors_ids": editors_ids,
- "participants_ids": participants_ids,
- }
- )
- data = await info.context.allocation.service.update(request)
- info.context.allocation.loader.clear(id)
- return graphql.domain_to_allocation(data)
+ with log.activity(f"updating allocation {id}"):
+ request = proto.UpdateAllocation.model_validate(
+ {
+ "_id": id,
+ "name": name,
+ "due": due,
+ "state": state,
+ "form_fields_ids": form_fields_ids,
+ "creator_id": creator_id,
+ "editors_ids": editors_ids,
+ "participants_ids": participants_ids,
+ }
+ )
+ data = await info.context.allocation.service.update(request)
+ info.context.allocation.loader.clear(id)
+ log.info(f"updated allocation {id}")
+ return graphql.domain_to_allocation(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def delete_allocation(
- root: AllocationQuery, info: Info[AllocationQuery], id: scalar.ObjectID
+ root: AllocationMutation, info: Info[AllocationMutation], id: scalar.ObjectID
) -> graphql.AllocationType: # type: ignore
- data = await info.context.allocation.service.delete(
- proto.DeleteAllocation(_id=id)
- )
- info.context.allocation.loader.clear(id)
- return graphql.domain_to_allocation(data)
+ with log.activity(f"deleting allocation {id}"):
+ data = await info.context.allocation.service.delete(
+ proto.DeleteAllocation(_id=id)
+ )
+ info.context.allocation.loader.clear(id)
+ log.info(f"deleted allocation {id}")
+ return graphql.domain_to_allocation(data)
diff --git a/src/adapter/external/graphql/operation/form_field.py b/src/adapter/external/graphql/operation/form_field.py
index 646f207..060c4ab 100644
--- a/src/adapter/external/graphql/operation/form_field.py
+++ b/src/adapter/external/graphql/operation/form_field.py
@@ -12,6 +12,9 @@
from src.adapter.external.graphql.tool.context import Info
from src.adapter.external.graphql.tool.permission import DefaultPermissions
from src.adapter.external.graphql.type import format_entity
+from src.utils.logger.logger import Logger
+
+log = Logger("graphql-form-ops")
@sb.input
@@ -113,12 +116,16 @@ class FormFieldQuery:
async def form_field(
root: FormFieldQuery, info: Info[FormFieldQuery], id: scalar.ObjectID
) -> graphql.FormFieldType: # type: ignore
- return await info.context.form_field.loader.load(id)
+ with log.activity(f"loading form field {id}"):
+ return await info.context.form_field.loader.load(id)
+
+@sb.type
+class FormFieldMutation:
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_text_form_field(
- root: FormFieldQuery,
- info: Info[FormFieldQuery],
+ root: FormFieldMutation,
+ info: Info[FormFieldMutation],
creator_id: scalar.ObjectID,
allocation_id: scalar.ObjectID,
question: str,
@@ -129,29 +136,31 @@ async def new_text_form_field(
re: str | None = None,
ex: str | None = None,
) -> graphql.TextFormFieldType:
- request = proto.CreateTextFormField(
- creator_id=creator_id,
- allocation_id=allocation_id,
- question=question,
- required=required,
- frozen=frozen,
- question_entities=(
- format_entities_to_domain_set(question_entities)
- if question_entities
- else set()
- ),
- editors_ids=set(editors_ids) if editors_ids else set(),
- re=re_compile(re) if re else None,
- ex=ex,
- )
-
- data = await info.context.form_field.service.create(request)
- return graphql.domain_to_form_field(data)
+ with log.activity("creating new text form field"):
+ request = proto.CreateTextFormField(
+ creator_id=creator_id,
+ allocation_id=allocation_id,
+ question=question,
+ required=required,
+ frozen=frozen,
+ question_entities=(
+ format_entities_to_domain_set(question_entities)
+ if question_entities
+ else set()
+ ),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ re=re_compile(re) if re else None,
+ ex=ex,
+ )
+
+ data = await info.context.form_field.service.create(request)
+ log.info(f"created text form field {data.id}")
+ return graphql.domain_to_form_field(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_choice_form_field(
- root: FormFieldQuery,
- info: Info[FormFieldQuery],
+ root: FormFieldMutation,
+ info: Info[FormFieldMutation],
creator_id: scalar.ObjectID,
allocation_id: scalar.ObjectID,
question: str,
@@ -162,29 +171,31 @@ async def new_choice_form_field(
question_entities: list[FormatEntityInput] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.ChoiceFormFieldType:
- request = proto.CreateChoiceFormField(
- creator_id=creator_id,
- allocation_id=allocation_id,
- question=question,
- required=required,
- frozen=frozen,
- multiple=multiple,
- options=choice_option_to_domain_list(options),
- question_entities=(
- format_entities_to_domain_set(question_entities)
- if question_entities
- else set()
- ),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.form_field.service.create(request)
- return graphql.domain_to_form_field(data)
+ with log.activity("creating new choice form field"):
+ request = proto.CreateChoiceFormField(
+ creator_id=creator_id,
+ allocation_id=allocation_id,
+ question=question,
+ required=required,
+ frozen=frozen,
+ multiple=multiple,
+ options=choice_option_to_domain_list(options),
+ question_entities=(
+ format_entities_to_domain_set(question_entities)
+ if question_entities
+ else set()
+ ),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.form_field.service.create(request)
+ log.info(f"created choice form field {data.id}")
+ return graphql.domain_to_form_field(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def update_text_form_field(
- root: FormFieldQuery,
- info: Info[FormFieldQuery],
+ root: FormFieldMutation,
+ info: Info[FormFieldMutation],
id: scalar.ObjectID,
question: str | None = None,
required: bool | None = None,
@@ -194,29 +205,31 @@ async def update_text_form_field(
re: str | None = None,
ex: str | None = None,
) -> graphql.TextFormFieldType:
- request = proto.UpdateTextFormField(
- _id=id,
- question=question,
- required=required,
- frozen=frozen,
- question_entities=(
- format_entities_to_domain_set(question_entities)
- if question_entities
- else set()
- ),
- editors_ids=set(editors_ids) if editors_ids else set(),
- re=re_compile(re) if re else None,
- ex=ex,
- )
-
- data = await info.context.form_field.service.update(request)
- info.context.form_field.loader.clear(id)
- return graphql.domain_to_form_field(data)
+ with log.activity(f"updating text form field {id}"):
+ request = proto.UpdateTextFormField(
+ _id=id,
+ question=question,
+ required=required,
+ frozen=frozen,
+ question_entities=(
+ format_entities_to_domain_set(question_entities)
+ if question_entities
+ else set()
+ ),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ re=re_compile(re) if re else None,
+ ex=ex,
+ )
+
+ data = await info.context.form_field.service.update(request)
+ info.context.form_field.loader.clear(id)
+ log.info(f"updated text form field {id}")
+ return graphql.domain_to_form_field(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def update_choice_form_field(
- root: FormFieldQuery,
- info: Info[FormFieldQuery],
+ root: FormFieldMutation,
+ info: Info[FormFieldMutation],
id: scalar.ObjectID,
question: str | None = None,
required: bool | None = None,
@@ -226,31 +239,37 @@ async def update_choice_form_field(
question_entities: list[FormatEntityInput] | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.ChoiceFormFieldType:
- request = proto.UpdateChoiceFormField(
- _id=id,
- question=question,
- required=required,
- frozen=frozen,
- multiple=multiple,
- options=update_choice_option_to_proto_list(options) if options else None,
- question_entities=(
- format_entities_to_domain_set(question_entities)
- if question_entities
- else set()
- ),
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
-
- data = await info.context.form_field.service.update(request)
- info.context.form_field.loader.clear(id)
- return graphql.domain_to_form_field(data)
+ with log.activity(f"updating choice form field {id}"):
+ request = proto.UpdateChoiceFormField(
+ _id=id,
+ question=question,
+ required=required,
+ frozen=frozen,
+ multiple=multiple,
+ options=(
+ update_choice_option_to_proto_list(options) if options else None
+ ),
+ question_entities=(
+ format_entities_to_domain_set(question_entities)
+ if question_entities
+ else set()
+ ),
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+
+ data = await info.context.form_field.service.update(request)
+ info.context.form_field.loader.clear(id)
+ log.info(f"updated choice form field {id}")
+ return graphql.domain_to_form_field(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def delete_form_field(
- root: FormFieldQuery, info: Info[FormFieldQuery], id: scalar.ObjectID
+ root: FormFieldMutation, info: Info[FormFieldMutation], id: scalar.ObjectID
) -> graphql.FormFieldType: # type: ignore
- data = await info.context.form_field.service.delete(
- proto.DeleteFormField(_id=id)
- )
- info.context.form_field.loader.clear(id)
- return graphql.domain_to_form_field(data)
+ with log.activity(f"deleting form field {id}"):
+ data = await info.context.form_field.service.delete(
+ proto.DeleteFormField(_id=id)
+ )
+ info.context.form_field.loader.clear(id)
+ log.info(f"deleted form field {id}")
+ return graphql.domain_to_form_field(data)
diff --git a/src/adapter/external/graphql/operation/participant.py b/src/adapter/external/graphql/operation/participant.py
index ed785b1..b6f5e88 100644
--- a/src/adapter/external/graphql/operation/participant.py
+++ b/src/adapter/external/graphql/operation/participant.py
@@ -7,6 +7,9 @@
from src.adapter.external.graphql import scalar
from src.adapter.external.graphql.tool.context import Info
from src.adapter.external.graphql.tool.permission import DefaultPermissions
+from src.utils.logger.logger import Logger
+
+log = Logger("graphql-participant-ops")
@sb.type
@@ -15,72 +18,82 @@ class ParticipantQuery:
async def participant(
root: ParticipantQuery, info: Info[ParticipantQuery], id: scalar.ObjectID
) -> graphql.ParticipantType: # type: ignore
- return await info.context.participant.loader.load(id)
+ with log.activity(f"loading participant {id}"):
+ return await info.context.participant.loader.load(id)
+
+@sb.type
+class ParticipantMutation:
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_creating_participant(
- root: ParticipantQuery,
- info: Info[ParticipantQuery],
+ root: ParticipantMutation,
+ info: Info[ParticipantMutation],
allocation_id: scalar.ObjectID,
user_id: scalar.ObjectID,
viewed_ids: list[scalar.ObjectID] | None = None,
subscription_ids: list[scalar.ObjectID] | None = None,
subscribers_ids: list[scalar.ObjectID] | None = None,
) -> graphql.CreatingParticipantType:
- request = proto.CreateCreatingParticipant(
- allocation_id=allocation_id,
- user_id=user_id,
- viewed_ids=set(viewed_ids) if viewed_ids else set(),
- subscription_ids=set(subscription_ids) if subscription_ids else set(),
- subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
- )
- data = await info.context.participant.service.create(request)
- return graphql.domain_to_participant(data)
+ with log.activity("creating new participant with state CREATING"):
+ request = proto.CreateCreatingParticipant(
+ allocation_id=allocation_id,
+ user_id=user_id,
+ viewed_ids=set(viewed_ids) if viewed_ids else set(),
+ subscription_ids=set(subscription_ids) if subscription_ids else set(),
+ subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
+ )
+ data = await info.context.participant.service.create(request)
+ log.info(f"created participant {data.id}")
+ return graphql.domain_to_participant(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_created_participant(
- root: ParticipantQuery,
- info: Info[ParticipantQuery],
+ root: ParticipantMutation,
+ info: Info[ParticipantMutation],
allocation_id: scalar.ObjectID,
user_id: scalar.ObjectID,
viewed_ids: list[scalar.ObjectID] | None = None,
subscription_ids: list[scalar.ObjectID] | None = None,
subscribers_ids: list[scalar.ObjectID] | None = None,
) -> graphql.CreatedParticipantType:
- request = proto.CreateCreatedParticipant(
- allocation_id=allocation_id,
- user_id=user_id,
- viewed_ids=set(viewed_ids) if viewed_ids else set(),
- subscription_ids=set(subscription_ids) if subscription_ids else set(),
- subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
- )
- data = await info.context.participant.service.create(request)
- return graphql.domain_to_participant(data)
+ with log.activity("creating new participant with state CREATED"):
+ request = proto.CreateCreatedParticipant(
+ allocation_id=allocation_id,
+ user_id=user_id,
+ viewed_ids=set(viewed_ids) if viewed_ids else set(),
+ subscription_ids=set(subscription_ids) if subscription_ids else set(),
+ subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
+ )
+ data = await info.context.participant.service.create(request)
+ log.info(f"created participant {data.id}")
+ return graphql.domain_to_participant(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_active_participant(
- root: ParticipantQuery,
- info: Info[ParticipantQuery],
+ root: ParticipantMutation,
+ info: Info[ParticipantMutation],
allocation_id: scalar.ObjectID,
user_id: scalar.ObjectID,
viewed_ids: list[scalar.ObjectID] | None = None,
subscription_ids: list[scalar.ObjectID] | None = None,
subscribers_ids: list[scalar.ObjectID] | None = None,
) -> graphql.ActiveParticipantType:
- request = proto.CreateActiveParticipant(
- allocation_id=allocation_id,
- user_id=user_id,
- viewed_ids=set(viewed_ids) if viewed_ids else set(),
- subscription_ids=set(subscription_ids) if subscription_ids else set(),
- subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
- )
- data = await info.context.participant.service.create(request)
- return graphql.domain_to_participant(data)
+ with log.activity("creating new participant with state ACTIVE"):
+ request = proto.CreateActiveParticipant(
+ allocation_id=allocation_id,
+ user_id=user_id,
+ viewed_ids=set(viewed_ids) if viewed_ids else set(),
+ subscription_ids=set(subscription_ids) if subscription_ids else set(),
+ subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
+ )
+ data = await info.context.participant.service.create(request)
+ log.info(f"created participant {data.id}")
+ return graphql.domain_to_participant(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_allocated_participant(
- root: ParticipantQuery,
- info: Info[ParticipantQuery],
+ root: ParticipantMutation,
+ info: Info[ParticipantMutation],
user_id: scalar.ObjectID,
allocation_id: scalar.ObjectID,
room_id: scalar.ObjectID,
@@ -88,21 +101,23 @@ async def new_allocated_participant(
subscription_ids: list[scalar.ObjectID] | None = None,
subscribers_ids: list[scalar.ObjectID] | None = None,
) -> graphql.AllocatedParticipantType:
- request = proto.CreateAllocatedParticipant(
- allocation_id=allocation_id,
- user_id=user_id,
- viewed_ids=set(viewed_ids) if viewed_ids else set(),
- subscription_ids=set(subscription_ids) if subscription_ids else set(),
- subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
- room_id=room_id,
- )
- data = await info.context.participant.service.create(request)
- return graphql.domain_to_participant(data)
+ with log.activity("creating new participant with state ALLOCATED"):
+ request = proto.CreateAllocatedParticipant(
+ allocation_id=allocation_id,
+ user_id=user_id,
+ viewed_ids=set(viewed_ids) if viewed_ids else set(),
+ subscription_ids=set(subscription_ids) if subscription_ids else set(),
+ subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
+ room_id=room_id,
+ )
+ data = await info.context.participant.service.create(request)
+ log.info(f"created participant {data.id}")
+ return graphql.domain_to_participant(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def update_participant(
- root: ParticipantQuery,
- info: Info[ParticipantQuery],
+ root: ParticipantMutation,
+ info: Info[ParticipantMutation],
id: scalar.ObjectID,
room_id: scalar.ObjectID | None = None,
state: graphql.ParticipantStateType | None = None, # type: ignore
@@ -110,24 +125,28 @@ async def update_participant(
subscription_ids: list[scalar.ObjectID] | None = None,
subscribers_ids: list[scalar.ObjectID] | None = None,
) -> graphql.ParticipantType: # type: ignore
- request = proto.UpdateParticipant(
- _id=id,
- room_id=room_id,
- state=state,
- viewed_ids=set(viewed_ids) if viewed_ids else set(),
- subscription_ids=set(subscription_ids) if subscription_ids else set(),
- subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
- )
- data = await info.context.participant.service.update(request)
- info.context.participant.loader.clear(id)
- return graphql.domain_to_participant(data)
+ with log.activity(f"updating participant {id}"):
+ request = proto.UpdateParticipant(
+ _id=id,
+ room_id=room_id,
+ state=state,
+ viewed_ids=set(viewed_ids) if viewed_ids else set(),
+ subscription_ids=set(subscription_ids) if subscription_ids else set(),
+ subscribers_ids=set(subscribers_ids) if subscribers_ids else set(),
+ )
+ data = await info.context.participant.service.update(request)
+ info.context.participant.loader.clear(id)
+ log.info(f"updated participant {id}")
+ return graphql.domain_to_participant(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def delete_participant(
- root: ParticipantQuery, info: Info[ParticipantQuery], id: scalar.ObjectID
+ root: ParticipantMutation, info: Info[ParticipantMutation], id: scalar.ObjectID
) -> graphql.ParticipantType: # type: ignore
- data = await info.context.participant.service.delete(
- proto.DeleteParticipant(_id=id)
- )
- info.context.participant.loader.clear(id)
- return graphql.domain_to_participant(data)
+ with log.activity(f"deleting participant {id}"):
+ data = await info.context.participant.service.delete(
+ proto.DeleteParticipant(_id=id)
+ )
+ info.context.participant.loader.clear(id)
+ log.info(f"deleted participant {id}")
+ return graphql.domain_to_participant(data)
diff --git a/src/adapter/external/graphql/operation/preference.py b/src/adapter/external/graphql/operation/preference.py
index c3f007d..5dab05d 100644
--- a/src/adapter/external/graphql/operation/preference.py
+++ b/src/adapter/external/graphql/operation/preference.py
@@ -7,60 +7,74 @@
from src.adapter.external.graphql import scalar
from src.adapter.external.graphql.tool.context import Info
from src.adapter.external.graphql.tool.permission import DefaultPermissions
+from src.utils.logger.logger import Logger
PreferenceKindInput = sb.input(graphql.PreferenceKindType)
PreferenceStatusInput = sb.input(graphql.PreferenceStatusType)
+log = Logger("graphql-preference-ops")
+
+@sb.type
class PreferenceQuery:
@sb.field(permission_classes=[DefaultPermissions])
async def preference(
root: PreferenceQuery, info: Info[PreferenceQuery], id: scalar.ObjectID
) -> graphql.PreferenceType:
- return await info.context.preference.loader.load(id)
+ with log.activity(f"loading preference {id}"):
+ return await info.context.preference.loader.load(id)
+
+@sb.type
+class PreferenceMutation:
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_preference(
- root: PreferenceQuery,
- info: Info[PreferenceQuery],
+ root: PreferenceMutation,
+ info: Info[PreferenceMutation],
kind: PreferenceKindInput, # type: ignore
status: PreferenceStatusInput, # type: ignore
user_id: scalar.ObjectID,
target_id: scalar.ObjectID,
) -> graphql.PreferenceType:
- request = proto.CreatePreference(
- kind=kind,
- status=status,
- user_id=user_id,
- target_id=target_id,
- )
- data = await info.context.preference.service.create(request)
- return graphql.PreferenceType.from_pydantic(data)
+ with log.activity("creating new preference"):
+ request = proto.CreatePreference(
+ kind=kind,
+ status=status,
+ user_id=user_id,
+ target_id=target_id,
+ )
+ data = await info.context.preference.service.create(request)
+ log.info(f"created preference {data.id}")
+ return graphql.PreferenceType.from_pydantic(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def update_preference(
- root: PreferenceQuery,
- info: Info[PreferenceQuery],
+ root: PreferenceMutation,
+ info: Info[PreferenceMutation],
id: scalar.ObjectID,
kind: PreferenceKindInput | None, # type: ignore
status: PreferenceStatusInput | None, # type: ignore
) -> graphql.PreferenceType:
- request = proto.UpdatePreference(
- _id=id,
- kind=kind,
- status=status,
- )
- data = await info.context.preference.service.update(request)
- info.context.preference.loader.clear(id)
- return graphql.PreferenceType.from_pydantic(data)
+ with log.activity(f"updating preference {id}"):
+ request = proto.UpdatePreference(
+ _id=id,
+ kind=kind,
+ status=status,
+ )
+ data = await info.context.preference.service.update(request)
+ info.context.preference.loader.clear(id)
+ log.info(f"updated preference {id}")
+ return graphql.PreferenceType.from_pydantic(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def delete_preference(
- root: PreferenceQuery,
- info: Info[PreferenceQuery],
+ root: PreferenceMutation,
+ info: Info[PreferenceMutation],
id: scalar.ObjectID,
) -> graphql.PreferenceType:
- request = proto.DeletePreference(_id=id)
- data = await info.context.preference.service.delete(request)
- info.context.preference.loader.clear(id)
- return graphql.PreferenceType.from_pydantic(data)
+ with log.activity(f"deleting preference {id}"):
+ request = proto.DeletePreference(_id=id)
+ data = await info.context.preference.service.delete(request)
+ info.context.preference.loader.clear(id)
+ log.info(f"deleted preference {id}")
+ return graphql.PreferenceType.from_pydantic(data)
diff --git a/src/adapter/external/graphql/operation/room.py b/src/adapter/external/graphql/operation/room.py
index 3bba418..50a9f82 100644
--- a/src/adapter/external/graphql/operation/room.py
+++ b/src/adapter/external/graphql/operation/room.py
@@ -6,6 +6,9 @@
import src.protocol.internal.database.room as proto
from src.adapter.external.graphql import scalar
from src.adapter.external.graphql.tool.context import Info
+from src.utils.logger.logger import Logger
+
+log = Logger("graphql-room-ops")
@sb.type
@@ -14,12 +17,16 @@ class RoomQuery:
async def room(
root: RoomQuery, info: Info[RoomQuery], id: scalar.ObjectID
) -> graphql.RoomType:
- return await info.context.room.loader.load(id)
+ with log.activity(f"loading room {id}"):
+ return await info.context.room.loader.load(id)
+
+@sb.type
+class RoomMutation:
@sb.mutation
async def new_room(
- root: RoomQuery,
- info: Info[RoomQuery],
+ root: RoomMutation,
+ info: Info[RoomMutation],
name: str,
capacity: int,
occupied: int,
@@ -27,21 +34,23 @@ async def new_room(
creator_id: scalar.ObjectID,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.RoomType:
- request = proto.CreateRoom(
- name=name,
- capacity=capacity,
- occupied=occupied,
- gender_restriction=gender_restriction,
- creator_id=creator_id,
- editors_ids=set(editors_ids) if editors_ids else set(),
- )
- data = await info.context.room.service.create(request)
- return graphql.RoomType.from_pydantic(data)
+ with log.activity("creating new room"):
+ request = proto.CreateRoom(
+ name=name,
+ capacity=capacity,
+ occupied=occupied,
+ gender_restriction=gender_restriction,
+ creator_id=creator_id,
+ editors_ids=set(editors_ids) if editors_ids else set(),
+ )
+ data = await info.context.room.service.create(request)
+ log.info(f"created room {data.id}")
+ return graphql.RoomType.from_pydantic(data)
@sb.mutation
async def update_room(
- root: RoomQuery,
- info: Info[RoomQuery],
+ root: RoomMutation,
+ info: Info[RoomMutation],
id: scalar.ObjectID,
name: str | None = None,
capacity: int | None = None,
@@ -49,25 +58,29 @@ async def update_room(
gender_restriction: graphql.GenderType | None = None,
editors_ids: list[scalar.ObjectID] | None = None,
) -> graphql.RoomType:
- request = proto.UpdateRoom(
- _id=id,
- name=name,
- capacity=capacity,
- occupied=occupied,
- gender_restriction=gender_restriction,
- editors_ids=set(editors_ids) if editors_ids else None,
- )
- data = await info.context.room.service.update(request)
- info.context.room.loader.clear(id)
- return graphql.RoomType.from_pydantic(data)
+ with log.activity(f"updating room {id}"):
+ request = proto.UpdateRoom(
+ _id=id,
+ name=name,
+ capacity=capacity,
+ occupied=occupied,
+ gender_restriction=gender_restriction,
+ editors_ids=set(editors_ids) if editors_ids else None,
+ )
+ data = await info.context.room.service.update(request)
+ info.context.room.loader.clear(id)
+ log.info(f"updated room {id}")
+ return graphql.RoomType.from_pydantic(data)
@sb.mutation
async def delete_room(
- root: RoomQuery,
- info: Info[RoomQuery],
+ root: RoomMutation,
+ info: Info[RoomMutation],
id: scalar.ObjectID,
) -> graphql.RoomType:
- request = proto.DeleteRoom(_id=id)
- data = await info.context.room.service.delete(request)
- info.context.room.loader.clear(id)
- return graphql.RoomType.from_pydantic(data)
+ with log.activity(f"deleting room {id}"):
+ request = proto.DeleteRoom(_id=id)
+ data = await info.context.room.service.delete(request)
+ info.context.room.loader.clear(id)
+ log.info(f"deleted room {id}")
+ return graphql.RoomType.from_pydantic(data)
diff --git a/src/adapter/external/graphql/operation/user.py b/src/adapter/external/graphql/operation/user.py
index 4395c5f..8e7f3d9 100644
--- a/src/adapter/external/graphql/operation/user.py
+++ b/src/adapter/external/graphql/operation/user.py
@@ -13,6 +13,9 @@
LanguageCodeType,
UserType,
)
+from src.utils.logger.logger import Logger
+
+log = Logger("graphql-user-ops")
@sb.type
@@ -21,12 +24,16 @@ class UserQuery:
async def user(
root: UserQuery, info: Info[UserQuery], id: scalar.ObjectID
) -> UserType: # type: ignore
- return await info.context.user.loader.load(id)
+ with log.activity(f"loading user {id}"):
+ return await info.context.user.loader.load(id)
+
+@sb.type
+class UserMutation:
@sb.mutation(permission_classes=[DefaultPermissions])
async def new_user(
- root: UserQuery,
- info: Info[UserQuery],
+ root: UserMutation,
+ info: Info[UserMutation],
telegram_id: int,
first_name: str,
language_code: LanguageCodeType, # type: ignore
@@ -36,26 +43,28 @@ async def new_user(
username: str | None = None,
views: int = 0,
) -> UserType:
- request = proto.CreateUser(
- telegram_id=telegram_id,
- profile=proto.Profile(
- first_name=first_name,
- language_code=language_code,
- gender=gender,
- birthdate=birthdate,
- last_name=last_name,
- username=username,
- ),
- views=views,
- )
+ with log.activity("creating new user"):
+ request = proto.CreateUser(
+ telegram_id=telegram_id,
+ profile=proto.Profile(
+ first_name=first_name,
+ language_code=language_code,
+ gender=gender,
+ birthdate=birthdate,
+ last_name=last_name,
+ username=username,
+ ),
+ views=views,
+ )
- data = await info.context.user.service.create(request)
- return UserType.from_pydantic(data)
+ data = await info.context.user.service.create(request)
+ log.info(f"created user {data.id}")
+ return UserType.from_pydantic(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def update_user(
- root: UserQuery,
- info: Info[UserQuery],
+ root: UserMutation,
+ info: Info[UserMutation],
id: scalar.ObjectID,
views: int | None = None,
first_name: str | None = None,
@@ -65,28 +74,32 @@ async def update_user(
gender: GenderType | None = None, # type: ignore
birthdate: datetime | None = None,
) -> UserType:
- payload = proto.UpdateUser(
- _id=id,
- views=views,
- profile=proto.UpdateProfile(
- first_name=first_name,
- last_name=last_name,
- username=username,
- language_code=language_code,
- gender=gender,
- birthdate=birthdate,
- ),
- )
+ with log.activity(f"updating user {id}"):
+ payload = proto.UpdateUser(
+ _id=id,
+ views=views,
+ profile=proto.UpdateProfile(
+ first_name=first_name,
+ last_name=last_name,
+ username=username,
+ language_code=language_code,
+ gender=gender,
+ birthdate=birthdate,
+ ),
+ )
- request = proto.UpdateUser.model_validate(payload)
- data = await info.context.user.service.update(request)
- info.context.user.loader.clear(request.id) # invalidate old cache
- return UserType.from_pydantic(data)
+ request = proto.UpdateUser.model_validate(payload)
+ data = await info.context.user.service.update(request)
+ info.context.user.loader.clear(request.id) # invalidate old cache
+ log.info(f"updated user {id}")
+ return UserType.from_pydantic(data)
@sb.mutation(permission_classes=[DefaultPermissions])
async def delete_user(
- root: UserQuery, info: Info[UserQuery], id: scalar.ObjectID
+ root: UserMutation, info: Info[UserMutation], id: scalar.ObjectID
) -> UserType:
- data = await info.context.user.service.delete(proto.DeleteUser(_id=id))
- info.context.user.loader.clear(id) # invalidate cache
- return UserType.from_pydantic(data)
+ with log.activity(f"deleting user {id}"):
+ data = await info.context.user.service.delete(proto.DeleteUser(_id=id))
+ info.context.user.loader.clear(id) # invalidate cache
+ log.info(f"deleted user {id}")
+ return UserType.from_pydantic(data)
diff --git a/src/adapter/external/graphql/query.py b/src/adapter/external/graphql/query.py
deleted file mode 100644
index a787e39..0000000
--- a/src/adapter/external/graphql/query.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import strawberry as sb
-
-from src.adapter.external.graphql.operation.allocation import AllocationQuery
-from src.adapter.external.graphql.operation.form_field import FormFieldQuery
-from src.adapter.external.graphql.operation.participant import ParticipantQuery
-from src.adapter.external.graphql.operation.preference import PreferenceQuery
-from src.adapter.external.graphql.operation.room import RoomQuery
-from src.adapter.external.graphql.operation.user import UserQuery
-
-
-@sb.type
-class Query(
- AllocationQuery,
- FormFieldQuery,
- ParticipantQuery,
- PreferenceQuery,
- RoomQuery,
- UserQuery,
-): ...
diff --git a/src/adapter/external/graphql/schema.py b/src/adapter/external/graphql/schema.py
new file mode 100644
index 0000000..0a11a77
--- /dev/null
+++ b/src/adapter/external/graphql/schema.py
@@ -0,0 +1,45 @@
+import strawberry as sb
+
+from src.adapter.external.graphql.operation.allocation import (
+ AllocationMutation,
+ AllocationQuery,
+)
+from src.adapter.external.graphql.operation.form_field import (
+ FormFieldMutation,
+ FormFieldQuery,
+)
+from src.adapter.external.graphql.operation.participant import (
+ ParticipantMutation,
+ ParticipantQuery,
+)
+from src.adapter.external.graphql.operation.preference import (
+ PreferenceMutation,
+ PreferenceQuery,
+)
+from src.adapter.external.graphql.operation.room import RoomMutation, RoomQuery
+from src.adapter.external.graphql.operation.user import UserMutation, UserQuery
+
+
+@sb.type
+class Query(
+ AllocationQuery,
+ FormFieldQuery,
+ ParticipantQuery,
+ PreferenceQuery,
+ RoomQuery,
+ UserQuery,
+): ...
+
+
+@sb.type
+class Mutation(
+ AllocationMutation,
+ FormFieldMutation,
+ ParticipantMutation,
+ PreferenceMutation,
+ RoomMutation,
+ UserMutation,
+): ...
+
+
+SCHEMA = sb.Schema(query=Query, mutation=Mutation)
diff --git a/src/adapter/external/graphql/view.py b/src/adapter/external/graphql/view.py
index 3758df1..31a5600 100644
--- a/src/adapter/external/graphql/view.py
+++ b/src/adapter/external/graphql/view.py
@@ -1,8 +1,9 @@
import strawberry as sb
+import ujson
from strawberry.aiohttp.views import GraphQLView
from strawberry.dataloader import DataLoader, DefaultCache
+from strawberry.http import GraphQLHTTPResponse
-from src.adapter.external.graphql.query import Query
from src.adapter.external.graphql.tool.context import Context, DataContext
from src.adapter.external.graphql.type.allocation import (
AllocationType,
@@ -33,8 +34,6 @@
from src.service.room import RoomService
from src.service.user import UserService
-GRAPHQL_SCHEMA = sb.Schema(query=Query)
-
class CustomDefaultCache[K, T](DefaultCache[K, T]):
def delete(self, key: K) -> None:
@@ -59,7 +58,7 @@ def __init__(
self._participant_service = participant_service
self._preference_service = preference_service
self._room_service = room_service
- super().__init__(schema)
+ super().__init__(schema, debug=False)
async def get_context(self, request, response):
return Context(
@@ -148,3 +147,6 @@ async def __load_rooms(self, ids: list[ObjectID]) -> list[RoomType]:
response = await self._room_service.read_many(request)
return [RoomType.from_pydantic(obj) for obj in response]
+
+ def encode_json(self, response_data: GraphQLHTTPResponse) -> str:
+ return ujson.dumps(response_data, ensure_ascii=False)
diff --git a/src/app/http/server.py b/src/app/http/server.py
index 7578f0c..f63accb 100644
--- a/src/app/http/server.py
+++ b/src/app/http/server.py
@@ -1,6 +1,7 @@
from aiohttp import web
-from src.adapter.external.graphql.view import GRAPHQL_SCHEMA, RandormGraphQLView
+from src.adapter.external.graphql.schema import SCHEMA
+from src.adapter.external.graphql.view import RandormGraphQLView
from src.app.http.routes import oauth
from src.protocol.external.auth.oauth import OauthProtocol
from src.service.allocation import AllocationService
@@ -33,7 +34,7 @@ def build_server(
"*",
"/graphql",
RandormGraphQLView(
- GRAPHQL_SCHEMA,
+ SCHEMA,
user_service,
allocation_service,
form_field_service,
diff --git a/src/utils/logger/logger.py b/src/utils/logger/logger.py
index e69de29..5e9be90 100644
--- a/src/utils/logger/logger.py
+++ b/src/utils/logger/logger.py
@@ -0,0 +1,74 @@
+import atexit
+import sys
+from contextlib import contextmanager
+from uuid import uuid4
+
+from loguru._logger import Core
+from loguru._logger import Logger as LoguruLogger
+
+
+class Logger(LoguruLogger):
+ def __init__(self, context: str):
+ super().__init__(
+ core=Core(),
+ exception=None,
+ depth=0,
+ record=False,
+ lazy=False,
+ colors=False,
+ raw=False,
+ capture=True,
+ patchers=[],
+ extra={"context": context, "correlation_id": None},
+ )
+ logger_format = (
+ "{time:YYYY-MM-DD HH:mm:ss.SSS} | "
+ "{level: <8} | "
+ "{name}:{function}:{line} | "
+ "[{extra[context]}] "
+ "[COR_ID: {extra[correlation_id]}] "
+ "{message}"
+ )
+ self.add(sys.stderr, format=logger_format)
+ atexit.register(self.remove)
+
+ def _start_record(self, name: str) -> str:
+ return f"activity [{name}] started."
+
+ def _fail_record(self, name: str, err: Exception) -> str:
+ return f"activity [{name}] failed with {type(err).__name__}: {err}"
+
+ def _error_record(self, name: str, err: Exception) -> str:
+ return f"activity [{name}] raised error: {err}"
+
+ def _finish_record(self, name: str) -> str:
+ return f"activity [{name}] finished."
+
+ @contextmanager
+ def activity(
+ self,
+ name: str,
+ with_traceback: bool = False,
+ capture: bool = False,
+ with_correlation_id: bool = True,
+ ):
+ if with_correlation_id:
+ correlation_id = uuid4().hex
+ else:
+ correlation_id = None
+
+ try:
+ self.info(self._start_record(name), correlation_id=correlation_id)
+ yield
+ except Exception as e:
+ self.error(self._fail_record(name, e), correlation_id=correlation_id)
+
+ if with_traceback:
+ self.opt(exception=e).error(
+ self._error_record(name, e), correlation_id=correlation_id
+ )
+
+ if not capture:
+ raise e
+ else:
+ self.info(self._finish_record(name), correlation_id=correlation_id)