From f4347cc0a95379ae12aa7d64b4439e0438fc4f26 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 11:47:55 +0100 Subject: [PATCH 1/9] Remove old linting code. Add Terraform to tool versions file for asdf / mise users. --- .flake8 | 3 - .tool-versions | 1 + Makefile | 12 +- poetry.lock | 1810 ---------------------------------- pyproject.toml | 37 - pytest.ini | 7 - terraform/.terraform-version | 1 - test-report.xml | 23 - 8 files changed, 3 insertions(+), 1891 deletions(-) delete mode 100644 .flake8 delete mode 100644 poetry.lock delete mode 100644 pyproject.toml delete mode 100644 pytest.ini delete mode 100644 terraform/.terraform-version delete mode 100644 test-report.xml diff --git a/.flake8 b/.flake8 deleted file mode 100644 index d0e7de497..000000000 --- a/.flake8 +++ /dev/null @@ -1,3 +0,0 @@ -[flake8] -max-line-length=121 -exclude = .git,__pycache__,dist,.venv/*,node_modules/*,utils/*,tests/.venv/*,dynamodb/*,backend/*,.direnv,delta_backend/*,ack_backend/* diff --git a/.tool-versions b/.tool-versions index 9e925de90..72348a17a 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,4 @@ poetry 2.1.4 nodejs 23.11.0 python 3.11.12 +terraform 1.12.2 diff --git a/Makefile b/Makefile index f72f71e75..9d063496a 100644 --- a/Makefile +++ b/Makefile @@ -3,20 +3,12 @@ SHELL=/usr/bin/env bash -euo pipefail PYTHON_PROJECT_DIRS_WITH_UNIT_TESTS = backend batch_processor_filter delta_backend filenameprocessor mesh_processor recordprocessor lambdas/ack_backend lambdas/redis_sync lambdas/id_sync lambdas/mns_subscription lambdas/shared PYTHON_PROJECT_DIRS = e2e e2e_batch quality_checks $(PYTHON_PROJECT_DIRS_WITH_UNIT_TESTS) -.PHONY: install-python install-node install lint format format-check clean publish build-proxy release initialise-all-python-venvs update-all-python-dependencies run-all-python-unit-tests build-all-docker-images - -#Installs dependencies using poetry. -install-python: - poetry lock --no-update - poetry install +.PHONY: install lint format format-check clean publish build-proxy release initialise-all-python-venvs update-all-python-dependencies run-all-python-unit-tests build-all-docker-images #Installs dependencies using npm. -install-node: +install: npm install --legacy-peer-deps -#Condensed Target to run all targets above. -install: install-node install-python - #Run the npm linting script (specified in package.json). Used to check the syntax and formatting of files. lint: npm run lint diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 47aa5ec73..000000000 --- a/poetry.lock +++ /dev/null @@ -1,1810 +0,0 @@ -# This file is automatically @generated by Poetry 2.2.0 and should not be changed by hand. - -[[package]] -name = "aiohappyeyeballs" -version = "2.4.4" -description = "Happy Eyeballs for asyncio" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, - {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, -] - -[[package]] -name = "aiohttp" -version = "3.10.11" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, - {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, - {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"}, - {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"}, - {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"}, - {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"}, - {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"}, - {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"}, - {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"}, - {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"}, - {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"}, - {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"}, - {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"}, - {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"}, - {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"}, - {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"}, - {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"}, - {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"}, - {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"}, - {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"}, - {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"}, - {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"}, - {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"}, - {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"}, - {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"}, - {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"}, - {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"}, - {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"}, - {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"}, - {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"}, - {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"}, - {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"}, - {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"}, -] - -[package.dependencies] -aiohappyeyeballs = ">=2.3.0" -aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.12.0,<2.0" - -[package.extras] -speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, - {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, -] - -[[package]] -name = "async-timeout" -version = "4.0.3" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version < \"3.11\"" -files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, -] - -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main", "dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6) ; platform_python_implementation == \"CPython\" and python_version >= \"3.8\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.8\""] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] - -[[package]] -name = "authlib" -version = "0.15.5" -description = "The ultimate Python library in building OAuth and OpenID Connect servers." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "Authlib-0.15.5-py2.py3-none-any.whl", hash = "sha256:ecf4a7a9f2508c0bb07e93a752dd3c495cfaffc20e864ef0ffc95e3f40d2abaf"}, - {file = "Authlib-0.15.5.tar.gz", hash = "sha256:b83cf6360c8e92b0e9df0d1f32d675790bcc4e3c03977499b1eed24dcdef4252"}, -] - -[package.dependencies] -cryptography = "*" - -[package.extras] -client = ["requests"] - -[[package]] -name = "black" -version = "20.8b1" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"}, -] - -[package.dependencies] -appdirs = "*" -click = ">=7.1.2" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.6,<1" -regex = ">=2020.1.8" -toml = ">=0.10.1" -typed-ast = ">=1.4.0" -typing-extensions = ">=3.7.4" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] - -[[package]] -name = "certifi" -version = "2024.2.2" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "2.0.12" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.5.0" -groups = ["main"] -files = [ - {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, - {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, -] - -[package.extras] -unicode-backport = ["unicodedata2"] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "sys_platform == \"win32\"", dev = "sys_platform == \"win32\" or platform_system == \"Windows\""} - -[[package]] -name = "coverage" -version = "5.5" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -groups = ["dev"] -files = [ - {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, - {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"}, - {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"}, - {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"}, - {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"}, - {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"}, - {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"}, - {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"}, - {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"}, - {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"}, - {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"}, - {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"}, - {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"}, - {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"}, - {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"}, - {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"}, - {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"}, - {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"}, - {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"}, - {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"}, - {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"}, - {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"}, - {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"}, - {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"}, - {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"}, - {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"}, - {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"}, - {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"}, - {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"}, - {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"}, - {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"}, - {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"}, - {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"}, - {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"}, - {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"}, - {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"}, - {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"}, - {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"}, - {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"}, - {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"}, - {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"}, - {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"}, - {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"}, - {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"}, - {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"}, - {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"}, - {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"}, - {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, -] - -[package.extras] -toml = ["toml"] - -[[package]] -name = "cryptography" -version = "36.0.1" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, - {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"}, - {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"}, - {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"}, - {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"}, - {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"}, - {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"}, -] - -[package.dependencies] -cffi = ">=1.12" - -[package.extras] -docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] -sdist = ["setuptools-rust (>=0.11.4)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"] - -[[package]] -name = "decorator" -version = "5.1.1" -description = "Decorators for Humans" -optional = false -python-versions = ">=3.5" -groups = ["dev"] -files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, -] - -[[package]] -name = "docopt" -version = "0.6.2" -description = "Pythonic argument parser, that will make you smile" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, -] - -[[package]] -name = "flake8" -version = "3.9.2" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -groups = ["dev"] -files = [ - {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, - {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, -] - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.7.0,<2.8.0" -pyflakes = ">=2.3.0,<2.4.0" - -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "gitdb" -version = "4.0.11" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, - {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.45" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77"}, - {file = "gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" -typing-extensions = {version = ">=3.10.0.2", markers = "python_version < \"3.10\""} - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock ; python_version < \"3.8\"", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions ; python_version < \"3.11\""] - -[[package]] -name = "idna" -version = "3.6" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -groups = ["main", "dev"] -files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "jinja2" -version = "3.1.6" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, - {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jsonpath-rw" -version = "1.4.0" -description = "A robust and significantly extended implementation of JSONPath for Python, with a clear AST for metaprogramming." -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "jsonpath-rw-1.4.0.tar.gz", hash = "sha256:05c471281c45ae113f6103d1268ec7a4831a2e96aa80de45edc89b11fac4fbec"}, -] - -[package.dependencies] -decorator = "*" -ply = "*" -six = "*" - -[[package]] -name = "lxml" -version = "4.7.1" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -groups = ["main"] -files = [ - {file = "lxml-4.7.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:d546431636edb1d6a608b348dd58cc9841b81f4116745857b6cb9f8dadb2725f"}, - {file = "lxml-4.7.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6308062534323f0d3edb4e702a0e26a76ca9e0e23ff99be5d82750772df32a9e"}, - {file = "lxml-4.7.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:f76dbe44e31abf516114f6347a46fa4e7c2e8bceaa4b6f7ee3a0a03c8eba3c17"}, - {file = "lxml-4.7.1-cp27-cp27m-win32.whl", hash = "sha256:d5618d49de6ba63fe4510bdada62d06a8acfca0b4b5c904956c777d28382b419"}, - {file = "lxml-4.7.1-cp27-cp27m-win_amd64.whl", hash = "sha256:9393a05b126a7e187f3e38758255e0edf948a65b22c377414002d488221fdaa2"}, - {file = "lxml-4.7.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50d3dba341f1e583265c1a808e897b4159208d814ab07530202b6036a4d86da5"}, - {file = "lxml-4.7.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:44f552e0da3c8ee3c28e2eb82b0b784200631687fc6a71277ea8ab0828780e7d"}, - {file = "lxml-4.7.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:e662c6266e3a275bdcb6bb049edc7cd77d0b0f7e119a53101d367c841afc66dc"}, - {file = "lxml-4.7.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4c093c571bc3da9ebcd484e001ba18b8452903cd428c0bc926d9b0141bcb710e"}, - {file = "lxml-4.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3e26ad9bc48d610bf6cc76c506b9e5ad9360ed7a945d9be3b5b2c8535a0145e3"}, - {file = "lxml-4.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a5f623aeaa24f71fce3177d7fee875371345eb9102b355b882243e33e04b7175"}, - {file = "lxml-4.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7b5e2acefd33c259c4a2e157119c4373c8773cf6793e225006a1649672ab47a6"}, - {file = "lxml-4.7.1-cp310-cp310-win32.whl", hash = "sha256:67fa5f028e8a01e1d7944a9fb616d1d0510d5d38b0c41708310bd1bc45ae89f6"}, - {file = "lxml-4.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:b1d381f58fcc3e63fcc0ea4f0a38335163883267f77e4c6e22d7a30877218a0e"}, - {file = "lxml-4.7.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38d9759733aa04fb1697d717bfabbedb21398046bd07734be7cccc3d19ea8675"}, - {file = "lxml-4.7.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:dfd0d464f3d86a1460683cd742306d1138b4e99b79094f4e07e1ca85ee267fe7"}, - {file = "lxml-4.7.1-cp35-cp35m-win32.whl", hash = "sha256:534e946bce61fd162af02bad7bfd2daec1521b71d27238869c23a672146c34a5"}, - {file = "lxml-4.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:6ec829058785d028f467be70cd195cd0aaf1a763e4d09822584ede8c9eaa4b03"}, - {file = "lxml-4.7.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:ade74f5e3a0fd17df5782896ddca7ddb998845a5f7cd4b0be771e1ffc3b9aa5b"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:41358bfd24425c1673f184d7c26c6ae91943fe51dfecc3603b5e08187b4bcc55"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6e56521538f19c4a6690f439fefed551f0b296bd785adc67c1777c348beb943d"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b0f782f0e03555c55e37d93d7a57454efe7495dab33ba0ccd2dbe25fc50f05d"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:490712b91c65988012e866c411a40cc65b595929ececf75eeb4c79fcc3bc80a6"}, - {file = "lxml-4.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c22eb8c819d59cec4444d9eebe2e38b95d3dcdafe08965853f8799fd71161d"}, - {file = "lxml-4.7.1-cp36-cp36m-win32.whl", hash = "sha256:2a906c3890da6a63224d551c2967413b8790a6357a80bf6b257c9a7978c2c42d"}, - {file = "lxml-4.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:36b16fecb10246e599f178dd74f313cbdc9f41c56e77d52100d1361eed24f51a"}, - {file = "lxml-4.7.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:a5edc58d631170de90e50adc2cc0248083541affef82f8cd93bea458e4d96db8"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:87c1b0496e8c87ec9db5383e30042357b4839b46c2d556abd49ec770ce2ad868"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:0a5f0e4747f31cff87d1eb32a6000bde1e603107f632ef4666be0dc065889c7a"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bf6005708fc2e2c89a083f258b97709559a95f9a7a03e59f805dd23c93bc3986"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc15874816b9320581133ddc2096b644582ab870cf6a6ed63684433e7af4b0d3"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0b5e96e25e70917b28a5391c2ed3ffc6156513d3db0e1476c5253fcd50f7a944"}, - {file = "lxml-4.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ec9027d0beb785a35aa9951d14e06d48cfbf876d8ff67519403a2522b181943b"}, - {file = "lxml-4.7.1-cp37-cp37m-win32.whl", hash = "sha256:9fbc0dee7ff5f15c4428775e6fa3ed20003140560ffa22b88326669d53b3c0f4"}, - {file = "lxml-4.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1104a8d47967a414a436007c52f533e933e5d52574cab407b1e49a4e9b5ddbd1"}, - {file = "lxml-4.7.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:fc9fb11b65e7bc49f7f75aaba1b700f7181d95d4e151cf2f24d51bfd14410b77"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:317bd63870b4d875af3c1be1b19202de34c32623609ec803b81c99193a788c1e"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:610807cea990fd545b1559466971649e69302c8a9472cefe1d6d48a1dee97440"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:09b738360af8cb2da275998a8bf79517a71225b0de41ab47339c2beebfff025f"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6a2ab9d089324d77bb81745b01f4aeffe4094306d939e92ba5e71e9a6b99b71e"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eed394099a7792834f0cb4a8f615319152b9d801444c1c9e1b1a2c36d2239f9e"}, - {file = "lxml-4.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:735e3b4ce9c0616e85f302f109bdc6e425ba1670a73f962c9f6b98a6d51b77c9"}, - {file = "lxml-4.7.1-cp38-cp38-win32.whl", hash = "sha256:772057fba283c095db8c8ecde4634717a35c47061d24f889468dc67190327bcd"}, - {file = "lxml-4.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:13dbb5c7e8f3b6a2cf6e10b0948cacb2f4c9eb05029fe31c60592d08ac63180d"}, - {file = "lxml-4.7.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:718d7208b9c2d86aaf0294d9381a6acb0158b5ff0f3515902751404e318e02c9"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:5bee1b0cbfdb87686a7fb0e46f1d8bd34d52d6932c0723a86de1cc532b1aa489"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e410cf3a2272d0a85526d700782a2fa92c1e304fdcc519ba74ac80b8297adf36"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:585ea241ee4961dc18a95e2f5581dbc26285fcf330e007459688096f76be8c42"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a555e06566c6dc167fbcd0ad507ff05fd9328502aefc963cb0a0547cfe7f00db"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:adaab25be351fff0d8a691c4f09153647804d09a87a4e4ea2c3f9fe9e8651851"}, - {file = "lxml-4.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:82d16a64236970cb93c8d63ad18c5b9f138a704331e4b916b2737ddfad14e0c4"}, - {file = "lxml-4.7.1-cp39-cp39-win32.whl", hash = "sha256:59e7da839a1238807226f7143c68a479dee09244d1b3cf8c134f2fce777d12d0"}, - {file = "lxml-4.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:a1bbc4efa99ed1310b5009ce7f3a1784698082ed2c1ef3895332f5df9b3b92c2"}, - {file = "lxml-4.7.1-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:0607ff0988ad7e173e5ddf7bf55ee65534bd18a5461183c33e8e41a59e89edf4"}, - {file = "lxml-4.7.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:6c198bfc169419c09b85ab10cb0f572744e686f40d1e7f4ed09061284fc1303f"}, - {file = "lxml-4.7.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a58d78653ae422df6837dd4ca0036610b8cb4962b5cfdbd337b7b24de9e5f98a"}, - {file = "lxml-4.7.1-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:e18281a7d80d76b66a9f9e68a98cf7e1d153182772400d9a9ce855264d7d0ce7"}, - {file = "lxml-4.7.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8e54945dd2eeb50925500957c7c579df3cd07c29db7810b83cf30495d79af267"}, - {file = "lxml-4.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:447d5009d6b5447b2f237395d0018901dcc673f7d9f82ba26c1b9f9c3b444b60"}, - {file = "lxml-4.7.1.tar.gz", hash = "sha256:a1613838aa6b89af4ba10a0f3a972836128801ed008078f8c1244e65958f1b24"}, -] - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.7)"] - -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] - -[[package]] -name = "multidict" -version = "6.0.5" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "packaging" -version = "24.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "pip-licenses" -version = "2.3.0" -description = "Dump the software license list of Python packages installed with pip." -optional = false -python-versions = "~=3.5" -groups = ["dev"] -files = [ - {file = "pip-licenses-2.3.0.tar.gz", hash = "sha256:630f7e1b51ac0751c9c218e2ed76bb982e769301510a0bcca0dd4a47d05198fd"}, - {file = "pip_licenses-2.3.0-py3-none-any.whl", hash = "sha256:b3922fc71e819c1a155460116d2fcf15eca85a22ebe057cd1e1dedb951b1199f"}, -] - -[package.dependencies] -PTable = "*" - -[package.extras] -test = ["docutils", "pytest-cov", "pytest-pycodestyle", "pytest-runner"] - -[[package]] -name = "pluggy" -version = "1.4.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "ply" -version = "3.11" -description = "Python Lex & Yacc" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, - {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, -] - -[[package]] -name = "propcache" -version = "0.2.0" -description = "Accelerated property cache" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, - {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, - {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, - {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, - {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, - {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, - {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, - {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, - {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, - {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, - {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, - {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, - {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, - {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, - {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, -] - -[[package]] -name = "ptable" -version = "0.9.2" -description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "PTable-0.9.2.tar.gz", hash = "sha256:aa7fc151cb40f2dabcd2275ba6f7fd0ff8577a86be3365cd3fb297cbe09cc292"}, -] - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main", "dev"] -files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] - -[[package]] -name = "pycodestyle" -version = "2.7.0" -description = "Python style guide checker" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, - {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, -] - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] - -[[package]] -name = "pycryptodome" -version = "3.13.0" -description = "Cryptographic library for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "pycryptodome-3.13.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e468724173df02f9d83f3fea830bf0d04aa291b5add22b4a78e01c97aab04873"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1fb7a6f222072412f320b9e48d3ce981920efbfce37b06d028ec9bd94093b37f"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4f1b594d0cf35bd12ec4244df1155a7f565bf6e6245976ac36174c1564688c90"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9ea70f6c3f6566159e3798e4593a4a8016994a0080ac29a45200615b45091a1b"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f7aad304575d075faf2806977b726b67da7ba294adc97d878f92a062e357a56a"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:702446a012fd9337b9327d168bb0c7dc714eb93ad361f6f61af9ca8305a301f1"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-win32.whl", hash = "sha256:681ac47c538c64305d710eaed2bb49532f62b3f4c93aa7c423c520df981392e5"}, - {file = "pycryptodome-3.13.0-cp27-cp27m-win_amd64.whl", hash = "sha256:7b3478a187d897f003b2aa1793bcc59463e8d57a42e2aafbcbbe9cd47ec46863"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:eec02d9199af4b1ccfe1f9c587691a07a1fa39d949d2c1dc69d079ab9af8212f"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9c8e0e6c5e982699801b20fa74f43c19aa080d2b53a39f3c132d35958e153bd4"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f5457e44d3f26d9946091e92b28f3e970a56538b96c87b4b155a84e32a40b7b5"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:88d6d54e83cf9bbd665ce1e7b9079983ee2d97a05f42e0569ff00a70f1dd8b1e"}, - {file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:72de8c4d71e6b11d54528bb924447fa4fdabcbb3d76cc0e7f61d3b6075def6b3"}, - {file = "pycryptodome-3.13.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:008ef2c631f112cd5a58736e0b29f4a28b4bb853e68878689f8b476fd56e0691"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:51ebe9624ad0a0b4da1aaaa2d43aabadf8537737fd494cee0ffa37cd6326de02"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:deede160bdf87ddb71f0a1314ad5a267b1a960be314ea7dc6b7ad86da6da89a3"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:857c16bffd938254e3a834cd6b2a755ed24e1a953b1a86e33da136d3e4c16a6f"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ca6db61335d07220de0b665bfee7b8e9615b2dfc67a54016db4826dac34c2dd2"}, - {file = "pycryptodome-3.13.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:073dedf0f9c490ae22ca081b86357646ac9b76f3e2bd89119d137fc697a9e3b6"}, - {file = "pycryptodome-3.13.0-cp35-abi3-win32.whl", hash = "sha256:e3affa03c49cce7b0a9501cc7f608d4f8e61fb2522b276d599ac049b5955576d"}, - {file = "pycryptodome-3.13.0-cp35-abi3-win_amd64.whl", hash = "sha256:e5d72be02b17e6bd7919555811264403468d1d052fa67c946e402257c3c29a27"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:0896d5d15ffe584d46cb9b69a75cf14a2bc8f6daf635b7bf16c1b041342a44b1"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:e420cdfca73f80fe15f79bb34756959945231a052440813e5fce531e6e96331a"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:720fafdf3e5c5de93039d8308f765cc60b8e9e7e852ad7135aa65dd89238191f"}, - {file = "pycryptodome-3.13.0-pp27-pypy_73-win32.whl", hash = "sha256:7a8b0e526ff239b4f4c61dd6898e2474d609843ffc437267f3a27ddff626e6f6"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d92a5eddffb0ad39f582f07c1de26e9daf6880e3e782a94bb7ebaf939567f8bf"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:cb9453c981554984c6f5c5ce7682d7286e65e2173d7416114c3593a977a01bf5"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:765b8b16bc1fd699e183dde642c7f2653b8f3c9c1a50051139908e9683f97732"}, - {file = "pycryptodome-3.13.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:b3af53dddf848afb38b3ac2bae7159ddad1feb9bac14aa3acec6ef1797b82f8d"}, - {file = "pycryptodome-3.13.0.tar.gz", hash = "sha256:95bacf9ff7d1b90bba537d3f5f6c834efe6bfbb1a0195cb3573f29e6716ef08d"}, -] - -[[package]] -name = "pydantic" -version = "1.9.1" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "pydantic-1.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8098a724c2784bf03e8070993f6d46aa2eeca031f8d8a048dff277703e6e193"}, - {file = "pydantic-1.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c320c64dd876e45254bdd350f0179da737463eea41c43bacbee9d8c9d1021f11"}, - {file = "pydantic-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18f3e912f9ad1bdec27fb06b8198a2ccc32f201e24174cec1b3424dda605a310"}, - {file = "pydantic-1.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11951b404e08b01b151222a1cb1a9f0a860a8153ce8334149ab9199cd198131"}, - {file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8bc541a405423ce0e51c19f637050acdbdf8feca34150e0d17f675e72d119580"}, - {file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e565a785233c2d03724c4dc55464559639b1ba9ecf091288dd47ad9c629433bd"}, - {file = "pydantic-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a4a88dcd6ff8fd47c18b3a3709a89adb39a6373f4482e04c1b765045c7e282fd"}, - {file = "pydantic-1.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:447d5521575f18e18240906beadc58551e97ec98142266e521c34968c76c8761"}, - {file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:985ceb5d0a86fcaa61e45781e567a59baa0da292d5ed2e490d612d0de5796918"}, - {file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059b6c1795170809103a1538255883e1983e5b831faea6558ef873d4955b4a74"}, - {file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d12f96b5b64bec3f43c8e82b4aab7599d0157f11c798c9f9c528a72b9e0b339a"}, - {file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ae72f8098acb368d877b210ebe02ba12585e77bd0db78ac04a1ee9b9f5dd2166"}, - {file = "pydantic-1.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:79b485767c13788ee314669008d01f9ef3bc05db9ea3298f6a50d3ef596a154b"}, - {file = "pydantic-1.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:494f7c8537f0c02b740c229af4cb47c0d39840b829ecdcfc93d91dcbb0779892"}, - {file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0f047e11febe5c3198ed346b507e1d010330d56ad615a7e0a89fae604065a0e"}, - {file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:969dd06110cb780da01336b281f53e2e7eb3a482831df441fb65dd30403f4608"}, - {file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:177071dfc0df6248fd22b43036f936cfe2508077a72af0933d0c1fa269b18537"}, - {file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9bcf8b6e011be08fb729d110f3e22e654a50f8a826b0575c7196616780683380"}, - {file = "pydantic-1.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a955260d47f03df08acf45689bd163ed9df82c0e0124beb4251b1290fa7ae728"}, - {file = "pydantic-1.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9ce157d979f742a915b75f792dbd6aa63b8eccaf46a1005ba03aa8a986bde34a"}, - {file = "pydantic-1.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf07cab5b279859c253d26a9194a8906e6f4a210063b84b433cf90a569de0c1"}, - {file = "pydantic-1.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d93d4e95eacd313d2c765ebe40d49ca9dd2ed90e5b37d0d421c597af830c195"}, - {file = "pydantic-1.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1542636a39c4892c4f4fa6270696902acb186a9aaeac6f6cf92ce6ae2e88564b"}, - {file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a9af62e9b5b9bc67b2a195ebc2c2662fdf498a822d62f902bf27cccb52dbbf49"}, - {file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fe4670cb32ea98ffbf5a1262f14c3e102cccd92b1869df3bb09538158ba90fe6"}, - {file = "pydantic-1.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:9f659a5ee95c8baa2436d392267988fd0f43eb774e5eb8739252e5a7e9cf07e0"}, - {file = "pydantic-1.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b83ba3825bc91dfa989d4eed76865e71aea3a6ca1388b59fc801ee04c4d8d0d6"}, - {file = "pydantic-1.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1dd8fecbad028cd89d04a46688d2fcc14423e8a196d5b0a5c65105664901f810"}, - {file = "pydantic-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02eefd7087268b711a3ff4db528e9916ac9aa18616da7bca69c1871d0b7a091f"}, - {file = "pydantic-1.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb57ba90929bac0b6cc2af2373893d80ac559adda6933e562dcfb375029acee"}, - {file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4ce9ae9e91f46c344bec3b03d6ee9612802682c1551aaf627ad24045ce090761"}, - {file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:72ccb318bf0c9ab97fc04c10c37683d9eea952ed526707fabf9ac5ae59b701fd"}, - {file = "pydantic-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b6760b08b7c395975d893e0b814a11cf011ebb24f7d869e7118f5a339a82e1"}, - {file = "pydantic-1.9.1-py3-none-any.whl", hash = "sha256:4988c0f13c42bfa9ddd2fe2f569c9d54646ce84adc5de84228cfe83396f3bd58"}, - {file = "pydantic-1.9.1.tar.gz", hash = "sha256:1ed987c3ff29fff7fd8c3ea3a3ea877ad310aae2ef9889a119e22d3f2db0691a"}, -] - -[package.dependencies] -typing-extensions = ">=3.7.4.3" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pyflakes" -version = "2.3.1" -description = "passive checker of Python programs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, - {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, -] - -[[package]] -name = "pyjwt" -version = "2.3.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"}, - {file = "PyJWT-2.3.0.tar.gz", hash = "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41"}, -] - -[package.extras] -crypto = ["cryptography (>=3.3.1)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.3.1)", "mypy", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pyotp" -version = "2.6.0" -description = "Python One Time Password Library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pyotp-2.6.0-py2.py3-none-any.whl", hash = "sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28"}, - {file = "pyotp-2.6.0.tar.gz", hash = "sha256:d28ddfd40e0c1b6a6b9da961c7d47a10261fb58f378cb00f05ce88b26df9c432"}, -] - -[[package]] -name = "pytest" -version = "6.2.5" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -files = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, -] - -[package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.14.0" -description = "Pytest support for asyncio." -optional = false -python-versions = ">= 3.5" -groups = ["dev"] -files = [ - {file = "pytest-asyncio-0.14.0.tar.gz", hash = "sha256:9882c0c6b24429449f5f969a5158b528f39bde47dc32e85b9f0403965017e700"}, - {file = "pytest_asyncio-0.14.0-py3-none-any.whl", hash = "sha256:2eae1e34f6c68fc0a9dc12d4bea190483843ff4708d24277c41568d6b6044f1d"}, -] - -[package.dependencies] -pytest = ">=5.4.0" - -[package.extras] -testing = ["async-generator (>=1.3)", "coverage", "hypothesis (>=5.7.1)"] - -[[package]] -name = "pytest-nhsd-apim" -version = "2.0.8" -description = "Pytest plugin accessing NHSDigital's APIM proxies" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pytest-nhsd-apim-2.0.8.tar.gz", hash = "sha256:202164b113ca1773e5c5391d1cca62d2d01f11ae8fa7566e4c44dc928e8964eb"}, - {file = "pytest_nhsd_apim-2.0.8-py3-none-any.whl", hash = "sha256:2d94fcf60d43b0bec816e06b42a7275d1bc26e1acbeacf10fff301db1202acb9"}, -] - -[package.dependencies] -Authlib = "0.15.5" -cryptography = "36.0.1" -lxml = "4.7.1" -pycryptodome = "3.13.0" -pydantic = "1.9.1" -PyJWT = "2.3.0" -pyotp = "2.6.0" -pytest = "6.2.5" -requests = "2.27.1" -toml = "0.10.2" -typing-extensions = "4.3.0" -wheel = "0.37.1" - -[[package]] -name = "pyyaml" -version = "5.4.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -groups = ["dev"] -files = [ - {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, - {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, - {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, - {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, - {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, - {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, - {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, - {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, - {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, -] - -[[package]] -name = "regex" -version = "2023.12.25" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, -] - -[[package]] -name = "requests" -version = "2.27.1" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -groups = ["main"] -files = [ - {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, - {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} -idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton ; sys_platform == \"win32\" and python_version == \"2.7\""] -use-chardet-on-py3 = ["chardet (>=3.0.2,<5)"] - -[[package]] -name = "semver" -version = "2.13.0" -description = "Python helper for Semantic Versioning (http://semver.org/)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4"}, - {file = "semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f"}, -] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["dev"] -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "smmap" -version = "5.0.1" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, - {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, -] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main", "dev"] -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - -[[package]] -name = "typed-ast" -version = "1.5.5" -description = "a fork of Python 2 and 3 ast modules with type comment support" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, - {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, - {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, - {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, - {file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"}, - {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"}, - {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"}, - {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"}, - {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"}, - {file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"}, - {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, - {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, - {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, - {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, - {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, -] - -[[package]] -name = "typing-extensions" -version = "4.3.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, -] - -[[package]] -name = "urllib3" -version = "1.26.18" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -groups = ["main"] -files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, -] - -[package.extras] -brotli = ["brotli (==1.0.9) ; os_name != \"nt\" and python_version < \"3\" and platform_python_implementation == \"CPython\"", "brotli (>=1.0.9) ; python_version >= \"3\" and platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; (os_name != \"nt\" or python_version >= \"3\") and platform_python_implementation != \"CPython\"", "brotlipy (>=0.6.0) ; os_name == \"nt\" and python_version < \"3\""] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress ; python_version == \"2.7\"", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "wheel" -version = "0.37.1" -description = "A built-package format for Python" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -groups = ["main"] -files = [ - {file = "wheel-0.37.1-py2.py3-none-any.whl", hash = "sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a"}, - {file = "wheel-0.37.1.tar.gz", hash = "sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4"}, -] - -[package.extras] -test = ["pytest (>=3.0.0)", "pytest-cov"] - -[[package]] -name = "yarl" -version = "1.15.2" -description = "Yet another URL library" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e4ee8b8639070ff246ad3649294336b06db37a94bdea0d09ea491603e0be73b8"}, - {file = "yarl-1.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a7cf963a357c5f00cb55b1955df8bbe68d2f2f65de065160a1c26b85a1e44172"}, - {file = "yarl-1.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:43ebdcc120e2ca679dba01a779333a8ea76b50547b55e812b8b92818d604662c"}, - {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3433da95b51a75692dcf6cc8117a31410447c75a9a8187888f02ad45c0a86c50"}, - {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38d0124fa992dbacd0c48b1b755d3ee0a9f924f427f95b0ef376556a24debf01"}, - {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ded1b1803151dd0f20a8945508786d57c2f97a50289b16f2629f85433e546d47"}, - {file = "yarl-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace4cad790f3bf872c082366c9edd7f8f8f77afe3992b134cfc810332206884f"}, - {file = "yarl-1.15.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c77494a2f2282d9bbbbcab7c227a4d1b4bb829875c96251f66fb5f3bae4fb053"}, - {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b7f227ca6db5a9fda0a2b935a2ea34a7267589ffc63c8045f0e4edb8d8dcf956"}, - {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:31561a5b4d8dbef1559b3600b045607cf804bae040f64b5f5bca77da38084a8a"}, - {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3e52474256a7db9dcf3c5f4ca0b300fdea6c21cca0148c8891d03a025649d935"}, - {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1af74a9529a1137c67c887ed9cde62cff53aa4d84a3adbec329f9ec47a3936"}, - {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:15c87339490100c63472a76d87fe7097a0835c705eb5ae79fd96e343473629ed"}, - {file = "yarl-1.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:74abb8709ea54cc483c4fb57fb17bb66f8e0f04438cff6ded322074dbd17c7ec"}, - {file = "yarl-1.15.2-cp310-cp310-win32.whl", hash = "sha256:ffd591e22b22f9cb48e472529db6a47203c41c2c5911ff0a52e85723196c0d75"}, - {file = "yarl-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:1695497bb2a02a6de60064c9f077a4ae9c25c73624e0d43e3aa9d16d983073c2"}, - {file = "yarl-1.15.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9fcda20b2de7042cc35cf911702fa3d8311bd40055a14446c1e62403684afdc5"}, - {file = "yarl-1.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0545de8c688fbbf3088f9e8b801157923be4bf8e7b03e97c2ecd4dfa39e48e0e"}, - {file = "yarl-1.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbda058a9a68bec347962595f50546a8a4a34fd7b0654a7b9697917dc2bf810d"}, - {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1ac2bc069f4a458634c26b101c2341b18da85cb96afe0015990507efec2e417"}, - {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd126498171f752dd85737ab1544329a4520c53eed3997f9b08aefbafb1cc53b"}, - {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3db817b4e95eb05c362e3b45dafe7144b18603e1211f4a5b36eb9522ecc62bcf"}, - {file = "yarl-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:076b1ed2ac819933895b1a000904f62d615fe4533a5cf3e052ff9a1da560575c"}, - {file = "yarl-1.15.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8cfd847e6b9ecf9f2f2531c8427035f291ec286c0a4944b0a9fce58c6446046"}, - {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:32b66be100ac5739065496c74c4b7f3015cef792c3174982809274d7e51b3e04"}, - {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:34a2d76a1984cac04ff8b1bfc939ec9dc0914821264d4a9c8fd0ed6aa8d4cfd2"}, - {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0afad2cd484908f472c8fe2e8ef499facee54a0a6978be0e0cff67b1254fd747"}, - {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c68e820879ff39992c7f148113b46efcd6ec765a4865581f2902b3c43a5f4bbb"}, - {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:98f68df80ec6ca3015186b2677c208c096d646ef37bbf8b49764ab4a38183931"}, - {file = "yarl-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56ec1eacd0a5d35b8a29f468659c47f4fe61b2cab948ca756c39b7617f0aa5"}, - {file = "yarl-1.15.2-cp311-cp311-win32.whl", hash = "sha256:eedc3f247ee7b3808ea07205f3e7d7879bc19ad3e6222195cd5fbf9988853e4d"}, - {file = "yarl-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:0ccaa1bc98751fbfcf53dc8dfdb90d96e98838010fc254180dd6707a6e8bb179"}, - {file = "yarl-1.15.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82d5161e8cb8f36ec778fd7ac4d740415d84030f5b9ef8fe4da54784a1f46c94"}, - {file = "yarl-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fa2bea05ff0a8fb4d8124498e00e02398f06d23cdadd0fe027d84a3f7afde31e"}, - {file = "yarl-1.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99e12d2bf587b44deb74e0d6170fec37adb489964dbca656ec41a7cd8f2ff178"}, - {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:243fbbbf003754fe41b5bdf10ce1e7f80bcc70732b5b54222c124d6b4c2ab31c"}, - {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:856b7f1a7b98a8c31823285786bd566cf06226ac4f38b3ef462f593c608a9bd6"}, - {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:553dad9af802a9ad1a6525e7528152a015b85fb8dbf764ebfc755c695f488367"}, - {file = "yarl-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30c3ff305f6e06650a761c4393666f77384f1cc6c5c0251965d6bfa5fbc88f7f"}, - {file = "yarl-1.15.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:353665775be69bbfc6d54c8d134bfc533e332149faeddd631b0bc79df0897f46"}, - {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f4fe99ce44128c71233d0d72152db31ca119711dfc5f2c82385ad611d8d7f897"}, - {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9c1e3ff4b89cdd2e1a24c214f141e848b9e0451f08d7d4963cb4108d4d798f1f"}, - {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:711bdfae4e699a6d4f371137cbe9e740dc958530cb920eb6f43ff9551e17cfbc"}, - {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4388c72174868884f76affcdd3656544c426407e0043c89b684d22fb265e04a5"}, - {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f0e1844ad47c7bd5d6fa784f1d4accc5f4168b48999303a868fe0f8597bde715"}, - {file = "yarl-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a5cafb02cf097a82d74403f7e0b6b9df3ffbfe8edf9415ea816314711764a27b"}, - {file = "yarl-1.15.2-cp312-cp312-win32.whl", hash = "sha256:156ececdf636143f508770bf8a3a0498de64da5abd890c7dbb42ca9e3b6c05b8"}, - {file = "yarl-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:435aca062444a7f0c884861d2e3ea79883bd1cd19d0a381928b69ae1b85bc51d"}, - {file = "yarl-1.15.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:416f2e3beaeae81e2f7a45dc711258be5bdc79c940a9a270b266c0bec038fb84"}, - {file = "yarl-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:173563f3696124372831007e3d4b9821746964a95968628f7075d9231ac6bb33"}, - {file = "yarl-1.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9ce2e0f6123a60bd1a7f5ae3b2c49b240c12c132847f17aa990b841a417598a2"}, - {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaea112aed589131f73d50d570a6864728bd7c0c66ef6c9154ed7b59f24da611"}, - {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4ca3b9f370f218cc2a0309542cab8d0acdfd66667e7c37d04d617012485f904"}, - {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23ec1d3c31882b2a8a69c801ef58ebf7bae2553211ebbddf04235be275a38548"}, - {file = "yarl-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75119badf45f7183e10e348edff5a76a94dc19ba9287d94001ff05e81475967b"}, - {file = "yarl-1.15.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78e6fdc976ec966b99e4daa3812fac0274cc28cd2b24b0d92462e2e5ef90d368"}, - {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8657d3f37f781d987037f9cc20bbc8b40425fa14380c87da0cb8dfce7c92d0fb"}, - {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:93bed8a8084544c6efe8856c362af08a23e959340c87a95687fdbe9c9f280c8b"}, - {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:69d5856d526802cbda768d3e6246cd0d77450fa2a4bc2ea0ea14f0d972c2894b"}, - {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ccad2800dfdff34392448c4bf834be124f10a5bc102f254521d931c1c53c455a"}, - {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:a880372e2e5dbb9258a4e8ff43f13888039abb9dd6d515f28611c54361bc5644"}, - {file = "yarl-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c998d0558805860503bc3a595994895ca0f7835e00668dadc673bbf7f5fbfcbe"}, - {file = "yarl-1.15.2-cp313-cp313-win32.whl", hash = "sha256:533a28754e7f7439f217550a497bb026c54072dbe16402b183fdbca2431935a9"}, - {file = "yarl-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:5838f2b79dc8f96fdc44077c9e4e2e33d7089b10788464609df788eb97d03aad"}, - {file = "yarl-1.15.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fbbb63bed5fcd70cd3dd23a087cd78e4675fb5a2963b8af53f945cbbca79ae16"}, - {file = "yarl-1.15.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2e93b88ecc8f74074012e18d679fb2e9c746f2a56f79cd5e2b1afcf2a8a786b"}, - {file = "yarl-1.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af8ff8d7dc07ce873f643de6dfbcd45dc3db2c87462e5c387267197f59e6d776"}, - {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66f629632220a4e7858b58e4857927dd01a850a4cef2fb4044c8662787165cf7"}, - {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:833547179c31f9bec39b49601d282d6f0ea1633620701288934c5f66d88c3e50"}, - {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2aa738e0282be54eede1e3f36b81f1e46aee7ec7602aa563e81e0e8d7b67963f"}, - {file = "yarl-1.15.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a13a07532e8e1c4a5a3afff0ca4553da23409fad65def1b71186fb867eeae8d"}, - {file = "yarl-1.15.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c45817e3e6972109d1a2c65091504a537e257bc3c885b4e78a95baa96df6a3f8"}, - {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:670eb11325ed3a6209339974b276811867defe52f4188fe18dc49855774fa9cf"}, - {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:d417a4f6943112fae3924bae2af7112562285848d9bcee737fc4ff7cbd450e6c"}, - {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bc8936d06cd53fddd4892677d65e98af514c8d78c79864f418bbf78a4a2edde4"}, - {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:954dde77c404084c2544e572f342aef384240b3e434e06cecc71597e95fd1ce7"}, - {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5bc0df728e4def5e15a754521e8882ba5a5121bd6b5a3a0ff7efda5d6558ab3d"}, - {file = "yarl-1.15.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b71862a652f50babab4a43a487f157d26b464b1dedbcc0afda02fd64f3809d04"}, - {file = "yarl-1.15.2-cp38-cp38-win32.whl", hash = "sha256:63eab904f8630aed5a68f2d0aeab565dcfc595dc1bf0b91b71d9ddd43dea3aea"}, - {file = "yarl-1.15.2-cp38-cp38-win_amd64.whl", hash = "sha256:2cf441c4b6e538ba0d2591574f95d3fdd33f1efafa864faa077d9636ecc0c4e9"}, - {file = "yarl-1.15.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a32d58f4b521bb98b2c0aa9da407f8bd57ca81f34362bcb090e4a79e9924fefc"}, - {file = "yarl-1.15.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:766dcc00b943c089349d4060b935c76281f6be225e39994c2ccec3a2a36ad627"}, - {file = "yarl-1.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bed1b5dbf90bad3bfc19439258c97873eab453c71d8b6869c136346acfe497e7"}, - {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed20a4bdc635f36cb19e630bfc644181dd075839b6fc84cac51c0f381ac472e2"}, - {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d538df442c0d9665664ab6dd5fccd0110fa3b364914f9c85b3ef9b7b2e157980"}, - {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c6cf1d92edf936ceedc7afa61b07e9d78a27b15244aa46bbcd534c7458ee1b"}, - {file = "yarl-1.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce44217ad99ffad8027d2fde0269ae368c86db66ea0571c62a000798d69401fb"}, - {file = "yarl-1.15.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47a6000a7e833ebfe5886b56a31cb2ff12120b1efd4578a6fcc38df16cc77bd"}, - {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e52f77a0cd246086afde8815039f3e16f8d2be51786c0a39b57104c563c5cbb0"}, - {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:f9ca0e6ce7774dc7830dc0cc4bb6b3eec769db667f230e7c770a628c1aa5681b"}, - {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:136f9db0f53c0206db38b8cd0c985c78ded5fd596c9a86ce5c0b92afb91c3a19"}, - {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:173866d9f7409c0fb514cf6e78952e65816600cb888c68b37b41147349fe0057"}, - {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:6e840553c9c494a35e449a987ca2c4f8372668ee954a03a9a9685075228e5036"}, - {file = "yarl-1.15.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:458c0c65802d816a6b955cf3603186de79e8fdb46d4f19abaec4ef0a906f50a7"}, - {file = "yarl-1.15.2-cp39-cp39-win32.whl", hash = "sha256:5b48388ded01f6f2429a8c55012bdbd1c2a0c3735b3e73e221649e524c34a58d"}, - {file = "yarl-1.15.2-cp39-cp39-win_amd64.whl", hash = "sha256:81dadafb3aa124f86dc267a2168f71bbd2bfb163663661ab0038f6e4b8edb810"}, - {file = "yarl-1.15.2-py3-none-any.whl", hash = "sha256:0d3105efab7c5c091609abacad33afff33bdff0035bece164c98bcf5a85ef90a"}, - {file = "yarl-1.15.2.tar.gz", hash = "sha256:a39c36f4218a5bb668b4f06874d676d35a035ee668e6e7e3538835c703634b84"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -propcache = ">=0.2.0" - -[metadata] -lock-version = "2.1" -python-versions = "^3.8" -content-hash = "7919cabef40410e28e5044175a76c7c1bf493064d9f30da72f6fc9fff882f730" diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 3abf6bace..000000000 --- a/pyproject.toml +++ /dev/null @@ -1,37 +0,0 @@ -[project] -name = "immunisation-fhir-api" -python = "^3.8" - -[tool.poetry] -name = "immunisation-fhir-api" -version = "0.0.1-alpha" -description = "FHIR server for Immunization resource" -authors = [] -readme = 'README.md' -license = "MIT" -repository = "https://github.com/NHSDigital/immunisation-fhir-api" -homepage = "https://github.com/NHSDigital/immunisation-fhir-api" -keywords = ["healthcare", "uk", "nhs"] - - -[tool.poetry.dependencies] -python = "^3.8" -pytest-nhsd-apim = "^2.0.2" - - -[tool.poetry.dev-dependencies] -flake8 = "^3.7.9" -black = "^20.8b1" -pip-licenses = "^2.0.1" -jinja2 = "^3.1.6" -pyyaml = "^5.2" -docopt = "^0.6.2" -jsonpath-rw = "^1.4.0" -semver = "^2.9.0" -gitpython = "^3.1.45" -pytest = "^6.1.2" -coverage = "^5.5" -aiohttp = "^3.10.11" -pytest-asyncio = "^0.14.0" - -[tool.poetry.scripts] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 1a4189b55..000000000 --- a/pytest.ini +++ /dev/null @@ -1,7 +0,0 @@ -[pytest] -python_files = *_tests.py test_*.py -norecursedirs = .venv .eggs build dist utils -addopts = --strict-markers -markers = - e2e: end to end tests - smoketest: suitable to run against all environments even production diff --git a/terraform/.terraform-version b/terraform/.terraform-version deleted file mode 100644 index 9edc58bb1..000000000 --- a/terraform/.terraform-version +++ /dev/null @@ -1 +0,0 @@ -1.6.4 diff --git a/test-report.xml b/test-report.xml deleted file mode 100644 index 51df42a33..000000000 --- a/test-report.xml +++ /dev/null @@ -1,23 +0,0 @@ -ImportError while importing test module '/Users/ewan.childs/Desktop/NHS/Bebop/immunisation-fhir-api/lambda_code/tests/test_get_imms.py'. -Hint: make sure your test modules/packages have valid Python names. -Traceback: -/usr/local/Cellar/python@3.9/3.9.18/Frameworks/Python.framework/Versions/3.9/lib/python3.9/importlib/__init__.py:127: in import_module - return _bootstrap._gcd_import(name[level:], package, level) -lambda_code/tests/test_get_imms.py:10: in <module> - from dynamodb import EventTable -E ImportError: cannot import name 'EventTable' from 'dynamodb' (/Users/ewan.childs/Desktop/NHS/Bebop/immunisation-fhir-api/dynamodb/__init__.py)tests/configuration/environment.py:6: in get_env - var = os.environ[variable_name] -/usr/local/Cellar/python@3.9/3.9.18/Frameworks/Python.framework/Versions/3.9/lib/python3.9/os.py:679: in __getitem__ - raise KeyError(key) from None -E KeyError: 'APIGEE_ENVIRONMENT' - -During handling of the above exception, another exception occurred: -tests/test_auth.py:3: in <module> - from .configuration import config -tests/configuration/config.py:1: in <module> - from .environment import ENV -tests/configuration/environment.py:15: in <module> - "environment": get_env("APIGEE_ENVIRONMENT"), -tests/configuration/environment.py:11: in get_env - raise RuntimeError(f"Variable is not set, Check {variable_name}.") -E RuntimeError: Variable is not set, Check APIGEE_ENVIRONMENT. \ No newline at end of file From d38d6ae3bfb204107268d6d0ec871789b15ca01f Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 11:49:41 +0100 Subject: [PATCH 2/9] Update quality checks pipeline. --- .github/workflows/quality-checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quality-checks.yml b/.github/workflows/quality-checks.yml index d4a76066b..71230d6b7 100644 --- a/.github/workflows/quality-checks.yml +++ b/.github/workflows/quality-checks.yml @@ -25,7 +25,7 @@ jobs: cache: "npm" - name: Install linting dependencies - run: make install-node + run: make install - name: Lint run: make lint From caa315cbd3c2fb5c7d8c38bfe7edde187f56b5eb Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 11:53:03 +0100 Subject: [PATCH 3/9] Update dist included files. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9d063496a..8e078369c 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ build-proxy: #Files to loop over in release # VED-811: remove everything except for proxy related files as we move to Github Actions for backend deployment -_dist_include="pytest.ini poetry.lock poetry.toml pyproject.toml Makefile build/. specification sandbox terraform scripts" +_dist_include="poetry.toml Makefile build/. specification sandbox terraform scripts" #Create /dist/ sub-directory and copy files into directory #Ensure full dir structure is preserved for Lambdas From 071221e5d6a2d8333a7291a25d05eb13a5faaf96 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 13:06:02 +0100 Subject: [PATCH 4/9] Remove unnecessary pipeline step and template. --- azure/templates/post-deploy.yml | 6 ---- azure/templates/run-tests.yml | 54 --------------------------------- 2 files changed, 60 deletions(-) delete mode 100644 azure/templates/run-tests.yml diff --git a/azure/templates/post-deploy.yml b/azure/templates/post-deploy.yml index 413d7818b..223b01e97 100644 --- a/azure/templates/post-deploy.yml +++ b/azure/templates/post-deploy.yml @@ -28,12 +28,6 @@ steps: - ptl/app-credentials/immunisation-fhir-api-testing-app/non-prod/INT_CLIENT_ID - ptl/app-credentials/immunisation-fhir-api-testing-app/non-prod/INT_CLIENT_SECRET - - bash: | - make install-python - workingDirectory: $(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME) - displayName: Setup pytests - condition: always() - - template: ./aws-assume-role.yml parameters: role: "auto-ops" diff --git a/azure/templates/run-tests.yml b/azure/templates/run-tests.yml deleted file mode 100644 index b97d7ba14..000000000 --- a/azure/templates/run-tests.yml +++ /dev/null @@ -1,54 +0,0 @@ -parameters: - - name: full - type: boolean - default: false - - name: test_command - type: string - default: "make test" - - name: smoketest_command - type: string - default: "make smoketest" - -steps: - - bash: | - make install-python - workingDirectory: $(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME) - displayName: Setup pytests - condition: always() - - - ${{ if parameters.full }}: - # In order to run tests in prod you must supply the unique ID of an Apigee app - # that has authorized access to your service proxy. - - bash: | - export PROXY_NAME="$(FULLY_QUALIFIED_SERVICE_NAME)" - export APIGEE_ACCESS_TOKEN="$(secret.AccessToken)" - export APIGEE_APP_ID="MY APP ID" - export STATUS_ENDPOINT_API_KEY="$(STATUS_ENDPOINT_API_KEY)" - export SOURCE_COMMIT_ID="$(Build.SourceVersion)" - ${{ parameters.test_command }} - workingDirectory: $(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME) - displayName: Run full test suite - - task: PublishTestResults@2 - displayName: "Publish test results" - condition: always() - inputs: - testResultsFiles: "$(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME)/test-report.xml" - failTaskOnFailedTests: true - - ${{ if not(parameters.full) }}: - # In order to run tests in prod you must supply the unique ID of an Apigee app - # that has authorized access to your service proxy. - - bash: | - export PROXY_NAME="$(FULLY_QUALIFIED_SERVICE_NAME)" - export APIGEE_ACCESS_TOKEN="$(secret.AccessToken)" - export APIGEE_APP_ID="MY APP ID" - export STATUS_ENDPOINT_API_KEY="$(STATUS_ENDPOINT_API_KEY)" - export SOURCE_COMMIT_ID="$(Build.SourceVersion)" - ${{ parameters.smoketest_command }} - workingDirectory: $(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME) - displayName: Run smoketests - - task: PublishTestResults@2 - displayName: "Publish smoketest results" - condition: always() - inputs: - testResultsFiles: "$(Pipeline.Workspace)/s/$(SERVICE_NAME)/$(SERVICE_ARTIFACT_NAME)/smoketest-report.xml" - failTaskOnFailedTests: true From 340939372f96cb4739eb6aa94952a3cbc96426c4 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 14:29:46 +0100 Subject: [PATCH 5/9] Reinstate .terraform-version while we're still using APIM pipelines. --- terraform/.terraform-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 terraform/.terraform-version diff --git a/terraform/.terraform-version b/terraform/.terraform-version new file mode 100644 index 000000000..6b89d58f8 --- /dev/null +++ b/terraform/.terraform-version @@ -0,0 +1 @@ +1.12.2 From a546ef3a17a771baea178aae5e803e93392a7fa3 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 15:47:12 +0100 Subject: [PATCH 6/9] Switch to Ruff for Python linting and formatting. --- backend/src/authorisation/authoriser.py | 2 +- .../src/controller/aws_apig_event_utils.py | 1 - .../controller/fhir_api_exception_handler.py | 8 +- backend/src/controller/fhir_controller.py | 17 +- backend/src/create_imms_handler.py | 2 +- backend/src/delete_imms_handler.py | 2 +- backend/src/filter.py | 5 +- backend/src/forwarding_batch_lambda.py | 7 +- backend/src/models/fhir_immunization.py | 1 - .../fhir_immunization_post_validators.py | 2 +- .../fhir_immunization_pre_validators.py | 10 +- backend/src/models/field_locations.py | 4 +- backend/src/models/obtain_field_value.py | 2 +- backend/src/models/utils/base_utils.py | 2 - backend/src/models/utils/generic_utils.py | 9 +- .../src/models/utils/pre_validator_utils.py | 5 +- backend/src/models/utils/validation_utils.py | 2 +- backend/src/not_found_handler.py | 1 - backend/src/parameter_parser.py | 3 +- .../src/repository/fhir_batch_repository.py | 8 +- backend/src/repository/fhir_repository.py | 9 +- backend/src/search_imms_handler.py | 6 +- backend/src/service/fhir_batch_service.py | 7 +- backend/src/service/fhir_service.py | 28 +-- backend/src/timer.py | 1 - backend/src/update_imms_handler.py | 2 +- backend/src/utils/dict_utils.py | 2 +- .../test_fhir_api_exception_handler.py | 2 +- .../controller/test_fhir_batch_controller.py | 7 +- .../tests/controller/test_fhir_controller.py | 15 +- .../tests/models/utils/test_generic_utils.py | 5 +- .../repository/test_fhir_batch_repository.py | 16 +- .../tests/repository/test_fhir_repository.py | 5 +- .../tests/service/test_fhir_batch_service.py | 3 - backend/tests/service/test_fhir_service.py | 44 ++-- backend/tests/test_api_errors.py | 2 +- backend/tests/test_create_imms.py | 2 +- backend/tests/test_delete_imms.py | 2 +- backend/tests/test_filter.py | 4 +- backend/tests/test_forwarding_batch_lambda.py | 14 +- .../tests/test_immunization_post_validator.py | 15 +- .../tests/test_immunization_pre_validator.py | 17 +- backend/tests/test_lambda_handler.py | 1 - backend/tests/test_log_structure_wrapper.py | 1 - backend/tests/test_parameter_parser.py | 6 +- backend/tests/test_search_imms.py | 2 +- backend/tests/test_validation_utils.py | 5 +- backend/tests/testing_utils/generic_utils.py | 5 +- .../tests/testing_utils/immunization_utils.py | 13 +- .../pre_validation_test_utils.py | 2 +- .../testing_utils/test_utils_for_batch.py | 1 - backend/tests/utils/test_dict_utils.py | 1 - .../src/batch_audit_repository.py | 5 +- .../src/batch_file_repository.py | 5 +- .../src/batch_processor_filter_service.py | 6 +- batch_processor_filter/src/lambda_handler.py | 3 +- batch_processor_filter/src/logger.py | 1 - .../src/send_log_to_firehose.py | 4 +- .../tests/test_lambda_handler.py | 24 +- batch_processor_filter/tests/testing_utils.py | 3 +- delta_backend/src/converter.py | 3 +- delta_backend/src/delta.py | 5 +- delta_backend/src/extractor.py | 4 +- delta_backend/src/log_firehose.py | 1 - delta_backend/tests/check_conversion.py | 2 +- delta_backend/tests/test_convert.py | 10 +- delta_backend/tests/test_convert_dates.py | 6 +- .../tests/test_convert_dose_amount.py | 6 +- .../tests/test_convert_dose_sequence.py | 6 +- .../tests/test_convert_location_code.py | 6 +- .../test_convert_location_code_type_uri.py | 6 +- .../tests/test_convert_lot_number.py | 6 +- .../tests/test_convert_manufacturer.py | 6 +- .../tests/test_convert_nhs_number.py | 6 +- .../tests/test_convert_person_forename.py | 5 +- .../tests/test_convert_person_gender.py | 6 +- .../tests/test_convert_person_surname.py | 5 +- delta_backend/tests/test_convert_post_code.py | 6 +- .../test_convert_practitioner_forename.py | 6 +- .../test_convert_practitioner_surname.py | 6 +- .../tests/test_convert_primary_source.py | 6 +- delta_backend/tests/test_convert_site_code.py | 6 +- delta_backend/tests/test_convert_site_uri.py | 6 +- .../tests/test_convert_snomed_codes.py | 6 +- .../tests/test_convert_snomed_terms.py | 6 +- delta_backend/tests/test_convert_unique_id.py | 6 +- .../tests/test_convert_unique_id_uri.py | 6 +- delta_backend/tests/test_current_period.py | 1 + delta_backend/tests/test_delta.py | 24 +- delta_backend/tests/test_log_firehose.py | 6 +- delta_backend/tests/test_utils.py | 2 +- .../tests/utils_for_converter_tests.py | 7 +- e2e/lib/apigee.py | 2 +- e2e/lib/authentication.py | 2 +- e2e/lib/env.py | 3 +- e2e/test_authorization.py | 3 +- e2e/test_create_immunization.py | 1 - e2e/test_delete_immunization.py | 1 - e2e/test_delta_immunization.py | 1 - e2e/test_deployment.py | 3 +- e2e/test_get_immunization.py | 3 +- e2e/test_proxy.py | 5 +- e2e/test_search_by_identifier_immunization.py | 6 +- ...search_identifier_elements_immunization.py | 3 +- e2e/test_search_immunization.py | 6 +- e2e/test_sqs_dlq.py | 2 - e2e/test_update_immunization.py | 1 - e2e/utils/base_test.py | 9 +- e2e/utils/factories.py | 8 +- e2e/utils/immunisation_api.py | 11 +- e2e/utils/resource.py | 9 +- e2e_batch/clients.py | 9 +- e2e_batch/scenarios.py | 29 ++- e2e_batch/test_e2e_batch.py | 33 ++- e2e_batch/utils.py | 41 ++-- filenameprocessor/src/audit_table.py | 3 +- filenameprocessor/src/clients.py | 6 +- filenameprocessor/src/constants.py | 2 +- filenameprocessor/src/elasticache.py | 5 +- filenameprocessor/src/file_name_processor.py | 27 +-- filenameprocessor/src/file_validation.py | 5 +- filenameprocessor/src/logging_decorator.py | 1 + .../src/make_and_upload_ack_file.py | 5 +- filenameprocessor/src/send_sqs_message.py | 3 +- filenameprocessor/src/supplier_permissions.py | 2 +- .../src/utils_for_filenameprocessor.py | 3 +- filenameprocessor/tests/test_audit_table.py | 9 +- filenameprocessor/tests/test_elasticache.py | 7 +- .../tests/test_file_key_validation.py | 4 +- .../tests/test_lambda_handler.py | 28 +-- .../tests/test_logging_decorator.py | 13 +- .../tests/test_make_and_upload_ack_file.py | 13 +- .../tests/test_send_sqs_message.py | 11 +- .../tests/test_supplier_permissions.py | 2 +- .../tests/test_utils_for_filenameprocessor.py | 15 +- .../generic_setup_and_teardown.py | 8 +- .../utils_for_filenameprocessor_tests.py | 15 +- .../tests/utils_for_tests/values_for_tests.py | 2 +- lambdas/ack_backend/src/ack_processor.py | 4 +- lambdas/ack_backend/src/audit_table.py | 2 +- lambdas/ack_backend/src/logging_decorators.py | 3 +- lambdas/ack_backend/src/update_ack_file.py | 7 +- .../ack_backend/tests/test_ack_processor.py | 25 +- lambdas/ack_backend/tests/test_audit_table.py | 2 +- .../tests/test_convert_message_to_ack_row.py | 8 +- .../tests/test_logging_decorators.py | 1 + .../ack_backend/tests/test_splunk_logging.py | 23 +- .../ack_backend/tests/test_update_ack_file.py | 30 +-- .../tests/test_update_ack_file_flow.py | 7 +- ...eric_setup_and_teardown_for_ack_backend.py | 4 +- .../utils/utils_for_ack_backend_tests.py | 3 +- lambdas/id_sync/src/id_sync.py | 3 +- lambdas/id_sync/src/ieds_db_operations.py | 9 +- lambdas/id_sync/src/pds_details.py | 3 +- lambdas/id_sync/src/record_processor.py | 12 +- lambdas/id_sync/src/utils.py | 2 +- lambdas/id_sync/tests/test_id_sync.py | 6 +- .../id_sync/tests/test_ieds_db_operations.py | 10 +- lambdas/id_sync/tests/test_os_vars.py | 3 +- lambdas/id_sync/tests/test_pds_details.py | 6 +- .../id_sync/tests/test_record_processor.py | 2 +- lambdas/mns_subscription/src/mns_service.py | 16 +- lambdas/mns_subscription/src/mns_setup.py | 3 +- lambdas/mns_subscription/src/subscribe_mns.py | 1 + .../mns_subscription/src/unsubscribe_mns.py | 1 + .../tests/test_mns_service.py | 15 +- .../mns_subscription/tests/test_mns_setup.py | 4 +- .../tests/test_subscribe_mns.py | 4 +- .../tests/test_unsubscribe_mns.py | 4 +- lambdas/redis_sync/src/record_processor.py | 2 +- lambdas/redis_sync/src/redis_cacher.py | 3 +- lambdas/redis_sync/src/redis_sync.py | 5 +- lambdas/redis_sync/src/transform_map.py | 4 +- lambdas/redis_sync/tests/test_event_read.py | 1 + lambdas/redis_sync/tests/test_handler.py | 4 +- .../tests/test_handler_decorator.py | 8 +- .../redis_sync/tests/test_record_processor.py | 4 +- lambdas/redis_sync/tests/test_redis_cacher.py | 2 +- .../redis_sync/tests/test_transform_config.py | 5 +- .../redis_sync/tests/test_transform_map.py | 3 +- lambdas/shared/src/common/authentication.py | 7 +- lambdas/shared/src/common/aws_lambda_event.py | 3 +- lambdas/shared/src/common/clients.py | 6 +- lambdas/shared/src/common/log_decorator.py | 3 +- lambdas/shared/src/common/pds_service.py | 2 +- lambdas/shared/src/common/redis_client.py | 1 + lambdas/shared/src/common/s3_reader.py | 2 +- .../tests/test_common/test_authentication.py | 6 +- .../tests/test_common/test_aws_dynamodb.py | 4 +- .../test_common/test_aws_lambda_event.py | 4 +- .../shared/tests/test_common/test_clients.py | 7 +- .../shared/tests/test_common/test_errors.py | 2 +- .../tests/test_common/test_log_decorator.py | 7 +- .../tests/test_common/test_pds_service.py | 4 +- .../tests/test_common/test_redis_client.py | 4 +- .../shared/tests/test_common/test_s3_event.py | 2 +- .../tests/test_common/test_s3_reader.py | 3 +- package.json | 4 +- quality_checks/.flake8 | 16 -- quality_checks/Makefile | 6 +- quality_checks/poetry.lock | 220 +++--------------- quality_checks/pyproject.toml | 4 +- recordprocessor/src/audit_table.py | 2 +- recordprocessor/src/batch_processor.py | 20 +- recordprocessor/src/clients.py | 3 +- .../src/convert_to_fhir_imms_resource.py | 7 +- recordprocessor/src/file_level_validation.py | 20 +- recordprocessor/src/logging_decorator.py | 3 +- .../src/make_and_upload_ack_file.py | 3 +- recordprocessor/src/mappings.py | 3 +- recordprocessor/src/models/utils.py | 2 +- recordprocessor/src/process_row.py | 4 +- recordprocessor/src/send_to_kinesis.py | 1 + .../src/utils_for_fhir_conversion.py | 1 + .../src/utils_for_recordprocessor.py | 1 + recordprocessor/tests/test_audit_table.py | 20 +- .../test_convert_to_fhir_imms_decorators.py | 14 +- .../test_convert_to_fhir_imms_resource.py | 10 +- .../tests/test_file_level_validation.py | 9 +- .../tests/test_logging_decorator.py | 20 +- .../tests/test_make_and_upload_ack_file.py | 8 +- .../tests/test_map_target_disease.py | 1 + .../tests/test_process_csv_to_fhir.py | 17 +- recordprocessor/tests/test_process_row.py | 17 +- .../tests/test_recordprocessor_edge_cases.py | 5 +- .../tests/test_recordprocessor_main.py | 43 ++-- recordprocessor/tests/test_send_to_kinesis.py | 11 +- .../tests/test_utils_for_fhir_conversion.py | 5 +- .../tests/test_utils_for_recordprocessor.py | 22 +- .../decorator_constants.py | 9 +- .../generic_setup_and_teardown.py | 9 +- .../utils_for_recordprocessor_tests.py | 25 +- .../values_for_recordprocessor_tests.py | 5 +- ruff.toml | 7 + scripts/calculate_version.py | 4 +- scripts/destroy_unused_workspaces.py | 4 +- scripts/set_version.py | 4 +- scripts/yaml2json.py | 6 +- temporary_sandbox/fhir_api/__init__.py | 8 +- .../fhir_api/exceptions/base_exceptions.py | 6 +- .../fhir_api/models/dynamodb/data_input.py | 4 +- .../fhir_api/models/dynamodb/read_models.py | 10 +- .../fhir_api/models/dynamodb/update_model.py | 12 +- .../fhir_api/models/fhir_r4/common.py | 6 +- .../models/fhir_r4/fhir_datatype_fields.py | 8 +- .../fhir_api/models/fhir_r4/immunization.py | 10 +- .../fhir_api/models/fhir_r4/patient.py | 20 +- temporary_sandbox/fhir_api/routes/dynamodb.py | 3 +- temporary_sandbox/fhir_api/routes/root.py | 1 - 249 files changed, 876 insertions(+), 1096 deletions(-) delete mode 100644 quality_checks/.flake8 create mode 100644 ruff.toml diff --git a/backend/src/authorisation/authoriser.py b/backend/src/authorisation/authoriser.py index ac5e48026..d6f406bdc 100644 --- a/backend/src/authorisation/authoriser.py +++ b/backend/src/authorisation/authoriser.py @@ -3,7 +3,7 @@ import json from authorisation.api_operation_code import ApiOperationCode -from clients import redis_client, logger +from clients import logger, redis_client from constants import SUPPLIER_PERMISSIONS_HASH_KEY diff --git a/backend/src/controller/aws_apig_event_utils.py b/backend/src/controller/aws_apig_event_utils.py index 87b6bb05e..93d7c93ac 100644 --- a/backend/src/controller/aws_apig_event_utils.py +++ b/backend/src/controller/aws_apig_event_utils.py @@ -3,7 +3,6 @@ from typing import Optional from aws_lambda_typing.events import APIGatewayProxyEventV1 - from controller.constants import SUPPLIER_SYSTEM_HEADER_NAME from models.errors import UnauthorizedError from utils import dict_utils diff --git a/backend/src/controller/fhir_api_exception_handler.py b/backend/src/controller/fhir_api_exception_handler.py index 3ec89d928..ddda753f0 100644 --- a/backend/src/controller/fhir_api_exception_handler.py +++ b/backend/src/controller/fhir_api_exception_handler.py @@ -8,12 +8,12 @@ from constants import GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE from controller.aws_apig_response_utils import create_response from models.errors import ( - UnauthorizedVaxError, - UnauthorizedError, + Code, ResourceNotFoundError, - create_operation_outcome, Severity, - Code, + UnauthorizedError, + UnauthorizedVaxError, + create_operation_outcome, ) _CUSTOM_EXCEPTION_TO_STATUS_MAP: dict[Type[Exception], int] = { diff --git a/backend/src/controller/fhir_controller.py b/backend/src/controller/fhir_controller.py index 319d01f44..2ccdaf4fc 100644 --- a/backend/src/controller/fhir_controller.py +++ b/backend/src/controller/fhir_controller.py @@ -8,28 +8,27 @@ from typing import Optional from aws_lambda_typing.events import APIGatewayProxyEventV1 - from controller.aws_apig_event_utils import ( - get_supplier_system_header, get_path_parameter, + get_supplier_system_header, ) from controller.aws_apig_response_utils import create_response from controller.constants import E_TAG_HEADER_NAME from controller.fhir_api_exception_handler import fhir_api_exception_handler from models.errors import ( - Severity, Code, - create_operation_outcome, - UnauthorizedError, - ResourceNotFoundError, - UnhandledResponseError, - ValidationError, IdentifierDuplicationError, ParameterException, + ResourceNotFoundError, + Severity, + UnauthorizedError, UnauthorizedVaxError, + UnhandledResponseError, + ValidationError, + create_operation_outcome, ) from models.utils.generic_utils import check_keys_in_sources -from parameter_parser import process_params, process_search_params, create_query_string +from parameter_parser import create_query_string, process_params, process_search_params from repository.fhir_repository import ImmunizationRepository, create_table from service.fhir_service import FhirService, UpdateOutcome, get_service_url diff --git a/backend/src/create_imms_handler.py b/backend/src/create_imms_handler.py index f61832123..5eee06358 100644 --- a/backend/src/create_imms_handler.py +++ b/backend/src/create_imms_handler.py @@ -8,7 +8,7 @@ from controller.fhir_controller import FhirController, make_controller from local_lambda import load_string from log_structure import function_info -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome logging.basicConfig(level="INFO") logger = logging.getLogger() diff --git a/backend/src/delete_imms_handler.py b/backend/src/delete_imms_handler.py index e621050d3..f32ba79db 100644 --- a/backend/src/delete_imms_handler.py +++ b/backend/src/delete_imms_handler.py @@ -7,7 +7,7 @@ from controller.aws_apig_response_utils import create_response from controller.fhir_controller import FhirController, make_controller from log_structure import function_info -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome logging.basicConfig(level="INFO") logger = logging.getLogger() diff --git a/backend/src/filter.py b/backend/src/filter.py index 8aa3f89d0..61cd8a198 100644 --- a/backend/src/filter.py +++ b/backend/src/filter.py @@ -2,9 +2,9 @@ from constants import Urls from models.utils.generic_utils import ( - is_actor_referencing_contained_resource, - get_contained_practitioner, get_contained_patient, + get_contained_practitioner, + is_actor_referencing_contained_resource, ) @@ -63,7 +63,6 @@ def replace_organization_values(imms: dict) -> dict: """ for performer in imms.get("performer", [{}]): if performer.get("actor", {}).get("type") == "Organization": - # Obfuscate or set the identifier value and system. identifier = performer["actor"].get("identifier", {}) if identifier.get("value") is not None: diff --git a/backend/src/forwarding_batch_lambda.py b/backend/src/forwarding_batch_lambda.py index 74cad1fbe..890a6f8cc 100644 --- a/backend/src/forwarding_batch_lambda.py +++ b/backend/src/forwarding_batch_lambda.py @@ -7,7 +7,6 @@ from datetime import datetime import simplejson as json - from batch.batch_filename_to_events_mapper import BatchFilenameToEventsMapper from clients import sqs_client from controller.fhir_batch_controller import ( @@ -15,12 +14,12 @@ make_batch_controller, ) from models.errors import ( - MessageNotSuccessfulError, - RecordProcessorError, CustomValidationError, IdentifierDuplicationError, - ResourceNotFoundError, + MessageNotSuccessfulError, + RecordProcessorError, ResourceFoundError, + ResourceNotFoundError, ) from repository.fhir_batch_repository import create_table diff --git a/backend/src/models/fhir_immunization.py b/backend/src/models/fhir_immunization.py index 1f6e61867..ccb4f9852 100644 --- a/backend/src/models/fhir_immunization.py +++ b/backend/src/models/fhir_immunization.py @@ -1,7 +1,6 @@ """Immunization FHIR R4B validator""" from fhir.resources.R4B.immunization import Immunization - from models.fhir_immunization_post_validators import PostValidators from models.fhir_immunization_pre_validators import PreValidators from models.utils.validation_utils import get_vaccine_type diff --git a/backend/src/models/fhir_immunization_post_validators.py b/backend/src/models/fhir_immunization_post_validators.py index f4688de1d..f38aea1e2 100644 --- a/backend/src/models/fhir_immunization_post_validators.py +++ b/backend/src/models/fhir_immunization_post_validators.py @@ -4,7 +4,7 @@ from models.field_locations import FieldLocations from models.field_names import FieldNames from models.mandation_functions import MandationFunctions -from models.utils.base_utils import obtain_field_value, obtain_field_location +from models.utils.base_utils import obtain_field_location, obtain_field_value from models.validation_sets import ValidationSets diff --git a/backend/src/models/fhir_immunization_pre_validators.py b/backend/src/models/fhir_immunization_pre_validators.py index 94e4435e4..d40d977ac 100644 --- a/backend/src/models/fhir_immunization_pre_validators.py +++ b/backend/src/models/fhir_immunization_pre_validators.py @@ -4,14 +4,14 @@ from models.constants import Constants from models.errors import MandatoryError from models.utils.generic_utils import ( - get_generic_extension_value, - generate_field_location_for_extension, check_for_unknown_elements, - patient_name_given_field_location, + generate_field_location_for_extension, + get_generic_extension_value, + patient_and_practitioner_value_and_index, patient_name_family_field_location, - practitioner_name_given_field_location, + patient_name_given_field_location, practitioner_name_family_field_location, - patient_and_practitioner_value_and_index, + practitioner_name_given_field_location, ) from models.utils.pre_validator_utils import PreValidation diff --git a/backend/src/models/field_locations.py b/backend/src/models/field_locations.py index 9c7ef1e41..031fabd37 100644 --- a/backend/src/models/field_locations.py +++ b/backend/src/models/field_locations.py @@ -8,10 +8,10 @@ from constants import Urls from models.utils.generic_utils import ( generate_field_location_for_extension, - patient_name_given_field_location, patient_name_family_field_location, - practitioner_name_given_field_location, + patient_name_given_field_location, practitioner_name_family_field_location, + practitioner_name_given_field_location, ) diff --git a/backend/src/models/obtain_field_value.py b/backend/src/models/obtain_field_value.py index 3258c4bcf..80e33c7d3 100644 --- a/backend/src/models/obtain_field_value.py +++ b/backend/src/models/obtain_field_value.py @@ -4,8 +4,8 @@ from models.utils.generic_utils import ( get_contained_patient, get_contained_practitioner, - is_organization, get_generic_extension_value, + is_organization, patient_and_practitioner_value_and_index, ) diff --git a/backend/src/models/utils/base_utils.py b/backend/src/models/utils/base_utils.py index 7314fa434..dc523c155 100644 --- a/backend/src/models/utils/base_utils.py +++ b/backend/src/models/utils/base_utils.py @@ -1,10 +1,8 @@ """Utils for backend src code""" from models.field_locations import FieldLocations - from models.obtain_field_value import ObtainFieldValue - FIELD_LOCATIONS = FieldLocations() diff --git a/backend/src/models/utils/generic_utils.py b/backend/src/models/utils/generic_utils.py index 1c91de47c..891d0d158 100644 --- a/backend/src/models/utils/generic_utils.py +++ b/backend/src/models/utils/generic_utils.py @@ -4,18 +4,19 @@ import datetime import json import urllib.parse -from typing import Literal, Union, Optional, Dict, Any +from typing import Any, Dict, Literal, Optional, Union from fhir.resources.R4B.bundle import ( Bundle as FhirBundle, +) +from fhir.resources.R4B.bundle import ( BundleEntry, - BundleLink, BundleEntrySearch, + BundleLink, ) from fhir.resources.R4B.immunization import Immunization -from stdnum.verhoeff import validate - from models.constants import Constants +from stdnum.verhoeff import validate def get_contained_resource(imms: dict, resource: Literal["Patient", "Practitioner", "QuestionnaireResponse"]): diff --git a/backend/src/models/utils/pre_validator_utils.py b/backend/src/models/utils/pre_validator_utils.py index 2ac164d47..793d86f92 100644 --- a/backend/src/models/utils/pre_validator_utils.py +++ b/backend/src/models/utils/pre_validator_utils.py @@ -1,12 +1,11 @@ -from datetime import datetime, date +from datetime import date, datetime from decimal import Decimal from typing import Union -from .generic_utils import nhs_number_mod11_check, is_valid_simple_snomed +from .generic_utils import is_valid_simple_snomed, nhs_number_mod11_check class PreValidation: - @staticmethod def for_string( field_value: str, diff --git a/backend/src/models/utils/validation_utils.py b/backend/src/models/utils/validation_utils.py index 412332e92..990821aa5 100644 --- a/backend/src/models/utils/validation_utils.py +++ b/backend/src/models/utils/validation_utils.py @@ -9,6 +9,7 @@ from models.field_names import FieldNames from models.obtain_field_value import ObtainFieldValue from models.utils.base_utils import obtain_field_location + from .generic_utils import create_diagnostics_error @@ -27,7 +28,6 @@ def get_target_disease_codes(immunization: dict): # For each item in the target disease list, extract the snomed code for i, element in enumerate(target_disease): - try: code = [x["code"] for x in element["coding"] if x.get("system") == Urls.snomed][0] except (KeyError, IndexError) as error: diff --git a/backend/src/not_found_handler.py b/backend/src/not_found_handler.py index 8acf38ab6..2f0d21fb4 100644 --- a/backend/src/not_found_handler.py +++ b/backend/src/not_found_handler.py @@ -11,7 +11,6 @@ def not_found_handler(event, context): def not_found(event, _context): - if event.get("httpMethod") not in ALLOWED_METHODS: response = { "statusCode": 405, diff --git a/backend/src/parameter_parser.py b/backend/src/parameter_parser.py index 21d996781..f72b1c0ad 100644 --- a/backend/src/parameter_parser.py +++ b/backend/src/parameter_parser.py @@ -2,10 +2,9 @@ import datetime from dataclasses import dataclass from typing import Optional -from urllib.parse import parse_qs, urlencode, quote +from urllib.parse import parse_qs, quote, urlencode from aws_lambda_typing.events import APIGatewayProxyEventV1 - from clients import redis_client from models.constants import Constants from models.errors import ParameterException diff --git a/backend/src/repository/fhir_batch_repository.py b/backend/src/repository/fhir_batch_repository.py index 7e8ad4c53..24e2fd612 100644 --- a/backend/src/repository/fhir_batch_repository.py +++ b/backend/src/repository/fhir_batch_repository.py @@ -6,14 +6,13 @@ import boto3 import botocore.exceptions import simplejson as json -from boto3.dynamodb.conditions import Key, Attr - +from boto3.dynamodb.conditions import Attr, Key from clients import logger from models.errors import ( - UnhandledResponseError, IdentifierDuplicationError, - ResourceNotFoundError, ResourceFoundError, + ResourceNotFoundError, + UnhandledResponseError, ) @@ -94,7 +93,6 @@ def __init__(self, imms: dict, vax_type: str, supplier: str, version: int): class ImmunizationBatchRepository: - def create_immunization( self, immunization: any, diff --git a/backend/src/repository/fhir_repository.py b/backend/src/repository/fhir_repository.py index efc133c8f..ed8cbd834 100644 --- a/backend/src/repository/fhir_repository.py +++ b/backend/src/repository/fhir_repository.py @@ -9,18 +9,17 @@ import simplejson as json from boto3.dynamodb.conditions import Attr, Key from botocore.config import Config -from mypy_boto3_dynamodb.service_resource import DynamoDBServiceResource, Table -from responses import logger - from models.errors import ( + IdentifierDuplicationError, ResourceNotFoundError, UnhandledResponseError, - IdentifierDuplicationError, ) from models.utils.validation_utils import ( - get_vaccine_type, check_identifier_system_value, + get_vaccine_type, ) +from mypy_boto3_dynamodb.service_resource import DynamoDBServiceResource, Table +from responses import logger def create_table(table_name=None, endpoint_url=None, region_name="eu-west-2"): diff --git a/backend/src/search_imms_handler.py b/backend/src/search_imms_handler.py index 7254566a1..f8f275ea7 100644 --- a/backend/src/search_imms_handler.py +++ b/backend/src/search_imms_handler.py @@ -6,13 +6,13 @@ import urllib.parse import uuid -from aws_lambda_typing import context as context_, events - +from aws_lambda_typing import context as context_ +from aws_lambda_typing import events from constants import GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE, MAX_RESPONSE_SIZE_BYTES from controller.aws_apig_response_utils import create_response from controller.fhir_controller import FhirController, make_controller from log_structure import function_info -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome logging.basicConfig(level="INFO") logger = logging.getLogger() diff --git a/backend/src/service/fhir_batch_service.py b/backend/src/service/fhir_batch_service.py index 85e39a1e8..48c200840 100644 --- a/backend/src/service/fhir_batch_service.py +++ b/backend/src/service/fhir_batch_service.py @@ -1,9 +1,6 @@ -from pydantic import ValidationError - -from models.errors import CustomValidationError -from models.errors import MandatoryError +from models.errors import CustomValidationError, MandatoryError from models.fhir_immunization import ImmunizationValidator - +from pydantic import ValidationError from repository.fhir_batch_repository import ImmunizationBatchRepository IMMUNIZATION_VALIDATOR = ImmunizationValidator() diff --git a/backend/src/service/fhir_service.py b/backend/src/service/fhir_service.py index 45616521c..bc9000278 100644 --- a/backend/src/service/fhir_service.py +++ b/backend/src/service/fhir_service.py @@ -1,42 +1,39 @@ import datetime import logging import os - - from enum import Enum from typing import Optional, Union from uuid import uuid4 +import parameter_parser +from authorisation.api_operation_code import ApiOperationCode +from authorisation.authoriser import Authoriser from fhir.resources.R4B.bundle import ( Bundle as FhirBundle, +) +from fhir.resources.R4B.bundle import ( BundleEntry, - BundleLink, BundleEntrySearch, + BundleLink, ) from fhir.resources.R4B.immunization import Immunization -from pydantic import ValidationError - -import parameter_parser -from authorisation.api_operation_code import ApiOperationCode -from authorisation.authoriser import Authoriser - from filter import Filter from models.errors import ( - InvalidPatientId, CustomValidationError, - UnauthorizedVaxError, + InvalidPatientId, + MandatoryError, ResourceNotFoundError, + UnauthorizedVaxError, ) -from models.errors import MandatoryError from models.fhir_immunization import ImmunizationValidator - from models.utils.generic_utils import ( - nhs_number_mod11_check, - get_occurrence_datetime, form_json, get_contained_patient, + get_occurrence_datetime, + nhs_number_mod11_check, ) from models.utils.validation_utils import get_vaccine_type +from pydantic import ValidationError from repository.fhir_repository import ImmunizationRepository from timer import timed @@ -54,7 +51,6 @@ def get_service_url( service_env: str = IMMUNIZATION_ENV, service_base_path: str = IMMUNIZATION_BASE_PATH, ) -> str: - if not service_base_path: service_base_path = "immunisation-fhir-api/FHIR/R4" diff --git a/backend/src/timer.py b/backend/src/timer.py index c78fda30d..777246c79 100644 --- a/backend/src/timer.py +++ b/backend/src/timer.py @@ -1,6 +1,5 @@ import logging import time - from functools import wraps logging.basicConfig() diff --git a/backend/src/update_imms_handler.py b/backend/src/update_imms_handler.py index cee122a55..7cd441185 100644 --- a/backend/src/update_imms_handler.py +++ b/backend/src/update_imms_handler.py @@ -8,7 +8,7 @@ from controller.fhir_controller import FhirController, make_controller from local_lambda import load_string from log_structure import function_info -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome logging.basicConfig(level="INFO") logger = logging.getLogger() diff --git a/backend/src/utils/dict_utils.py b/backend/src/utils/dict_utils.py index 1bcff54ac..a8e0cf3a3 100644 --- a/backend/src/utils/dict_utils.py +++ b/backend/src/utils/dict_utils.py @@ -1,6 +1,6 @@ """Generic helper module for Python dictionary utility functions""" -from typing import Optional, Any +from typing import Any, Optional def get_field(target_dict: dict, *args: str, default: Optional[Any] = None) -> Any: diff --git a/backend/tests/controller/test_fhir_api_exception_handler.py b/backend/tests/controller/test_fhir_api_exception_handler.py index bcc6d4792..668bec628 100644 --- a/backend/tests/controller/test_fhir_api_exception_handler.py +++ b/backend/tests/controller/test_fhir_api_exception_handler.py @@ -3,7 +3,7 @@ from unittest.mock import patch from controller.fhir_api_exception_handler import fhir_api_exception_handler -from models.errors import UnauthorizedError, UnauthorizedVaxError, ResourceNotFoundError +from models.errors import ResourceNotFoundError, UnauthorizedError, UnauthorizedVaxError class TestFhirApiExceptionHandler(unittest.TestCase): diff --git a/backend/tests/controller/test_fhir_batch_controller.py b/backend/tests/controller/test_fhir_batch_controller.py index b06bc9164..44a230513 100644 --- a/backend/tests/controller/test_fhir_batch_controller.py +++ b/backend/tests/controller/test_fhir_batch_controller.py @@ -4,10 +4,10 @@ from controller.fhir_batch_controller import ImmunizationBatchController from models.errors import ( - ResourceNotFoundError, - UnhandledResponseError, CustomValidationError, IdentifierDuplicationError, + ResourceNotFoundError, + UnhandledResponseError, ) from repository.fhir_batch_repository import ImmunizationBatchRepository from service.fhir_batch_service import ImmunizationBatchService @@ -15,7 +15,6 @@ class TestCreateImmunizationBatchController(unittest.TestCase): - def setUp(self): self.mock_repo = create_autospec(ImmunizationBatchRepository) self.mock_service = create_autospec(ImmunizationBatchService) @@ -132,7 +131,6 @@ def test_send_request_to_dynamo_create_unhandled_error(self): class TestUpdateImmunizationBatchController(unittest.TestCase): - def setUp(self): self.mock_repo = create_autospec(ImmunizationBatchRepository) self.mock_service = create_autospec(ImmunizationBatchService) @@ -248,7 +246,6 @@ def test_send_request_to_dynamo_update_unhandled_error(self): class TestDeleteImmunizationBatchController(unittest.TestCase): - def setUp(self): self.mock_repo = create_autospec(ImmunizationBatchRepository) self.mock_service = create_autospec(ImmunizationBatchService) diff --git a/backend/tests/controller/test_fhir_controller.py b/backend/tests/controller/test_fhir_controller.py index 8c298faa2..8a7d2ddf1 100644 --- a/backend/tests/controller/test_fhir_controller.py +++ b/backend/tests/controller/test_fhir_controller.py @@ -4,22 +4,21 @@ import urllib import urllib.parse import uuid -from unittest.mock import create_autospec, ANY, patch, Mock +from unittest.mock import ANY, Mock, create_autospec, patch from urllib.parse import urlencode -from fhir.resources.R4B.bundle import Bundle -from fhir.resources.R4B.immunization import Immunization - from controller.aws_apig_response_utils import create_response from controller.fhir_controller import FhirController +from fhir.resources.R4B.bundle import Bundle +from fhir.resources.R4B.immunization import Immunization from models.errors import ( - ResourceNotFoundError, - UnhandledResponseError, - InvalidPatientId, CustomValidationError, + IdentifierDuplicationError, + InvalidPatientId, ParameterException, + ResourceNotFoundError, UnauthorizedVaxError, - IdentifierDuplicationError, + UnhandledResponseError, ) from parameter_parser import patient_identifier_system, process_search_params from repository.fhir_repository import ImmunizationRepository diff --git a/backend/tests/models/utils/test_generic_utils.py b/backend/tests/models/utils/test_generic_utils.py index f02d09f41..86c4014dd 100644 --- a/backend/tests/models/utils/test_generic_utils.py +++ b/backend/tests/models/utils/test_generic_utils.py @@ -1,11 +1,10 @@ """Generic utils for tests""" import unittest -from datetime import datetime, date +from datetime import date, datetime from src.models.utils.generic_utils import form_json - -from testing_utils.generic_utils import load_json_data, format_date_types +from testing_utils.generic_utils import format_date_types, load_json_data class TestFormJson(unittest.TestCase): diff --git a/backend/tests/repository/test_fhir_batch_repository.py b/backend/tests/repository/test_fhir_batch_repository.py index ee7ff89f8..3f84ae51b 100644 --- a/backend/tests/repository/test_fhir_batch_repository.py +++ b/backend/tests/repository/test_fhir_batch_repository.py @@ -1,19 +1,18 @@ import os import unittest -from unittest.mock import MagicMock, ANY, patch +from unittest.mock import ANY, MagicMock, patch from uuid import uuid4 import boto3 import botocore.exceptions import simplejson as json -from moto import mock_aws - from models.errors import ( IdentifierDuplicationError, + ResourceFoundError, ResourceNotFoundError, UnhandledResponseError, - ResourceFoundError, ) +from moto import mock_aws from repository.fhir_batch_repository import ImmunizationBatchRepository, create_table from testing_utils.immunization_utils import create_covid_19_immunization_dict @@ -26,7 +25,6 @@ def _make_immunization_pk(_id): @mock_aws class TestImmunizationBatchRepository(unittest.TestCase): - def setUp(self): os.environ["DYNAMODB_TABLE_NAME"] = "test-immunization-table" self.dynamodb = boto3.resource("dynamodb", region_name="eu-west-2") @@ -47,7 +45,6 @@ def tearDown(self): class TestCreateImmunization(TestImmunizationBatchRepository): - def modify_immunization(self, remove_nhs): """Modify the immunization object by removing NHS number if required""" if remove_nhs: @@ -77,7 +74,7 @@ def create_immunization_test_logic(self, is_present, remove_nhs): }, ConditionExpression=ANY, ) - self.assertEqual(item["PK"], f'Immunization#{self.immunization["id"]}') + self.assertEqual(item["PK"], f"Immunization#{self.immunization['id']}") def test_create_immunization_with_nhs_number(self): """Test creating Immunization with NHS number.""" @@ -219,7 +216,7 @@ def test_update_immunization(self): ReturnValues=ANY, ConditionExpression=ANY, ) - self.assertEqual(response, f'Immunization#{self.immunization["id"]}') + self.assertEqual(response, f"Immunization#{self.immunization['id']}") def test_update_immunization_not_found(self): """it should not update Immunization since the imms id not found""" @@ -332,7 +329,7 @@ def test_delete_immunization(self): ReturnValues=ANY, ConditionExpression=ANY, ) - self.assertEqual(response, f'Immunization#{self.immunization ["id"]}') + self.assertEqual(response, f"Immunization#{self.immunization['id']}") def test_delete_immunization_not_found(self): """it should not delete Immunization since the imms id not found""" @@ -417,7 +414,6 @@ def test_delete_immunization_conditionalcheckfailedexception_error(self): @mock_aws @patch.dict(os.environ, {"DYNAMODB_TABLE_NAME": "TestTable"}) class TestCreateTable(TestImmunizationBatchRepository): - def test_create_table_success(self): """Test if create_table returns a DynamoDB Table instance with the correct name""" diff --git a/backend/tests/repository/test_fhir_repository.py b/backend/tests/repository/test_fhir_repository.py index a09341892..7cd39b30e 100644 --- a/backend/tests/repository/test_fhir_repository.py +++ b/backend/tests/repository/test_fhir_repository.py @@ -1,16 +1,15 @@ import time import unittest import uuid -from unittest.mock import MagicMock, patch, ANY +from unittest.mock import ANY, MagicMock, patch import botocore.exceptions import simplejson as json from boto3.dynamodb.conditions import Attr, Key - from models.errors import ( + IdentifierDuplicationError, ResourceNotFoundError, UnhandledResponseError, - IdentifierDuplicationError, ) from models.utils.validation_utils import get_vaccine_type from repository.fhir_repository import ImmunizationRepository diff --git a/backend/tests/service/test_fhir_batch_service.py b/backend/tests/service/test_fhir_batch_service.py index 2f4855280..c1e618e74 100644 --- a/backend/tests/service/test_fhir_batch_service.py +++ b/backend/tests/service/test_fhir_batch_service.py @@ -27,7 +27,6 @@ def tearDown(self): class TestCreateImmunizationBatchService(TestFhirBatchServiceBase): - def setUp(self): super().setUp() self.mock_repo = create_autospec(ImmunizationBatchRepository) @@ -98,7 +97,6 @@ def test_create_immunization_post_validation_error(self): class TestUpdateImmunizationBatchService(TestFhirBatchServiceBase): - def setUp(self): super().setUp() self.mock_repo = create_autospec(ImmunizationBatchRepository) @@ -170,7 +168,6 @@ def test_update_immunization_post_validation_error(self): class TestDeleteImmunizationBatchService(unittest.TestCase): - def setUp(self): self.mock_repo = create_autospec(ImmunizationBatchRepository) self.mock_validator = create_autospec(ImmunizationValidator) diff --git a/backend/tests/service/test_fhir_service.py b/backend/tests/service/test_fhir_service.py index 66ddebf3a..658046163 100644 --- a/backend/tests/service/test_fhir_service.py +++ b/backend/tests/service/test_fhir_service.py @@ -5,33 +5,32 @@ import uuid from copy import deepcopy from decimal import Decimal -from unittest.mock import MagicMock -from unittest.mock import create_autospec, patch - -from fhir.resources.R4B.bundle import Bundle as FhirBundle, BundleEntry -from fhir.resources.R4B.immunization import Immunization -from pydantic import ValidationError -from pydantic.error_wrappers import ErrorWrapper +from unittest.mock import MagicMock, create_autospec, patch from authorisation.api_operation_code import ApiOperationCode from authorisation.authoriser import Authoriser from constants import NHS_NUMBER_USED_IN_SAMPLE_DATA +from fhir.resources.R4B.bundle import Bundle as FhirBundle +from fhir.resources.R4B.bundle import BundleEntry +from fhir.resources.R4B.immunization import Immunization from models.errors import ( - InvalidPatientId, CustomValidationError, - UnauthorizedVaxError, + InvalidPatientId, ResourceNotFoundError, + UnauthorizedVaxError, ) from models.fhir_immunization import ImmunizationValidator from models.utils.generic_utils import get_contained_patient +from pydantic import ValidationError +from pydantic.error_wrappers import ErrorWrapper from repository.fhir_repository import ImmunizationRepository from service.fhir_service import FhirService, UpdateOutcome, get_service_url from testing_utils.generic_utils import load_json_data from testing_utils.immunization_utils import ( + VALID_NHS_NUMBER, create_covid_19_immunization, create_covid_19_immunization_dict, create_covid_19_immunization_dict_no_id, - VALID_NHS_NUMBER, ) @@ -51,7 +50,6 @@ def tearDown(self): class TestServiceUrl(unittest.TestCase): - def setUp(self): self.logger_info_patcher = patch("logging.Logger.info") self.mock_logger_info = self.logger_info_patcher.start() @@ -379,11 +377,14 @@ def test_get_immunization_by_identifier(self): mock_resource = create_covid_19_immunization_dict(identifier) self.authoriser.authorise.return_value = True - self.imms_repo.get_immunization_by_identifier.return_value = { - "resource": mock_resource, - "id": imms_id, - "version": 1, - }, "covid19" + self.imms_repo.get_immunization_by_identifier.return_value = ( + { + "resource": mock_resource, + "id": imms_id, + "version": 1, + }, + "covid19", + ) # When service_resp = self.fhir_service.get_immunization_by_identifier( @@ -409,10 +410,13 @@ def test_get_immunization_by_identifier_raises_error_when_not_authorised(self): identifier = "test" element = "id,mEta,DDD" self.authoriser.authorise.return_value = False - self.imms_repo.get_immunization_by_identifier.return_value = { - "id": "foo", - "version": 1, - }, "covid19" + self.imms_repo.get_immunization_by_identifier.return_value = ( + { + "id": "foo", + "version": 1, + }, + "covid19", + ) with self.assertRaises(UnauthorizedVaxError): # When diff --git a/backend/tests/test_api_errors.py b/backend/tests/test_api_errors.py index e10618998..6474dd35d 100644 --- a/backend/tests/test_api_errors.py +++ b/backend/tests/test_api_errors.py @@ -1,6 +1,6 @@ import unittest -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome "test" diff --git a/backend/tests/test_create_imms.py b/backend/tests/test_create_imms.py index d34a433ba..6f1abc0a9 100644 --- a/backend/tests/test_create_imms.py +++ b/backend/tests/test_create_imms.py @@ -5,7 +5,7 @@ from constants import GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE from controller.fhir_controller import FhirController from create_imms_handler import create_immunization -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome class TestCreateImmunizationById(unittest.TestCase): diff --git a/backend/tests/test_delete_imms.py b/backend/tests/test_delete_imms.py index 34b0c434a..acc646582 100644 --- a/backend/tests/test_delete_imms.py +++ b/backend/tests/test_delete_imms.py @@ -5,7 +5,7 @@ from constants import GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE from controller.fhir_controller import FhirController from delete_imms_handler import delete_immunization -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome class TestDeleteImmunizationById(unittest.TestCase): diff --git a/backend/tests/test_filter.py b/backend/tests/test_filter.py index d2148ddb1..40f6eec25 100644 --- a/backend/tests/test_filter.py +++ b/backend/tests/test_filter.py @@ -7,9 +7,9 @@ from constants import Urls from filter import ( Filter, - remove_reference_to_contained_practitioner, - create_reference_to_patient_resource, add_use_to_identifier, + create_reference_to_patient_resource, + remove_reference_to_contained_practitioner, replace_address_postal_codes, replace_organization_values, ) diff --git a/backend/tests/test_forwarding_batch_lambda.py b/backend/tests/test_forwarding_batch_lambda.py index 3b33b56af..d1bcb294b 100644 --- a/backend/tests/test_forwarding_batch_lambda.py +++ b/backend/tests/test_forwarding_batch_lambda.py @@ -5,32 +5,30 @@ import unittest from typing import Optional from unittest import TestCase -from unittest.mock import patch, MagicMock, ANY +from unittest.mock import ANY, MagicMock, patch from boto3 import resource as boto3_resource -from moto import mock_aws - from models.errors import ( - MessageNotSuccessfulError, - RecordProcessorError, CustomValidationError, IdentifierDuplicationError, - ResourceNotFoundError, + MessageNotSuccessfulError, + RecordProcessorError, ResourceFoundError, + ResourceNotFoundError, ) +from moto import mock_aws from testing_utils.test_utils_for_batch import ForwarderValues, MockFhirImmsResources with patch.dict("os.environ", ForwarderValues.MOCK_ENVIRONMENT_DICT): from forwarding_batch_lambda import ( - forward_lambda_handler, create_diagnostics_dictionary, + forward_lambda_handler, ) @mock_aws @patch.dict(os.environ, ForwarderValues.MOCK_ENVIRONMENT_DICT) class TestForwardLambdaHandler(TestCase): - def setUp(self): """Set up dynamodb table test values to be used for the tests""" self.dynamodb_resource = boto3_resource("dynamodb", "eu-west-2") diff --git a/backend/tests/test_immunization_post_validator.py b/backend/tests/test_immunization_post_validator.py index f04e1226e..fea868789 100644 --- a/backend/tests/test_immunization_post_validator.py +++ b/backend/tests/test_immunization_post_validator.py @@ -5,15 +5,16 @@ from unittest.mock import patch from jsonpath_ng.ext import parse -from pydantic import ValidationError - from models.fhir_immunization import ImmunizationValidator +from pydantic import ValidationError +from testing_utils.generic_utils import ( + load_json_data, + update_contained_resource_field, +) from testing_utils.generic_utils import ( # these have an underscore to avoid pytest collecting them as tests test_invalid_values_rejected as _test_invalid_values_rejected, - load_json_data, ) -from testing_utils.generic_utils import update_contained_resource_field from testing_utils.mandation_test_utils import MandationTests from testing_utils.values_for_tests import NameInstances @@ -570,9 +571,9 @@ def test_post_pre_validate_extension_url(self): self.mock_redis_client.hget.side_effect = None self.mock_redis_client.hget.return_value = "COVID19" invalid_json_data = deepcopy(self.completed_json_data["COVID19"]) - invalid_json_data["extension"][0]["valueCodeableConcept"]["coding"][0][ - "system" - ] = "https://xyz/Extension-UKCore-VaccinationProcedure" + invalid_json_data["extension"][0]["valueCodeableConcept"]["coding"][0]["system"] = ( + "https://xyz/Extension-UKCore-VaccinationProcedure" + ) with self.assertRaises(Exception) as error: self.validator.validate(invalid_json_data) diff --git a/backend/tests/test_immunization_pre_validator.py b/backend/tests/test_immunization_pre_validator.py index a259106c4..1bafd2994 100644 --- a/backend/tests/test_immunization_pre_validator.py +++ b/backend/tests/test_immunization_pre_validator.py @@ -6,24 +6,27 @@ from unittest.mock import patch from jsonpath_ng.ext import parse - from models.fhir_immunization import ImmunizationValidator from models.fhir_immunization_pre_validators import PreValidators -from models.utils.generic_utils import get_generic_extension_value from models.utils.generic_utils import ( - patient_name_given_field_location, + get_generic_extension_value, patient_name_family_field_location, - practitioner_name_given_field_location, + patient_name_given_field_location, practitioner_name_family_field_location, + practitioner_name_given_field_location, +) +from testing_utils.generic_utils import ( + load_json_data, +) +from testing_utils.generic_utils import ( + test_invalid_values_rejected as _test_invalid_values_rejected, ) from testing_utils.generic_utils import ( # these have an underscore to avoid pytest collecting them as tests test_valid_values_accepted as _test_valid_values_accepted, - test_invalid_values_rejected as _test_invalid_values_rejected, - load_json_data, ) from testing_utils.pre_validation_test_utils import ValidatorModelTests -from testing_utils.values_for_tests import ValidValues, InvalidValues +from testing_utils.values_for_tests import InvalidValues, ValidValues class TestImmunizationModelPreValidationRules(unittest.TestCase): diff --git a/backend/tests/test_lambda_handler.py b/backend/tests/test_lambda_handler.py index 9ea8bc62d..9cc39317e 100644 --- a/backend/tests/test_lambda_handler.py +++ b/backend/tests/test_lambda_handler.py @@ -19,5 +19,4 @@ def test_unsupported_method(self): if __name__ == "__main__": - unittest.main() diff --git a/backend/tests/test_log_structure_wrapper.py b/backend/tests/test_log_structure_wrapper.py index 5b0838563..f0e4afd66 100644 --- a/backend/tests/test_log_structure_wrapper.py +++ b/backend/tests/test_log_structure_wrapper.py @@ -8,7 +8,6 @@ @patch("log_structure.firehose_logger") @patch("log_structure.logger") class TestFunctionInfoWrapper(unittest.TestCase): - def setUp(self): self.redis_patcher = patch("models.utils.validation_utils.redis_client") self.mock_redis_client = self.redis_patcher.start() diff --git a/backend/tests/test_parameter_parser.py b/backend/tests/test_parameter_parser.py index 8b062f147..0d68af685 100644 --- a/backend/tests/test_parameter_parser.py +++ b/backend/tests/test_parameter_parser.py @@ -5,13 +5,13 @@ from models.errors import ParameterException from parameter_parser import ( + SearchParams, + create_query_string, date_from_key, date_to_key, + include_key, process_params, process_search_params, - create_query_string, - include_key, - SearchParams, ) from service.fhir_service import FhirService diff --git a/backend/tests/test_search_imms.py b/backend/tests/test_search_imms.py index 0041719c3..1ef035c87 100644 --- a/backend/tests/test_search_imms.py +++ b/backend/tests/test_search_imms.py @@ -5,7 +5,7 @@ from constants import GENERIC_SERVER_ERROR_DIAGNOSTICS_MESSAGE from controller.fhir_controller import FhirController -from models.errors import Severity, Code, create_operation_outcome +from models.errors import Code, Severity, create_operation_outcome from search_imms_handler import search_imms script_location = Path(__file__).absolute().parent diff --git a/backend/tests/test_validation_utils.py b/backend/tests/test_validation_utils.py index c5914b2a1..d8e3c730e 100644 --- a/backend/tests/test_validation_utils.py +++ b/backend/tests/test_validation_utils.py @@ -2,19 +2,18 @@ from copy import deepcopy from jsonpath_ng.ext import parse - from models.fhir_immunization import ImmunizationValidator from models.obtain_field_value import ObtainFieldValue from models.utils.generic_utils import ( get_current_name_instance, obtain_current_name_period, - patient_and_practitioner_value_and_index, obtain_name_field_location, + patient_and_practitioner_value_and_index, ) from testing_utils.generic_utils import ( load_json_data, ) -from testing_utils.values_for_tests import ValidValues, InvalidValues, NameInstances +from testing_utils.values_for_tests import InvalidValues, NameInstances, ValidValues class TestValidatorUtils(unittest.TestCase): diff --git a/backend/tests/testing_utils/generic_utils.py b/backend/tests/testing_utils/generic_utils.py index e8aff0ea4..4f00e36ec 100644 --- a/backend/tests/testing_utils/generic_utils.py +++ b/backend/tests/testing_utils/generic_utils.py @@ -3,10 +3,9 @@ import json import os import unittest -from datetime import datetime, date +from datetime import date, datetime from decimal import Decimal -from typing import Literal, Any -from typing import Union, List +from typing import Any, List, Literal, Union from jsonpath_ng.ext import parse diff --git a/backend/tests/testing_utils/immunization_utils.py b/backend/tests/testing_utils/immunization_utils.py index f25f69a22..cd69b1ba8 100644 --- a/backend/tests/testing_utils/immunization_utils.py +++ b/backend/tests/testing_utils/immunization_utils.py @@ -1,7 +1,6 @@ """Immunization utils.""" from fhir.resources.R4B.immunization import Immunization - from testing_utils.generic_utils import load_json_data from testing_utils.values_for_tests import ValidValues @@ -21,9 +20,9 @@ def create_covid_19_immunization_dict( immunization_json = load_json_data("completed_covid19_immunization_event.json") immunization_json["id"] = imms_id - [x for x in immunization_json["contained"] if x.get("resourceType") == "Patient"][0]["identifier"][0][ - "value" - ] = nhs_number + [x for x in immunization_json["contained"] if x.get("resourceType") == "Patient"][0]["identifier"][0]["value"] = ( + nhs_number + ) immunization_json["occurrenceDateTime"] = occurrence_date_time @@ -35,9 +34,9 @@ def create_covid_19_immunization_dict_no_id( ): immunization_json = load_json_data("completed_covid19_immunization_event.json") - [x for x in immunization_json["contained"] if x.get("resourceType") == "Patient"][0]["identifier"][0][ - "value" - ] = nhs_number + [x for x in immunization_json["contained"] if x.get("resourceType") == "Patient"][0]["identifier"][0]["value"] = ( + nhs_number + ) immunization_json["occurrenceDateTime"] = occurrence_date_time diff --git a/backend/tests/testing_utils/pre_validation_test_utils.py b/backend/tests/testing_utils/pre_validation_test_utils.py index 9f8d5f36b..2abd1c0ac 100644 --- a/backend/tests/testing_utils/pre_validation_test_utils.py +++ b/backend/tests/testing_utils/pre_validation_test_utils.py @@ -6,8 +6,8 @@ from jsonpath_ng.ext import parse from .generic_utils import ( - test_valid_values_accepted, test_invalid_values_rejected, + test_valid_values_accepted, ) from .values_for_tests import InvalidDataTypes, InvalidValues, ValidValues diff --git a/backend/tests/testing_utils/test_utils_for_batch.py b/backend/tests/testing_utils/test_utils_for_batch.py index ce7ee25ef..ce5c57955 100644 --- a/backend/tests/testing_utils/test_utils_for_batch.py +++ b/backend/tests/testing_utils/test_utils_for_batch.py @@ -2,7 +2,6 @@ class ForwarderValues: - MOCK_ENVIRONMENT_DICT = { "DYNAMODB_TABLE_NAME": "immunisation-batch-internal-dev-imms-test-table", "ENVIRONMENT": "internal-dev-test", diff --git a/backend/tests/utils/test_dict_utils.py b/backend/tests/utils/test_dict_utils.py index 718fac210..161c632c4 100644 --- a/backend/tests/utils/test_dict_utils.py +++ b/backend/tests/utils/test_dict_utils.py @@ -4,7 +4,6 @@ class TestDictUtils(unittest.TestCase): - def test_get_field_returns_none_if_value_is_not_dict(self): """Test that the default None value is returned if the provided argument is not a dict""" result = dict_utils.get_field(["test"], "test_key") diff --git a/batch_processor_filter/src/batch_audit_repository.py b/batch_processor_filter/src/batch_audit_repository.py index 4f0f3ef4a..f3e15e751 100644 --- a/batch_processor_filter/src/batch_audit_repository.py +++ b/batch_processor_filter/src/batch_audit_repository.py @@ -1,13 +1,12 @@ import boto3 from boto3.dynamodb.conditions import Key - from constants import ( + AUDIT_TABLE_FILENAME_GSI, AUDIT_TABLE_NAME, + AUDIT_TABLE_QUEUE_NAME_GSI, REGION_NAME, - AUDIT_TABLE_FILENAME_GSI, AuditTableKeys, FileStatus, - AUDIT_TABLE_QUEUE_NAME_GSI, ) diff --git a/batch_processor_filter/src/batch_file_repository.py b/batch_processor_filter/src/batch_file_repository.py index 239016e10..e30746cbb 100644 --- a/batch_processor_filter/src/batch_file_repository.py +++ b/batch_processor_filter/src/batch_file_repository.py @@ -1,12 +1,11 @@ """Module for the batch file repository""" from csv import writer -from io import StringIO, BytesIO +from io import BytesIO, StringIO import boto3 - from batch_file_created_event import BatchFileCreatedEvent -from constants import SOURCE_BUCKET_NAME, ACK_BUCKET_NAME +from constants import ACK_BUCKET_NAME, SOURCE_BUCKET_NAME class BatchFileRepository: diff --git a/batch_processor_filter/src/batch_processor_filter_service.py b/batch_processor_filter/src/batch_processor_filter_service.py index 7f4bcfe0b..988e652b1 100644 --- a/batch_processor_filter/src/batch_processor_filter_service.py +++ b/batch_processor_filter/src/batch_processor_filter_service.py @@ -1,14 +1,12 @@ """Batch processor filter service module""" -import boto3 import json +import boto3 from batch_audit_repository import BatchAuditRepository - from batch_file_created_event import BatchFileCreatedEvent from batch_file_repository import BatchFileRepository - -from constants import REGION_NAME, FileStatus, QUEUE_URL, FileNotProcessedReason +from constants import QUEUE_URL, REGION_NAME, FileNotProcessedReason, FileStatus from exceptions import EventAlreadyProcessingForSupplierAndVaccTypeError from logger import logger from send_log_to_firehose import send_log_to_firehose diff --git a/batch_processor_filter/src/lambda_handler.py b/batch_processor_filter/src/lambda_handler.py index b55a875d7..0ba0ca202 100644 --- a/batch_processor_filter/src/lambda_handler.py +++ b/batch_processor_filter/src/lambda_handler.py @@ -1,12 +1,11 @@ import json -from aws_lambda_typing import events, context +from aws_lambda_typing import context, events from batch_file_created_event import BatchFileCreatedEvent from batch_processor_filter_service import BatchProcessorFilterService from exception_decorator import exception_decorator from exceptions import InvalidBatchSizeError - service = BatchProcessorFilterService() diff --git a/batch_processor_filter/src/logger.py b/batch_processor_filter/src/logger.py index c6e5a24c4..47e9168b3 100644 --- a/batch_processor_filter/src/logger.py +++ b/batch_processor_filter/src/logger.py @@ -2,7 +2,6 @@ import logging - logging.basicConfig(level="INFO") logger = logging.getLogger() logger.setLevel("INFO") diff --git a/batch_processor_filter/src/send_log_to_firehose.py b/batch_processor_filter/src/send_log_to_firehose.py index a89e181cc..be04327b7 100644 --- a/batch_processor_filter/src/send_log_to_firehose.py +++ b/batch_processor_filter/src/send_log_to_firehose.py @@ -1,7 +1,7 @@ import json -import boto3 -from constants import SPLUNK_FIREHOSE_STREAM_NAME, REGION_NAME +import boto3 +from constants import REGION_NAME, SPLUNK_FIREHOSE_STREAM_NAME firehose_client = boto3.client("firehose", region_name=REGION_NAME) diff --git a/batch_processor_filter/tests/test_lambda_handler.py b/batch_processor_filter/tests/test_lambda_handler.py index 16d0c758d..69a35b90b 100644 --- a/batch_processor_filter/tests/test_lambda_handler.py +++ b/batch_processor_filter/tests/test_lambda_handler.py @@ -1,36 +1,34 @@ +import copy import json from json import JSONDecodeError - -import boto3 -import copy from unittest import TestCase -from unittest.mock import patch, Mock, ANY, call +from unittest.mock import ANY, Mock, call, patch +import boto3 import botocore -from moto import mock_aws - from batch_file_created_event import BatchFileCreatedEvent from exceptions import ( - InvalidBatchSizeError, EventAlreadyProcessingForSupplierAndVaccTypeError, + InvalidBatchSizeError, ) +from moto import mock_aws from testing_utils import ( MOCK_ENVIRONMENT_DICT, - make_sqs_record, add_entry_to_mock_table, get_audit_entry_status_by_id, + make_sqs_record, ) with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from lambda_handler import lambda_handler from constants import ( + AUDIT_TABLE_FILENAME_GSI, AUDIT_TABLE_NAME, + AUDIT_TABLE_QUEUE_NAME_GSI, REGION_NAME, AuditTableKeys, - AUDIT_TABLE_FILENAME_GSI, - AUDIT_TABLE_QUEUE_NAME_GSI, FileStatus, ) + from lambda_handler import lambda_handler sqs_client = boto3.client("sqs", region_name=REGION_NAME) dynamodb_client = boto3.client("dynamodb", region_name=REGION_NAME) @@ -123,7 +121,7 @@ def _assert_source_file_moved(self, filename: str): self.assertEqual( str(exc.exception), - "An error occurred (NoSuchKey) when calling the GetObject " "operation: The specified key does not exist.", + "An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist.", ) archived_object = s3_client.get_object(Bucket=self.mock_source_bucket, Key=f"archive/{filename}") self.assertIsNotNone(archived_object) @@ -287,7 +285,7 @@ def test_lambda_handler_processes_event_successfully(self): ) expected_success_log_message = ( - f"File forwarded for processing by ECS. Filename: " f"{self.default_batch_file_event['filename']}" + f"File forwarded for processing by ECS. Filename: {self.default_batch_file_event['filename']}" ) self.mock_logger.info.assert_has_calls( [ diff --git a/batch_processor_filter/tests/testing_utils.py b/batch_processor_filter/tests/testing_utils.py index 604a9c973..bae2a8201 100644 --- a/batch_processor_filter/tests/testing_utils.py +++ b/batch_processor_filter/tests/testing_utils.py @@ -3,7 +3,6 @@ from aws_lambda_typing.events.sqs import SQSMessage from batch_file_created_event import BatchFileCreatedEvent - MOCK_ENVIRONMENT_DICT = { "AUDIT_TABLE_NAME": "immunisation-batch-internal-dev-audit-table", "QUEUE_URL": "https://sqs.eu-west-2.amazonaws.com/123456789012/imms-batch-metadata-queue.fifo", @@ -32,7 +31,7 @@ def add_entry_to_mock_table( """Add an entry to the audit table""" audit_table_entry = { "message_id": {"S": batch_file_created_event.get("message_id")}, - "queue_name": {"S": f'{batch_file_created_event["supplier"]}_{batch_file_created_event["vaccine_type"]}'}, + "queue_name": {"S": f"{batch_file_created_event['supplier']}_{batch_file_created_event['vaccine_type']}"}, "filename": {"S": batch_file_created_event.get("filename")}, "status": {"S": status}, } diff --git a/delta_backend/src/converter.py b/delta_backend/src/converter.py index 80c0510e3..830f8571d 100644 --- a/delta_backend/src/converter.py +++ b/delta_backend/src/converter.py @@ -1,12 +1,11 @@ # Main validation engine import exception_messages from common.mappings import ActionFlag -from conversion_layout import ConversionLayout, ConversionField +from conversion_layout import ConversionField, ConversionLayout from extractor import Extractor class Converter: - def __init__(self, fhir_data, action_flag=ActionFlag.UPDATE, report_unexpected_exception=True): self.converted = {} self.error_records = [] diff --git a/delta_backend/src/delta.py b/delta_backend/src/delta.py index 155772363..4c2eebddf 100644 --- a/delta_backend/src/delta.py +++ b/delta_backend/src/delta.py @@ -3,13 +3,12 @@ import logging import os import time -from datetime import datetime, timedelta, UTC +from datetime import UTC, datetime, timedelta import boto3 from boto3.dynamodb.conditions import Attr from botocore.exceptions import ClientError - -from common.mappings import ActionFlag, Operation, EventName +from common.mappings import ActionFlag, EventName, Operation from converter import Converter from log_firehose import FirehoseLogger diff --git a/delta_backend/src/extractor.py b/delta_backend/src/extractor.py index 02d6e5404..8c40bbf6d 100644 --- a/delta_backend/src/extractor.py +++ b/delta_backend/src/extractor.py @@ -3,11 +3,10 @@ from datetime import datetime, timedelta, timezone import exception_messages -from common.mappings import Gender, ConversionFieldName +from common.mappings import ConversionFieldName, Gender class Extractor: - # This file holds the schema/base layout that maps FHIR fields to flat JSON fields # Each entry tells the converter how to extract and transform a specific value EXTENSION_URL_VACCINATION_PRODEDURE = ( @@ -40,7 +39,6 @@ def _get_patient(self): ) def _get_valid_names(self, names, occurrence_time): - official_names = [n for n in names if n.get("use") == "official" and self._is_current_period(n, occurrence_time)] if official_names: return official_names[0] diff --git a/delta_backend/src/log_firehose.py b/delta_backend/src/log_firehose.py index c5c8134f4..66d2000e6 100644 --- a/delta_backend/src/log_firehose.py +++ b/delta_backend/src/log_firehose.py @@ -2,7 +2,6 @@ import logging import os - import boto3 from botocore.config import Config diff --git a/delta_backend/tests/check_conversion.py b/delta_backend/tests/check_conversion.py index ff4918a7e..698a9c30b 100644 --- a/delta_backend/tests/check_conversion.py +++ b/delta_backend/tests/check_conversion.py @@ -2,8 +2,8 @@ import json import os import sys -from converter import Converter +from converter import Converter sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src"))) diff --git a/delta_backend/tests/test_convert.py b/delta_backend/tests/test_convert.py index 08c05d7f6..6eaaca3cb 100644 --- a/delta_backend/tests/test_convert.py +++ b/delta_backend/tests/test_convert.py @@ -4,10 +4,11 @@ from copy import deepcopy from datetime import datetime from unittest.mock import patch -from moto import mock_aws + from boto3 import resource as boto3_resource -from utils_for_converter_tests import ValuesForTests, ErrorValuesForTests -from common.mappings import ActionFlag, Operation, EventName +from common.mappings import ActionFlag, EventName, Operation +from moto import mock_aws +from utils_for_converter_tests import ErrorValuesForTests, ValuesForTests MOCK_ENV_VARS = { "AWS_SQS_QUEUE_URL": "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue", @@ -17,7 +18,7 @@ } request_json_data = ValuesForTests.json_data with patch.dict("os.environ", MOCK_ENV_VARS): - from delta import handler, Converter + from delta import Converter, handler @patch.dict("os.environ", MOCK_ENV_VARS, clear=True) @@ -214,7 +215,6 @@ def test_handler_imms_convert_to_flat_json(self): for test_case in expected_action_flags: with self.subTest(test_case["Operation"]): - event = self.get_event(operation=test_case["Operation"]) response = handler(event, None) diff --git a/delta_backend/tests/test_convert_dates.py b/delta_backend/tests/test_convert_dates.py index 15104f3ea..c3e859761 100644 --- a/delta_backend/tests/test_convert_dates.py +++ b/delta_backend/tests/test_convert_dates.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestDateConversions(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_dose_amount.py b/delta_backend/tests/test_convert_dose_amount.py index e359c55c9..b3a04c18b 100644 --- a/delta_backend/tests/test_convert_dose_amount.py +++ b/delta_backend/tests/test_convert_dose_amount.py @@ -2,13 +2,13 @@ import decimal import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestDoseAmountTypeUriToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_dose_sequence.py b/delta_backend/tests/test_convert_dose_sequence.py index 99e1bc54d..c06535ba3 100644 --- a/delta_backend/tests/test_convert_dose_sequence.py +++ b/delta_backend/tests/test_convert_dose_sequence.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestDoseSequenceToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_location_code.py b/delta_backend/tests/test_convert_location_code.py index 0dab0ed83..378cb7438 100644 --- a/delta_backend/tests/test_convert_location_code.py +++ b/delta_backend/tests/test_convert_location_code.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestLocationCode(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_location_code_type_uri.py b/delta_backend/tests/test_convert_location_code_type_uri.py index 718697109..0e03c49f3 100644 --- a/delta_backend/tests/test_convert_location_code_type_uri.py +++ b/delta_backend/tests/test_convert_location_code_type_uri.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestLocationCodeTypeUri(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_lot_number.py b/delta_backend/tests/test_convert_lot_number.py index 95ac7d6e4..c2a0bdbd5 100644 --- a/delta_backend/tests/test_convert_lot_number.py +++ b/delta_backend/tests/test_convert_lot_number.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestBatchNumber(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_manufacturer.py b/delta_backend/tests/test_convert_manufacturer.py index 5089abbd4..f97a50a6d 100644 --- a/delta_backend/tests/test_convert_manufacturer.py +++ b/delta_backend/tests/test_convert_manufacturer.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestVaccineManufacturer(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_nhs_number.py b/delta_backend/tests/test_convert_nhs_number.py index 57fb29198..9681d99b5 100644 --- a/delta_backend/tests/test_convert_nhs_number.py +++ b/delta_backend/tests/test_convert_nhs_number.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestNHSNumberToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_person_forename.py b/delta_backend/tests/test_convert_person_forename.py index e813eba8b..b42b844e1 100644 --- a/delta_backend/tests/test_convert_person_forename.py +++ b/delta_backend/tests/test_convert_person_forename.py @@ -1,9 +1,10 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPersonForenmeToFlatJson(unittest.TestCase): diff --git a/delta_backend/tests/test_convert_person_gender.py b/delta_backend/tests/test_convert_person_gender.py index 064c1e7b9..548ead88f 100644 --- a/delta_backend/tests/test_convert_person_gender.py +++ b/delta_backend/tests/test_convert_person_gender.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPersonGenderToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_person_surname.py b/delta_backend/tests/test_convert_person_surname.py index 8d1331abe..a485d2266 100644 --- a/delta_backend/tests/test_convert_person_surname.py +++ b/delta_backend/tests/test_convert_person_surname.py @@ -1,9 +1,10 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPersonSurnameToFlatJson(unittest.TestCase): diff --git a/delta_backend/tests/test_convert_post_code.py b/delta_backend/tests/test_convert_post_code.py index a07dc6d63..e8958b8c1 100644 --- a/delta_backend/tests/test_convert_post_code.py +++ b/delta_backend/tests/test_convert_post_code.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPersonPostalCodeToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_practitioner_forename.py b/delta_backend/tests/test_convert_practitioner_forename.py index 38edc88b9..e5a7aba90 100644 --- a/delta_backend/tests/test_convert_practitioner_forename.py +++ b/delta_backend/tests/test_convert_practitioner_forename.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPractitionerForenameToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_practitioner_surname.py b/delta_backend/tests/test_convert_practitioner_surname.py index b8bf1919b..d7e820aa9 100644 --- a/delta_backend/tests/test_convert_practitioner_surname.py +++ b/delta_backend/tests/test_convert_practitioner_surname.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPractitionerSurnameToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_primary_source.py b/delta_backend/tests/test_convert_primary_source.py index e5b94b261..f52e70953 100644 --- a/delta_backend/tests/test_convert_primary_source.py +++ b/delta_backend/tests/test_convert_primary_source.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestPrimarySourceFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_site_code.py b/delta_backend/tests/test_convert_site_code.py index 5eab55b0b..68dd1b2dc 100644 --- a/delta_backend/tests/test_convert_site_code.py +++ b/delta_backend/tests/test_convert_site_code.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestSiteCodeToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_site_uri.py b/delta_backend/tests/test_convert_site_uri.py index 6d29b25e3..d5ddbff8e 100644 --- a/delta_backend/tests/test_convert_site_uri.py +++ b/delta_backend/tests/test_convert_site_uri.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestSiteUriToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_snomed_codes.py b/delta_backend/tests/test_convert_snomed_codes.py index 593eb08b4..367a9f189 100644 --- a/delta_backend/tests/test_convert_snomed_codes.py +++ b/delta_backend/tests/test_convert_snomed_codes.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestSNOMEDToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_snomed_terms.py b/delta_backend/tests/test_convert_snomed_terms.py index 057e983f0..4d4882ac0 100644 --- a/delta_backend/tests/test_convert_snomed_terms.py +++ b/delta_backend/tests/test_convert_snomed_terms.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestSNOMEDTermsToFlatJson(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_unique_id.py b/delta_backend/tests/test_convert_unique_id.py index 277118108..e7a7be93f 100644 --- a/delta_backend/tests/test_convert_unique_id.py +++ b/delta_backend/tests/test_convert_unique_id.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestUniqueId(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_convert_unique_id_uri.py b/delta_backend/tests/test_convert_unique_id_uri.py index 379087f2f..ae5447811 100644 --- a/delta_backend/tests/test_convert_unique_id_uri.py +++ b/delta_backend/tests/test_convert_unique_id_uri.py @@ -1,13 +1,13 @@ import copy import json import unittest -from utils_for_converter_tests import ValuesForTests -from converter import Converter + from common.mappings import ConversionFieldName +from converter import Converter +from utils_for_converter_tests import ValuesForTests class TestUniqueIdUri(unittest.TestCase): - def setUp(self): self.request_json_data = copy.deepcopy(ValuesForTests.json_data) diff --git a/delta_backend/tests/test_current_period.py b/delta_backend/tests/test_current_period.py index f4b75ec57..c8dd60bc7 100644 --- a/delta_backend/tests/test_current_period.py +++ b/delta_backend/tests/test_current_period.py @@ -1,5 +1,6 @@ import unittest from datetime import datetime, timezone + from extractor import Extractor diff --git a/delta_backend/tests/test_delta.py b/delta_backend/tests/test_delta.py index 7add6fe1b..7df127c7f 100644 --- a/delta_backend/tests/test_delta.py +++ b/delta_backend/tests/test_delta.py @@ -1,17 +1,18 @@ -import unittest -from unittest.mock import patch, MagicMock -from botocore.exceptions import ClientError -import os -import json import decimal -from common.mappings import EventName, Operation, ActionFlag -from utils_for_converter_tests import ValuesForTests, RecordConfig +import json +import os +import unittest +from unittest.mock import MagicMock, patch + import delta +from botocore.exceptions import ClientError +from common.mappings import ActionFlag, EventName, Operation from delta import ( - send_message, handler, process_record, + send_message, ) +from utils_for_converter_tests import RecordConfig, ValuesForTests TEST_QUEUE_URL = "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue" os.environ["AWS_SQS_QUEUE_URL"] = TEST_QUEUE_URL @@ -26,7 +27,6 @@ class DeltaHandlerTestCase(unittest.TestCase): - # TODO refactor for dependency injection, eg process_record, send_firehose etc def setUp(self): self.logger_info_patcher = patch("logging.Logger.info") @@ -501,7 +501,6 @@ def test_handler_sends_all_to_firehose(self, mock_send_firehose, mock_process_re class DeltaRecordProcessorTestCase(unittest.TestCase): - def setUp(self): self.logger_info_patcher = patch("logging.Logger.info") self.mock_logger_info = self.logger_info_patcher.start() @@ -525,7 +524,6 @@ def tearDown(self): self.delta_table_patcher.stop() def test_multi_record_success(self): - # Arrange self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE test_configs = [ @@ -557,7 +555,6 @@ def test_multi_record_success(self): self.assertEqual(self.mock_logger_warning.call_count, 0) def test_multi_record_success_with_fail(self): - # Arrange expected_returns = [True, False, True] self.mock_delta_table.put_item.side_effect = [ @@ -589,7 +586,6 @@ def test_multi_record_success_with_fail(self): self.assertEqual(self.mock_logger_error.call_count, 1) def test_single_record_table_exception(self): - # Arrange imms_id = "exception-id" record = ValuesForTests.get_event_record( @@ -613,7 +609,6 @@ def test_single_record_table_exception(self): @patch("delta.json.loads") def test_json_loads_called_with_parse_float_decimal(self, mock_json_loads): - # Arrange record = ValuesForTests.get_event_record(imms_id="id", event_name=EventName.UPDATE, operation=Operation.UPDATE) @@ -640,7 +635,6 @@ def tearDown(self): self.logger_error_patcher.stop() def test_returns_table_on_success(self): - table = delta.get_delta_table() self.assertIs(table, self.mock_delta_table) # Should cache the table diff --git a/delta_backend/tests/test_log_firehose.py b/delta_backend/tests/test_log_firehose.py index 6df02bf87..6e90f3436 100644 --- a/delta_backend/tests/test_log_firehose.py +++ b/delta_backend/tests/test_log_firehose.py @@ -1,11 +1,11 @@ -import unittest -from unittest.mock import patch, MagicMock import json +import unittest +from unittest.mock import MagicMock, patch + from log_firehose import FirehoseLogger class TestFirehoseLogger(unittest.TestCase): - def setUp(self): # Common setup if needed self.context = {} diff --git a/delta_backend/tests/test_utils.py b/delta_backend/tests/test_utils.py index 0fcacb61a..a0a2f483e 100644 --- a/delta_backend/tests/test_utils.py +++ b/delta_backend/tests/test_utils.py @@ -1,9 +1,9 @@ import unittest + from utils import is_valid_simple_snomed class TestIsValidSimpleSnomed(unittest.TestCase): - def test_valid_snomed(self): valid_snomed = "956951000000104" self.assertTrue(is_valid_simple_snomed(valid_snomed)) diff --git a/delta_backend/tests/utils_for_converter_tests.py b/delta_backend/tests/utils_for_converter_tests.py index 6919650be..d956d6a6e 100644 --- a/delta_backend/tests/utils_for_converter_tests.py +++ b/delta_backend/tests/utils_for_converter_tests.py @@ -1,9 +1,10 @@ +import json import uuid from decimal import Decimal -import json -from common.mappings import EventName, Operation from typing import List +from common.mappings import EventName, Operation + class RecordConfig: def __init__(self, event_name, operation, imms_id, expected_action_flag=None, supplier="EMIS"): @@ -15,7 +16,6 @@ def __init__(self, event_name, operation, imms_id, expected_action_flag=None, su class ValuesForTests: - MOCK_ENVIRONMENT_DICT = { "DYNAMODB_TABLE_NAME": "immunisation-batch-internal-dev-imms-test-table", "ENVIRONMENT": "internal-dev-test", @@ -346,7 +346,6 @@ def get_expected_imms(expected_action_flag): class ErrorValuesForTests: - json_dob_error = { "resourceType": "Immunization", "contained": [ diff --git a/e2e/lib/apigee.py b/e2e/lib/apigee.py index ba3f757cd..750b55701 100644 --- a/e2e/lib/apigee.py +++ b/e2e/lib/apigee.py @@ -1,5 +1,5 @@ import inspect -from dataclasses import dataclass, field, asdict +from dataclasses import asdict, dataclass, field from enum import StrEnum from typing import List diff --git a/e2e/lib/authentication.py b/e2e/lib/authentication.py index 9400ebcab..c79024e73 100644 --- a/e2e/lib/authentication.py +++ b/e2e/lib/authentication.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from enum import Enum from time import time -from urllib.parse import urlparse, parse_qs +from urllib.parse import parse_qs, urlparse import jwt import requests diff --git a/e2e/lib/env.py b/e2e/lib/env.py index d9df56146..14f10c818 100644 --- a/e2e/lib/env.py +++ b/e2e/lib/env.py @@ -23,8 +23,7 @@ def get_apigee_env() -> ApigeeEnv: logging.error(f'the environment variable "APIGEE_ENVIRONMENT: {env}" is invalid') else: logging.warning( - 'the environment variable "APIGEE_ENVIRONMENT" is empty, ' - 'falling back to the default value: "internal-dev"' + 'the environment variable "APIGEE_ENVIRONMENT" is empty, falling back to the default value: "internal-dev"' ) return ApigeeEnv.INTERNAL_DEV diff --git a/e2e/test_authorization.py b/e2e/test_authorization.py index 1b112568f..4ad8192c9 100644 --- a/e2e/test_authorization.py +++ b/e2e/test_authorization.py @@ -11,7 +11,7 @@ from lib.env import get_auth_url, get_proxy_name, get_service_base_path from utils.authorization import Permission, app_full_access from utils.base_test import ImmunizationBaseTest -from utils.constants import valid_nhs_number1, cis2_user +from utils.constants import cis2_user, valid_nhs_number1 from utils.factories import make_app_restricted_app, make_cis2_app from utils.immunisation_api import ImmunisationApi from utils.mappings import VaccineTypes @@ -20,7 +20,6 @@ @unittest.skip("Skipping this entire test suite for now") class TestApplicationRestrictedAuthorization(ImmunizationBaseTest): - my_app: ApigeeApp my_imms_api: ImmunisationApi diff --git a/e2e/test_create_immunization.py b/e2e/test_create_immunization.py index 10d592b4f..dd2cc6cf8 100644 --- a/e2e/test_create_immunization.py +++ b/e2e/test_create_immunization.py @@ -3,7 +3,6 @@ class TestCreateImmunization(ImmunizationBaseTest): - def test_create_imms(self): """it should create a FHIR Immunization resource""" for imms_api in self.imms_apis: diff --git a/e2e/test_delete_immunization.py b/e2e/test_delete_immunization.py index ffcd79106..18ba5e369 100644 --- a/e2e/test_delete_immunization.py +++ b/e2e/test_delete_immunization.py @@ -4,7 +4,6 @@ class TestDeleteImmunization(ImmunizationBaseTest): - def test_delete_imms(self): """it should delete a FHIR Immunization resource""" for imms_api in self.imms_apis: diff --git a/e2e/test_delta_immunization.py b/e2e/test_delta_immunization.py index 87689a3a1..89f63bb86 100644 --- a/e2e/test_delta_immunization.py +++ b/e2e/test_delta_immunization.py @@ -9,7 +9,6 @@ class TestDeltaImmunization(ImmunizationBaseTest): - CREATE_OPERATION = "CREATE" UPDATE_OPERATION = "UPDATE" DELETE_OPERATION = "DELETE" diff --git a/e2e/test_deployment.py b/e2e/test_deployment.py index 88b03c469..3a3c759c4 100644 --- a/e2e/test_deployment.py +++ b/e2e/test_deployment.py @@ -2,11 +2,10 @@ from time import sleep import requests - from lib.env import ( get_service_base_path, - get_status_endpoint_api_key, get_source_commit_id, + get_status_endpoint_api_key, ) """Tests in this package don't really test anything. Platform created these tests to check if the current diff --git a/e2e/test_get_immunization.py b/e2e/test_get_immunization.py index 0d8e982c3..60e8b3460 100644 --- a/e2e/test_get_immunization.py +++ b/e2e/test_get_immunization.py @@ -4,11 +4,10 @@ from utils.base_test import ImmunizationBaseTest from utils.immunisation_api import parse_location from utils.mappings import EndpointOperationNames, VaccineTypes -from utils.resource import generate_imms_resource, generate_filtered_imms_resource +from utils.resource import generate_filtered_imms_resource, generate_imms_resource class TestGetImmunization(ImmunizationBaseTest): - def test_get_imms(self): """it should get a FHIR Immunization resource""" for imms_api in self.imms_apis: diff --git a/e2e/test_proxy.py b/e2e/test_proxy.py index ead3f24b0..2f2fdc962 100644 --- a/e2e/test_proxy.py +++ b/e2e/test_proxy.py @@ -4,13 +4,11 @@ import uuid import requests - from lib.env import get_service_base_path, get_status_endpoint_api_key from utils.immunisation_api import ImmunisationApi class TestProxyHealthcheck(unittest.TestCase): - proxy_url: str status_api_key: str @@ -80,8 +78,7 @@ def get_backend_url() -> str: return res.stdout except FileNotFoundError: raise RuntimeError( - "Make sure you install terraform. This test can only be run if you have access to the" - "backend deployment" + "Make sure you install terraform. This test can only be run if you have access to thebackend deployment" ) except RuntimeError as e: raise RuntimeError(f"Failed to run command\n{e}") diff --git a/e2e/test_search_by_identifier_immunization.py b/e2e/test_search_by_identifier_immunization.py index fda427b3c..ac06b4c1e 100644 --- a/e2e/test_search_by_identifier_immunization.py +++ b/e2e/test_search_by_identifier_immunization.py @@ -1,17 +1,16 @@ import pprint import uuid from decimal import Decimal -from typing import NamedTuple, Literal, Optional +from typing import Literal, NamedTuple, Optional from lib.env import get_service_base_path from utils.base_test import ImmunizationBaseTest from utils.constants import valid_nhs_number1 from utils.mappings import VaccineTypes -from utils.resource import generate_imms_resource, generate_filtered_imms_resource +from utils.resource import generate_filtered_imms_resource, generate_imms_resource class TestSearchImmunizationByIdentifier(ImmunizationBaseTest): - def store_records(self, *resources): ids = [] for res in resources: @@ -68,7 +67,6 @@ def test_search_backwards_compatible(self): """ for imms_api in self.imms_apis: with self.subTest(imms_api): - stored_imms_resource = generate_imms_resource() imms_identifier_value = stored_imms_resource["identifier"][0]["value"] imms_id = self.store_records(stored_imms_resource) diff --git a/e2e/test_search_identifier_elements_immunization.py b/e2e/test_search_identifier_elements_immunization.py index da6c3d130..156eeb663 100644 --- a/e2e/test_search_identifier_elements_immunization.py +++ b/e2e/test_search_identifier_elements_immunization.py @@ -1,6 +1,6 @@ import pprint import uuid -from typing import NamedTuple, Literal, Optional +from typing import Literal, NamedTuple, Optional from lib.env import get_service_base_path from utils.base_test import ImmunizationBaseTest @@ -10,7 +10,6 @@ class TestSearchImmunizationByIdentifier(ImmunizationBaseTest): - def store_records(self, *resources): ids = [] for res in resources: diff --git a/e2e/test_search_immunization.py b/e2e/test_search_immunization.py index 12ae7bf76..e7486a1ce 100644 --- a/e2e/test_search_immunization.py +++ b/e2e/test_search_immunization.py @@ -1,18 +1,18 @@ import pprint import uuid from decimal import Decimal -from typing import NamedTuple, Literal, Optional, List +from typing import List, Literal, NamedTuple, Optional from lib.env import get_service_base_path from utils.base_test import ImmunizationBaseTest from utils.constants import ( valid_nhs_number1, valid_nhs_number2, - valid_patient_identifier2, valid_patient_identifier1, + valid_patient_identifier2, ) from utils.mappings import VaccineTypes -from utils.resource import generate_imms_resource, generate_filtered_imms_resource +from utils.resource import generate_filtered_imms_resource, generate_imms_resource class TestSearchImmunization(ImmunizationBaseTest): diff --git a/e2e/test_sqs_dlq.py b/e2e/test_sqs_dlq.py index 6a76ee67e..d92579e6c 100644 --- a/e2e/test_sqs_dlq.py +++ b/e2e/test_sqs_dlq.py @@ -4,13 +4,11 @@ import boto3 from botocore.exceptions import ClientError # Handle potential errors - from utils.delete_sqs_messages import read_and_delete_messages from utils.get_sqs_url import get_queue_url class TestSQS(unittest.TestCase): - def setUp(self): # Get SQS queue url self.queue_name = os.environ["AWS_SQS_QUEUE_NAME"] diff --git a/e2e/test_update_immunization.py b/e2e/test_update_immunization.py index 98c934e90..451184a0f 100644 --- a/e2e/test_update_immunization.py +++ b/e2e/test_update_immunization.py @@ -7,7 +7,6 @@ class TestUpdateImmunization(ImmunizationBaseTest): - def test_update_imms(self): """it should update a FHIR Immunization resource""" for imms_api in self.imms_apis: diff --git a/e2e/utils/base_test.py b/e2e/utils/base_test.py index 405db1654..9f648b393 100644 --- a/e2e/utils/base_test.py +++ b/e2e/utils/base_test.py @@ -2,10 +2,7 @@ import uuid from typing import List -from utils.constants import cis2_user -from utils.immunisation_api import ImmunisationApi - -from lib.apigee import ApigeeService, ApigeeApp, ApigeeProduct +from lib.apigee import ApigeeApp, ApigeeProduct, ApigeeService from lib.authentication import ( AppRestrictedAuthentication, Cis2Authentication, @@ -16,12 +13,14 @@ get_proxy_name, get_service_base_path, ) +from utils.constants import cis2_user from utils.factories import ( + make_apigee_product, make_apigee_service, make_app_restricted_app, make_cis2_app, - make_apigee_product, ) +from utils.immunisation_api import ImmunisationApi class ImmunizationBaseTest(unittest.TestCase): diff --git a/e2e/utils/factories.py b/e2e/utils/factories.py index a7b155ba7..ab3a86c34 100644 --- a/e2e/utils/factories.py +++ b/e2e/utils/factories.py @@ -2,18 +2,18 @@ import uuid from typing import Set -from lib.apigee import ApigeeService, ApigeeConfig, ApigeeApp, ApigeeProduct +from lib.apigee import ApigeeApp, ApigeeConfig, ApigeeProduct, ApigeeService from lib.authentication import ( - AppRestrictedCredentials, AppRestrictedAuthentication, + AppRestrictedCredentials, AuthType, UserRestrictedCredentials, ) from lib.env import ( get_apigee_access_token, - get_auth_url, - get_apigee_username, get_apigee_env, + get_apigee_username, + get_auth_url, get_default_app_restricted_credentials, get_proxy_name, ) diff --git a/e2e/utils/immunisation_api.py b/e2e/utils/immunisation_api.py index dda191e2a..ea2747907 100644 --- a/e2e/utils/immunisation_api.py +++ b/e2e/utils/immunisation_api.py @@ -3,12 +3,12 @@ import time import uuid from datetime import datetime -from typing import Optional, Literal, List +from typing import List, Literal, Optional import requests - from lib.authentication import BaseAuthentication -from utils.resource import generate_imms_resource, delete_imms_records +from utils.resource import delete_imms_records, generate_imms_resource + from .constants import patient_identifier_system @@ -85,10 +85,10 @@ def make_request_with_backoff( # Check if the response matches the expected status code to identify potential issues if response.status_code != expected_status_code: if response.status_code >= 500: - raise RuntimeError(f"Server error: {response.status_code} during " f"in {http_method} {url}") + raise RuntimeError(f"Server error: {response.status_code} during in {http_method} {url}") else: raise ValueError( - f"Expected {expected_status_code} but got " f"{response.status_code} in {http_method} {url}" + f"Expected {expected_status_code} but got {response.status_code} in {http_method} {url}" ) return response @@ -220,7 +220,6 @@ def search_immunizations_full( body: Optional[str], expected_status_code: int = 200, ): - if http_method == "POST": url = f"{self.url}/Immunization/_search?{query_string}" else: diff --git a/e2e/utils/resource.py b/e2e/utils/resource.py index e974cf3e5..1b341ceba 100644 --- a/e2e/utils/resource.py +++ b/e2e/utils/resource.py @@ -3,14 +3,14 @@ import uuid from copy import deepcopy from decimal import Decimal -from typing import Union, Literal +from typing import Literal, Union import boto3 from botocore.config import Config from mypy_boto3_dynamodb.service_resource import DynamoDBServiceResource, Table from .constants import valid_nhs_number1 -from .mappings import vaccine_type_mappings, VaccineTypes +from .mappings import VaccineTypes, vaccine_type_mappings current_directory = os.path.dirname(os.path.realpath(__file__)) @@ -169,7 +169,4 @@ def delete_imms_records(identifiers: list[str]) -> None: failure_count = total # Assume all failed if batch writer fails if failure_count > 0: - print( - f"[teardown warning] Deleted {success_count} records out of {total}, " - f"failed to delete {failure_count}" - ) + print(f"[teardown warning] Deleted {success_count} records out of {total}, failed to delete {failure_count}") diff --git a/e2e_batch/clients.py b/e2e_batch/clients.py index 1cd05f050..3198df763 100644 --- a/e2e_batch/clients.py +++ b/e2e_batch/clients.py @@ -3,15 +3,16 @@ """ import logging + +from boto3 import client as boto3_client +from boto3 import resource as boto3_resource from constants import ( - environment, REGION, - batch_fifo_queue_name, ack_metadata_queue_name, audit_table_name, + batch_fifo_queue_name, + environment, ) -from boto3 import client as boto3_client, resource as boto3_resource - # AWS Clients and Resources diff --git a/e2e_batch/scenarios.py b/e2e_batch/scenarios.py index 436c30d67..50789049b 100644 --- a/e2e_batch/scenarios.py +++ b/e2e_batch/scenarios.py @@ -1,27 +1,28 @@ -import pandas as pd +import csv +import uuid from datetime import datetime, timezone -from vax_suppliers import TestPair, OdsVax + +import pandas as pd +from clients import logger from constants import ( + ACK_BUCKET, + RAVS_URI, ActionFlag, BusRowResult, DestinationType, Operation, - ACK_BUCKET, - RAVS_URI, OperationOutcome, ) +from errors import DynamoDBMismatchError from utils import ( - poll_s3_file_pattern, - fetch_pk_and_operation_from_dynamodb, - validate_fatal_error, - get_file_content_from_s3, aws_cleanup, create_row, + fetch_pk_and_operation_from_dynamodb, + get_file_content_from_s3, + poll_s3_file_pattern, + validate_fatal_error, ) -from clients import logger -from errors import DynamoDBMismatchError -import uuid -import csv +from vax_suppliers import OdsVax, TestPair class TestAction: @@ -111,14 +112,12 @@ def check_bus_file_content(self): if operation_outcome and "OPERATION_OUTCOME" in row: row_OPERATION_OUTCOME = row["OPERATION_OUTCOME"].strip() assert row_OPERATION_OUTCOME.startswith(operation_outcome), ( - f"{desc}.Row {i} expected OPERATION_OUTCOME '{operation_outcome}', " - f"but got '{row_OPERATION_OUTCOME}'" + f"{desc}.Row {i} expected OPERATION_OUTCOME '{operation_outcome}', but got '{row_OPERATION_OUTCOME}'" ) elif row_HEADER_RESPONSE_CODE == "Fatal Error": validate_fatal_error(desc, row, i, operation_outcome) def generate_csv_file(self): - self.file_name = self.get_file_name(self.vax, self.ods, self.version) logger.info(f'Test "{self.name}" File {self.file_name}') data = [] diff --git a/e2e_batch/test_e2e_batch.py b/e2e_batch/test_e2e_batch.py index b55b737ff..963e9d93a 100644 --- a/e2e_batch/test_e2e_batch.py +++ b/e2e_batch/test_e2e_batch.py @@ -1,30 +1,29 @@ import time import unittest -from utils import ( - upload_file_to_s3, - get_file_content_from_s3, - check_ack_file_content, - validate_row_count, - purge_sqs_queues, - delete_file_from_s3, -) from clients import logger +from constants import ( + ACK_BUCKET, + INPUT_PREFIX, + SOURCE_BUCKET, + TEMP_ACK_PREFIX, + DestinationType, + environment, +) from scenarios import ( - scenarios, TestCase, create_test_cases, enable_tests, generate_csv_files, + scenarios, ) - -from constants import ( - SOURCE_BUCKET, - INPUT_PREFIX, - ACK_BUCKET, - environment, - DestinationType, - TEMP_ACK_PREFIX, +from utils import ( + check_ack_file_content, + delete_file_from_s3, + get_file_content_from_s3, + purge_sqs_queues, + upload_file_to_s3, + validate_row_count, ) diff --git a/e2e_batch/utils.py b/e2e_batch/utils.py index d3a4347af..e057075a3 100644 --- a/e2e_batch/utils.py +++ b/e2e_batch/utils.py @@ -1,37 +1,38 @@ -import time import csv -import pandas as pd -import uuid -import json -import random import io +import json import os -from botocore.exceptions import ClientError -from boto3.dynamodb.conditions import Key -from io import StringIO +import random +import time +import uuid from datetime import datetime, timezone +from io import StringIO + +import pandas as pd +from boto3.dynamodb.conditions import Key +from botocore.exceptions import ClientError from clients import ( - logger, - s3_client, + ack_metadata_queue_url, audit_table, + batch_fifo_queue_url, events_table, + logger, + s3_client, sqs_client, - batch_fifo_queue_url, - ack_metadata_queue_url, ) -from errors import AckFileNotFoundError, DynamoDBMismatchError from constants import ( ACK_BUCKET, - FORWARDEDFILE_PREFIX, - SOURCE_BUCKET, - DUPLICATE, ACK_PREFIX, + DUPLICATE, FILE_NAME_VAL_ERROR, + FORWARDEDFILE_PREFIX, HEADER_RESPONSE_CODE_COLUMN, RAVS_URI, + SOURCE_BUCKET, ActionFlag, environment, ) +from errors import AckFileNotFoundError, DynamoDBMismatchError def upload_file_to_s3(file_name, bucket, prefix): @@ -313,9 +314,9 @@ def validate_row_count(desc, source_file_name, ack_file_name): """ source_file_row_count = fetch_row_count(SOURCE_BUCKET, f"archive/{source_file_name}") ack_file_row_count = fetch_row_count(ACK_BUCKET, ack_file_name) - assert ( - source_file_row_count == ack_file_row_count - ), f"{desc}. Row count mismatch: Input ({source_file_row_count}) vs Ack ({ack_file_row_count})" + assert source_file_row_count == ack_file_row_count, ( + f"{desc}. Row count mismatch: Input ({source_file_row_count}) vs Ack ({ack_file_row_count})" + ) def fetch_row_count(bucket, file_name): @@ -430,7 +431,6 @@ def verify_final_ack_file(file_key): def delete_filename_from_audit_table(filename) -> bool: - # 1. Query the GSI to get all items with the given filename try: response = audit_table.query( @@ -449,7 +449,6 @@ def delete_filename_from_audit_table(filename) -> bool: def delete_filename_from_events_table(identifier) -> bool: - # 1. Query the GSI to get all items with the given filename try: identifier_pk = f"{RAVS_URI}#{identifier}" diff --git a/filenameprocessor/src/audit_table.py b/filenameprocessor/src/audit_table.py index 84f8efe41..08bf7c068 100644 --- a/filenameprocessor/src/audit_table.py +++ b/filenameprocessor/src/audit_table.py @@ -1,9 +1,10 @@ """Add the filename to the audit table and check for duplicates.""" from typing import Optional + from clients import dynamodb_client, logger -from errors import UnhandledAuditTableError from constants import AUDIT_TABLE_NAME, AuditTableKeys +from errors import UnhandledAuditTableError def upsert_audit_table( diff --git a/filenameprocessor/src/clients.py b/filenameprocessor/src/clients.py index 7690d2921..3149d877a 100644 --- a/filenameprocessor/src/clients.py +++ b/filenameprocessor/src/clients.py @@ -3,10 +3,12 @@ lambda should be initialised ONCE ONLY (in this file) and then imported into the files where they are needed. """ -import os import logging +import os + import redis -from boto3 import client as boto3_client, resource as boto3_resource +from boto3 import client as boto3_client +from boto3 import resource as boto3_resource # AWS Clients and Resources. REGION_NAME = "eu-west-2" diff --git a/filenameprocessor/src/constants.py b/filenameprocessor/src/constants.py index fe1fddef4..9f675b0ac 100644 --- a/filenameprocessor/src/constants.py +++ b/filenameprocessor/src/constants.py @@ -4,10 +4,10 @@ from enum import StrEnum from errors import ( - VaccineTypePermissionsError, InvalidFileKeyError, UnhandledAuditTableError, UnhandledSqsError, + VaccineTypePermissionsError, ) SOURCE_BUCKET_NAME = os.getenv("SOURCE_BUCKET_NAME") diff --git a/filenameprocessor/src/elasticache.py b/filenameprocessor/src/elasticache.py index 7270d7a29..3dc8f9ee0 100644 --- a/filenameprocessor/src/elasticache.py +++ b/filenameprocessor/src/elasticache.py @@ -1,9 +1,10 @@ import json + from clients import redis_client from constants import ( - VACCINE_TYPE_TO_DISEASES_HASH_KEY, - SUPPLIER_PERMISSIONS_HASH_KEY, ODS_CODE_TO_SUPPLIER_SYSTEM_HASH_KEY, + SUPPLIER_PERMISSIONS_HASH_KEY, + VACCINE_TYPE_TO_DISEASES_HASH_KEY, ) diff --git a/filenameprocessor/src/file_name_processor.py b/filenameprocessor/src/file_name_processor.py index 6c3310639..15860372b 100644 --- a/filenameprocessor/src/file_name_processor.py +++ b/filenameprocessor/src/file_name_processor.py @@ -8,26 +8,27 @@ import argparse from uuid import uuid4 -from utils_for_filenameprocessor import get_creation_and_expiry_times, move_file -from file_validation import validate_file_key, is_file_in_directory_root -from send_sqs_message import make_and_send_sqs_message -from make_and_upload_ack_file import make_and_upload_the_ack_file + from audit_table import upsert_audit_table from clients import logger, s3_client -from logging_decorator import logging_decorator -from supplier_permissions import validate_vaccine_type_permissions +from constants import ( + ERROR_TYPE_TO_STATUS_CODE_MAP, + SOURCE_BUCKET_NAME, + FileNotProcessedReason, + FileStatus, +) from errors import ( - VaccineTypePermissionsError, InvalidFileKeyError, UnhandledAuditTableError, UnhandledSqsError, + VaccineTypePermissionsError, ) -from constants import ( - FileNotProcessedReason, - FileStatus, - ERROR_TYPE_TO_STATUS_CODE_MAP, - SOURCE_BUCKET_NAME, -) +from file_validation import is_file_in_directory_root, validate_file_key +from logging_decorator import logging_decorator +from make_and_upload_ack_file import make_and_upload_the_ack_file +from send_sqs_message import make_and_send_sqs_message +from supplier_permissions import validate_vaccine_type_permissions +from utils_for_filenameprocessor import get_creation_and_expiry_times, move_file # NOTE: logging_decorator is applied to handle_record function, rather than lambda_handler, because diff --git a/filenameprocessor/src/file_validation.py b/filenameprocessor/src/file_validation.py index 125393ec7..7440ad77b 100644 --- a/filenameprocessor/src/file_validation.py +++ b/filenameprocessor/src/file_validation.py @@ -1,11 +1,12 @@ """Functions for file key validation""" -from re import match from datetime import datetime +from re import match + from constants import VALID_VERSIONS from elasticache import ( - get_valid_vaccine_types_from_cache, get_supplier_system_from_cache, + get_valid_vaccine_types_from_cache, ) from errors import InvalidFileKeyError diff --git a/filenameprocessor/src/logging_decorator.py b/filenameprocessor/src/logging_decorator.py index c06f4f4c1..2cb281a25 100644 --- a/filenameprocessor/src/logging_decorator.py +++ b/filenameprocessor/src/logging_decorator.py @@ -5,6 +5,7 @@ import time from datetime import datetime from functools import wraps + from clients import firehose_client, logger STREAM_NAME = os.getenv("SPLUNK_FIREHOSE_NAME", "immunisation-fhir-api-internal-dev-splunk-firehose") diff --git a/filenameprocessor/src/make_and_upload_ack_file.py b/filenameprocessor/src/make_and_upload_ack_file.py index ccefba0ac..7d820adee 100644 --- a/filenameprocessor/src/make_and_upload_ack_file.py +++ b/filenameprocessor/src/make_and_upload_ack_file.py @@ -1,8 +1,9 @@ """Create ack file and upload to S3 bucket""" -from csv import writer import os -from io import StringIO, BytesIO +from csv import writer +from io import BytesIO, StringIO + from clients import s3_client diff --git a/filenameprocessor/src/send_sqs_message.py b/filenameprocessor/src/send_sqs_message.py index a5fb3c527..92746c0e1 100644 --- a/filenameprocessor/src/send_sqs_message.py +++ b/filenameprocessor/src/send_sqs_message.py @@ -2,7 +2,8 @@ import os from json import dumps as json_dumps -from clients import sqs_client, logger + +from clients import logger, sqs_client from errors import UnhandledSqsError diff --git a/filenameprocessor/src/supplier_permissions.py b/filenameprocessor/src/supplier_permissions.py index 8fbef2c75..79f8d8bb7 100644 --- a/filenameprocessor/src/supplier_permissions.py +++ b/filenameprocessor/src/supplier_permissions.py @@ -1,8 +1,8 @@ """Functions for fetching supplier permissions""" from clients import logger -from errors import VaccineTypePermissionsError from elasticache import get_supplier_permissions_from_cache +from errors import VaccineTypePermissionsError def validate_vaccine_type_permissions(vaccine_type: str, supplier: str) -> list: diff --git a/filenameprocessor/src/utils_for_filenameprocessor.py b/filenameprocessor/src/utils_for_filenameprocessor.py index d3ea2e1ff..d2a9324c9 100644 --- a/filenameprocessor/src/utils_for_filenameprocessor.py +++ b/filenameprocessor/src/utils_for_filenameprocessor.py @@ -1,7 +1,8 @@ """Utils for filenameprocessor lambda""" from datetime import timedelta -from clients import s3_client, logger + +from clients import logger, s3_client from constants import AUDIT_TABLE_TTL_DAYS diff --git a/filenameprocessor/tests/test_audit_table.py b/filenameprocessor/tests/test_audit_table.py index 0d958d2e0..3355d61f6 100644 --- a/filenameprocessor/tests/test_audit_table.py +++ b/filenameprocessor/tests/test_audit_table.py @@ -2,25 +2,26 @@ from unittest import TestCase from unittest.mock import patch + from boto3 import client as boto3_client from moto import mock_dynamodb -from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT from tests.utils_for_tests.generic_setup_and_teardown import ( GenericSetUp, GenericTearDown, ) -from tests.utils_for_tests.values_for_tests import MockFileDetails, FileDetails +from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT from tests.utils_for_tests.utils_for_filenameprocessor_tests import ( assert_audit_table_entry, ) +from tests.utils_for_tests.values_for_tests import FileDetails, MockFileDetails # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from constants import AUDIT_TABLE_NAME, FileStatus from audit_table import upsert_audit_table - from errors import UnhandledAuditTableError from clients import REGION_NAME + from constants import AUDIT_TABLE_NAME, FileStatus + from errors import UnhandledAuditTableError dynamodb_client = boto3_client("dynamodb", region_name=REGION_NAME) diff --git a/filenameprocessor/tests/test_elasticache.py b/filenameprocessor/tests/test_elasticache.py index 098ab9b7e..87f0437cd 100644 --- a/filenameprocessor/tests/test_elasticache.py +++ b/filenameprocessor/tests/test_elasticache.py @@ -3,24 +3,25 @@ import json from unittest import TestCase from unittest.mock import patch + from boto3 import client as boto3_client from moto import mock_s3 -from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT from tests.utils_for_tests.generic_setup_and_teardown import ( GenericSetUp, GenericTearDown, ) +from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT from tests.utils_for_tests.utils_for_filenameprocessor_tests import create_mock_hget # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): + from clients import REGION_NAME from elasticache import ( get_supplier_permissions_from_cache, - get_valid_vaccine_types_from_cache, get_supplier_system_from_cache, + get_valid_vaccine_types_from_cache, ) - from clients import REGION_NAME s3_client = boto3_client("s3", region_name=REGION_NAME) diff --git a/filenameprocessor/tests/test_file_key_validation.py b/filenameprocessor/tests/test_file_key_validation.py index a7ca2bc6d..73560e39f 100644 --- a/filenameprocessor/tests/test_file_key_validation.py +++ b/filenameprocessor/tests/test_file_key_validation.py @@ -3,21 +3,21 @@ from unittest import TestCase from unittest.mock import patch -from tests.utils_for_tests.values_for_tests import MockFileDetails from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT from tests.utils_for_tests.utils_for_filenameprocessor_tests import ( MOCK_ODS_CODE_TO_SUPPLIER, create_mock_hget, ) +from tests.utils_for_tests.values_for_tests import MockFileDetails # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): + from errors import InvalidFileKeyError from file_validation import ( is_file_in_directory_root, is_valid_datetime, validate_file_key, ) - from errors import InvalidFileKeyError VALID_FLU_EMIS_FILE_KEY = MockFileDetails.emis_flu.file_key VALID_RSV_RAVS_FILE_KEY = MockFileDetails.ravs_rsv_1.file_key diff --git a/filenameprocessor/tests/test_lambda_handler.py b/filenameprocessor/tests/test_lambda_handler.py index 1c754dd11..5642adede 100644 --- a/filenameprocessor/tests/test_lambda_handler.py +++ b/filenameprocessor/tests/test_lambda_handler.py @@ -2,41 +2,42 @@ import json import sys -from unittest.mock import patch, ANY -from unittest import TestCase -from json import loads as json_loads from contextlib import ExitStack from copy import deepcopy +from json import loads as json_loads +from unittest import TestCase +from unittest.mock import ANY, patch + import fakeredis from boto3 import client as boto3_client -from moto import mock_s3, mock_sqs, mock_firehose, mock_dynamodb +from moto import mock_dynamodb, mock_firehose, mock_s3, mock_sqs from tests.utils_for_tests.generic_setup_and_teardown import ( GenericSetUp, GenericTearDown, ) -from tests.utils_for_tests.utils_for_filenameprocessor_tests import ( - assert_audit_table_entry, - create_mock_hget, - MOCK_ODS_CODE_TO_SUPPLIER, -) from tests.utils_for_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, BucketNames, Sqs, ) +from tests.utils_for_tests.utils_for_filenameprocessor_tests import ( + MOCK_ODS_CODE_TO_SUPPLIER, + assert_audit_table_entry, + create_mock_hget, +) from tests.utils_for_tests.values_for_tests import ( - MOCK_CREATED_AT_FORMATTED_STRING, - MockFileDetails, MOCK_BATCH_FILE_CONTENT, + MOCK_CREATED_AT_FORMATTED_STRING, MOCK_EXPIRES_AT, + MockFileDetails, ) # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from file_name_processor import lambda_handler, handle_record from clients import REGION_NAME - from constants import AUDIT_TABLE_NAME, FileStatus, AuditTableKeys + from constants import AUDIT_TABLE_NAME, AuditTableKeys, FileStatus + from file_name_processor import handle_record, lambda_handler s3_client = boto3_client("s3", region_name=REGION_NAME) sqs_client = boto3_client("sqs", region_name=REGION_NAME) @@ -443,7 +444,6 @@ def test_unexpected_bucket_name_and_filename_validation_fails(self): class TestMainEntryPoint(TestCase): - def test_run_local_constructs_event_and_calls_lambda_handler(self): test_args = [ "file_name_processor.py", diff --git a/filenameprocessor/tests/test_logging_decorator.py b/filenameprocessor/tests/test_logging_decorator.py index 0dc3285f6..f90f80168 100644 --- a/filenameprocessor/tests/test_logging_decorator.py +++ b/filenameprocessor/tests/test_logging_decorator.py @@ -1,12 +1,13 @@ """Tests for the logging_decorator and its helper functions""" -import unittest -from unittest.mock import patch import json +import unittest from contextlib import ExitStack +from unittest.mock import patch + from boto3 import client as boto3_client from botocore.exceptions import ClientError -from moto import mock_s3, mock_firehose, mock_sqs, mock_dynamodb +from moto import mock_dynamodb, mock_firehose, mock_s3, mock_sqs from tests.utils_for_tests.generic_setup_and_teardown import ( GenericSetUp, @@ -17,18 +18,18 @@ BucketNames, Firehose, ) +from tests.utils_for_tests.utils_for_filenameprocessor_tests import create_mock_hget from tests.utils_for_tests.values_for_tests import ( + MOCK_BATCH_FILE_CONTENT, MockFileDetails, fixed_datetime, - MOCK_BATCH_FILE_CONTENT, ) -from tests.utils_for_tests.utils_for_filenameprocessor_tests import create_mock_hget # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): from clients import REGION_NAME from file_name_processor import lambda_handler - from logging_decorator import send_log_to_firehose, generate_and_send_logs + from logging_decorator import generate_and_send_logs, send_log_to_firehose s3_client = boto3_client("s3", region_name=REGION_NAME) sqs_client = boto3_client("sqs", region_name=REGION_NAME) diff --git a/filenameprocessor/tests/test_make_and_upload_ack_file.py b/filenameprocessor/tests/test_make_and_upload_ack_file.py index 0005ca3db..f1dadf587 100644 --- a/filenameprocessor/tests/test_make_and_upload_ack_file.py +++ b/filenameprocessor/tests/test_make_and_upload_ack_file.py @@ -1,28 +1,29 @@ """Tests for make_and_upload_ack_file functions""" +from copy import deepcopy from unittest import TestCase from unittest.mock import patch -from copy import deepcopy + from boto3 import client as boto3_client from moto import mock_s3 -from tests.utils_for_tests.utils_for_filenameprocessor_tests import ( - get_csv_file_dict_reader, -) from tests.utils_for_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, BucketNames, ) +from tests.utils_for_tests.utils_for_filenameprocessor_tests import ( + get_csv_file_dict_reader, +) from tests.utils_for_tests.values_for_tests import MockFileDetails # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): + from clients import REGION_NAME from make_and_upload_ack_file import ( + make_and_upload_the_ack_file, make_the_ack_data, upload_ack_file, - make_and_upload_the_ack_file, ) - from clients import REGION_NAME s3_client = boto3_client("s3", region_name=REGION_NAME) diff --git a/filenameprocessor/tests/test_send_sqs_message.py b/filenameprocessor/tests/test_send_sqs_message.py index 054996e5c..a05048521 100644 --- a/filenameprocessor/tests/test_send_sqs_message.py +++ b/filenameprocessor/tests/test_send_sqs_message.py @@ -1,20 +1,21 @@ """Tests for send_sqs_message functions""" +from copy import deepcopy +from json import loads as json_loads from unittest import TestCase from unittest.mock import patch -from json import loads as json_loads -from copy import deepcopy -from moto import mock_sqs + from boto3 import client as boto3_client +from moto import mock_sqs from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT, Sqs from tests.utils_for_tests.values_for_tests import MockFileDetails # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from send_sqs_message import send_to_supplier_queue, make_and_send_sqs_message - from errors import UnhandledSqsError from clients import REGION_NAME + from errors import UnhandledSqsError + from send_sqs_message import make_and_send_sqs_message, send_to_supplier_queue sqs_client = boto3_client("sqs", region_name=REGION_NAME) diff --git a/filenameprocessor/tests/test_supplier_permissions.py b/filenameprocessor/tests/test_supplier_permissions.py index d373a9223..5f1981077 100644 --- a/filenameprocessor/tests/test_supplier_permissions.py +++ b/filenameprocessor/tests/test_supplier_permissions.py @@ -7,8 +7,8 @@ # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from supplier_permissions import validate_vaccine_type_permissions from errors import VaccineTypePermissionsError + from supplier_permissions import validate_vaccine_type_permissions class TestSupplierPermissions(TestCase): diff --git a/filenameprocessor/tests/test_utils_for_filenameprocessor.py b/filenameprocessor/tests/test_utils_for_filenameprocessor.py index 692f9eea9..449274235 100644 --- a/filenameprocessor/tests/test_utils_for_filenameprocessor.py +++ b/filenameprocessor/tests/test_utils_for_filenameprocessor.py @@ -1,24 +1,25 @@ """Tests for utils_for_filenameprocessor functions""" +from datetime import datetime, timedelta, timezone from unittest import TestCase from unittest.mock import patch -from datetime import datetime, timedelta, timezone -from moto import mock_s3 + from boto3 import client as boto3_client +from moto import mock_s3 -from tests.utils_for_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, - BucketNames, -) from tests.utils_for_tests.generic_setup_and_teardown import ( GenericSetUp, GenericTearDown, ) +from tests.utils_for_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, + BucketNames, +) # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from constants import AUDIT_TABLE_TTL_DAYS from clients import REGION_NAME + from constants import AUDIT_TABLE_TTL_DAYS from utils_for_filenameprocessor import get_creation_and_expiry_times, move_file s3_client = boto3_client("s3", region_name=REGION_NAME) diff --git a/filenameprocessor/tests/utils_for_tests/generic_setup_and_teardown.py b/filenameprocessor/tests/utils_for_tests/generic_setup_and_teardown.py index c7d79359d..27d87aa42 100644 --- a/filenameprocessor/tests/utils_for_tests/generic_setup_and_teardown.py +++ b/filenameprocessor/tests/utils_for_tests/generic_setup_and_teardown.py @@ -3,16 +3,16 @@ from unittest.mock import patch from tests.utils_for_tests.mock_environment_variables import ( - BucketNames, MOCK_ENVIRONMENT_DICT, - Sqs, + BucketNames, Firehose, + Sqs, ) # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): from clients import REGION_NAME - from constants import AuditTableKeys, AUDIT_TABLE_NAME + from constants import AUDIT_TABLE_NAME, AuditTableKeys class GenericSetUp: @@ -32,7 +32,6 @@ def __init__( sqs_client=None, dynamodb_client=None, ): - if s3_client: for bucket_name in [ BucketNames.SOURCE, @@ -78,7 +77,6 @@ def __init__( sqs_client=None, dynamodb_client=None, ): - if s3_client: for bucket_name in [ BucketNames.SOURCE, diff --git a/filenameprocessor/tests/utils_for_tests/utils_for_filenameprocessor_tests.py b/filenameprocessor/tests/utils_for_tests/utils_for_filenameprocessor_tests.py index c7956735e..440046aa2 100644 --- a/filenameprocessor/tests/utils_for_tests/utils_for_filenameprocessor_tests.py +++ b/filenameprocessor/tests/utils_for_tests/utils_for_filenameprocessor_tests.py @@ -1,22 +1,23 @@ """Utils functions for filenameprocessor tests""" -from unittest.mock import patch from io import StringIO -from boto3 import client as boto3_client +from unittest.mock import patch -from tests.utils_for_tests.values_for_tests import FileDetails, MockFileDetails +from boto3 import client as boto3_client from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT +from tests.utils_for_tests.values_for_tests import FileDetails, MockFileDetails # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from clients import REGION_NAME from csv import DictReader + + from clients import REGION_NAME from constants import ( - AuditTableKeys, AUDIT_TABLE_NAME, - FileStatus, - SUPPLIER_PERMISSIONS_HASH_KEY, ODS_CODE_TO_SUPPLIER_SYSTEM_HASH_KEY, + SUPPLIER_PERMISSIONS_HASH_KEY, + AuditTableKeys, + FileStatus, ) MOCK_ODS_CODE_TO_SUPPLIER = {"YGM41": "EMIS", "X8E5B": "RAVS"} diff --git a/filenameprocessor/tests/utils_for_tests/values_for_tests.py b/filenameprocessor/tests/utils_for_tests/values_for_tests.py index 8d48d4b9a..017d013d6 100644 --- a/filenameprocessor/tests/utils_for_tests/values_for_tests.py +++ b/filenameprocessor/tests/utils_for_tests/values_for_tests.py @@ -1,7 +1,7 @@ """File of values which can be used for testing""" -from unittest.mock import patch from datetime import datetime +from unittest.mock import patch from tests.utils_for_tests.mock_environment_variables import MOCK_ENVIRONMENT_DICT diff --git a/lambdas/ack_backend/src/ack_processor.py b/lambdas/ack_backend/src/ack_processor.py index de84fee57..7b5cf9885 100644 --- a/lambdas/ack_backend/src/ack_processor.py +++ b/lambdas/ack_backend/src/ack_processor.py @@ -1,9 +1,10 @@ """Ack lambda handler""" import json + +from convert_message_to_ack_row import convert_message_to_ack_row from logging_decorators import ack_lambda_handler_logging_decorator from update_ack_file import update_ack_file -from convert_message_to_ack_row import convert_message_to_ack_row @ack_lambda_handler_logging_decorator @@ -24,7 +25,6 @@ def lambda_handler(event, context): ack_data_rows = [] for i, record in enumerate(event["Records"]): - try: incoming_message_body = json.loads(record["body"]) except Exception as body_json_error: diff --git a/lambdas/ack_backend/src/audit_table.py b/lambdas/ack_backend/src/audit_table.py index 48a723d27..7f0fdf43d 100644 --- a/lambdas/ack_backend/src/audit_table.py +++ b/lambdas/ack_backend/src/audit_table.py @@ -2,7 +2,7 @@ from common.clients import dynamodb_client, logger from common.models.errors import UnhandledAuditTableError -from constants import AUDIT_TABLE_NAME, FileStatus, AuditTableKeys +from constants import AUDIT_TABLE_NAME, AuditTableKeys, FileStatus def change_audit_table_status_to_processed(file_key: str, message_id: str) -> None: diff --git a/lambdas/ack_backend/src/logging_decorators.py b/lambdas/ack_backend/src/logging_decorators.py index 9327c9e9e..a5cadae23 100644 --- a/lambdas/ack_backend/src/logging_decorators.py +++ b/lambdas/ack_backend/src/logging_decorators.py @@ -4,6 +4,7 @@ import time from datetime import datetime from functools import wraps + from common.log_decorator import generate_and_send_logs PREFIX = "ack_processor" @@ -73,7 +74,6 @@ def upload_ack_file_logging_decorator(func): @wraps(func) def wrapper(*args, **kwargs): - base_log_data = { "function_name": f"{PREFIX}_{func.__name__}", "date_time": str(datetime.now()), @@ -101,7 +101,6 @@ def ack_lambda_handler_logging_decorator(func): @wraps(func) def wrapper(event, context, *args, **kwargs): - base_log_data = { "function_name": f"{PREFIX}_{func.__name__}", "date_time": str(datetime.now()), diff --git a/lambdas/ack_backend/src/update_ack_file.py b/lambdas/ack_backend/src/update_ack_file.py index 3ae60dd86..3df7f83b1 100644 --- a/lambdas/ack_backend/src/update_ack_file.py +++ b/lambdas/ack_backend/src/update_ack_file.py @@ -1,11 +1,12 @@ """Functions for uploading the data to the ack file""" -from botocore.exceptions import ClientError -from io import StringIO, BytesIO +from io import BytesIO, StringIO from typing import Optional + from audit_table import change_audit_table_status_to_processed +from botocore.exceptions import ClientError from common.clients import get_s3_client, logger -from constants import ACK_HEADERS, get_source_bucket_name, get_ack_bucket_name +from constants import ACK_HEADERS, get_ack_bucket_name, get_source_bucket_name from logging_decorators import upload_ack_file_logging_decorator from utils_for_ack_lambda import get_row_count diff --git a/lambdas/ack_backend/tests/test_ack_processor.py b/lambdas/ack_backend/tests/test_ack_processor.py index 82e6a3262..84e9ac608 100644 --- a/lambdas/ack_backend/tests/test_ack_processor.py +++ b/lambdas/ack_backend/tests/test_ack_processor.py @@ -1,31 +1,32 @@ """Tests for the ack processor lambda handler.""" -import unittest -import os import json -from unittest.mock import patch +import os +import unittest from io import StringIO +from unittest.mock import patch + from boto3 import client as boto3_client -from moto import mock_s3, mock_firehose +from moto import mock_firehose, mock_s3 -from tests.utils.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, - BucketNames, - REGION_NAME, -) from tests.utils.generic_setup_and_teardown_for_ack_backend import ( GenericSetUp, GenericTearDown, ) +from tests.utils.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, + REGION_NAME, + BucketNames, +) from tests.utils.utils_for_ack_backend_tests import ( setup_existing_ack_file, validate_ack_file_content, ) from tests.utils.values_for_ack_backend_tests import ( - DiagnosticsDictionaries, + EXPECTED_ACK_LAMBDA_RESPONSE_FOR_SUCCESS, MOCK_MESSAGE_DETAILS, + DiagnosticsDictionaries, ValidValues, - EXPECTED_ACK_LAMBDA_RESPONSE_FOR_SUCCESS, ) with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): @@ -150,7 +151,7 @@ def test_lambda_handler_main(self): test_cases = [ { "description": "Multiple messages: all successful", - "messages": [{"row_id": f"row_{i+1}"} for i in range(10)], + "messages": [{"row_id": f"row_{i + 1}"} for i in range(10)], }, { "description": "Multiple messages: all with diagnostics (failure messages)", diff --git a/lambdas/ack_backend/tests/test_audit_table.py b/lambdas/ack_backend/tests/test_audit_table.py index cea36ea40..f44f24301 100644 --- a/lambdas/ack_backend/tests/test_audit_table.py +++ b/lambdas/ack_backend/tests/test_audit_table.py @@ -1,11 +1,11 @@ import unittest from unittest.mock import patch + import audit_table from common.models.errors import UnhandledAuditTableError class TestAuditTable(unittest.TestCase): - def setUp(self): self.logger_patcher = patch("audit_table.logger") self.mock_logger = self.logger_patcher.start() diff --git a/lambdas/ack_backend/tests/test_convert_message_to_ack_row.py b/lambdas/ack_backend/tests/test_convert_message_to_ack_row.py index 45d56bed2..197083954 100644 --- a/lambdas/ack_backend/tests/test_convert_message_to_ack_row.py +++ b/lambdas/ack_backend/tests/test_convert_message_to_ack_row.py @@ -2,19 +2,19 @@ import unittest from unittest.mock import patch -from boto3 import client as boto3_client -from moto import mock_s3, mock_firehose +from boto3 import client as boto3_client +from moto import mock_firehose, mock_s3 -from tests.utils.mock_environment_variables import MOCK_ENVIRONMENT_DICT, REGION_NAME from tests.utils.generic_setup_and_teardown_for_ack_backend import ( GenericSetUp, GenericTearDown, ) +from tests.utils.mock_environment_variables import MOCK_ENVIRONMENT_DICT, REGION_NAME from tests.utils.values_for_ack_backend_tests import ( DefaultValues, - ValidValues, DiagnosticsDictionaries, + ValidValues, ) with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): diff --git a/lambdas/ack_backend/tests/test_logging_decorators.py b/lambdas/ack_backend/tests/test_logging_decorators.py index f9b85d85f..d410c4af8 100644 --- a/lambdas/ack_backend/tests/test_logging_decorators.py +++ b/lambdas/ack_backend/tests/test_logging_decorators.py @@ -1,5 +1,6 @@ import unittest from unittest.mock import patch + import logging_decorators diff --git a/lambdas/ack_backend/tests/test_splunk_logging.py b/lambdas/ack_backend/tests/test_splunk_logging.py index 90229d89e..c6e6c55de 100644 --- a/lambdas/ack_backend/tests/test_splunk_logging.py +++ b/lambdas/ack_backend/tests/test_splunk_logging.py @@ -1,25 +1,26 @@ """Tests for ack lambda logging decorators""" -import unittest -from unittest.mock import patch, call import json -from io import StringIO +import unittest from contextlib import ExitStack -from moto import mock_s3 +from io import StringIO +from unittest.mock import call, patch + from boto3 import client as boto3_client +from moto import mock_s3 -from tests.utils.values_for_ack_backend_tests import ( - ValidValues, - InvalidValues, - DiagnosticsDictionaries, - EXPECTED_ACK_LAMBDA_RESPONSE_FOR_SUCCESS, -) -from tests.utils.mock_environment_variables import MOCK_ENVIRONMENT_DICT, BucketNames from tests.utils.generic_setup_and_teardown_for_ack_backend import ( GenericSetUp, GenericTearDown, ) +from tests.utils.mock_environment_variables import MOCK_ENVIRONMENT_DICT, BucketNames from tests.utils.utils_for_ack_backend_tests import generate_event +from tests.utils.values_for_ack_backend_tests import ( + EXPECTED_ACK_LAMBDA_RESPONSE_FOR_SUCCESS, + DiagnosticsDictionaries, + InvalidValues, + ValidValues, +) with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): from ack_processor import lambda_handler diff --git a/lambdas/ack_backend/tests/test_update_ack_file.py b/lambdas/ack_backend/tests/test_update_ack_file.py index c9ee7de7a..a18f17078 100644 --- a/lambdas/ack_backend/tests/test_update_ack_file.py +++ b/lambdas/ack_backend/tests/test_update_ack_file.py @@ -1,36 +1,36 @@ """Tests for the functions in the update_ack_file module.""" -import unittest import os +import unittest +from io import StringIO +from unittest.mock import patch + from boto3 import client as boto3_client from moto import mock_s3 -from tests.utils.values_for_ack_backend_tests import ValidValues, DefaultValues -from tests.utils.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, - BucketNames, - REGION_NAME, -) from tests.utils.generic_setup_and_teardown_for_ack_backend import ( GenericSetUp, GenericTearDown, ) +from tests.utils.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, + REGION_NAME, + BucketNames, +) from tests.utils.utils_for_ack_backend_tests import ( - setup_existing_ack_file, - obtain_current_ack_file_content, + MOCK_MESSAGE_DETAILS, + generate_expected_ack_content, generate_expected_ack_file_row, generate_sample_existing_ack_content, - generate_expected_ack_content, - MOCK_MESSAGE_DETAILS, + obtain_current_ack_file_content, + setup_existing_ack_file, ) - -from unittest.mock import patch -from io import StringIO +from tests.utils.values_for_ack_backend_tests import DefaultValues, ValidValues with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): from update_ack_file import ( - obtain_current_ack_content, create_ack_data, + obtain_current_ack_content, update_ack_file, ) diff --git a/lambdas/ack_backend/tests/test_update_ack_file_flow.py b/lambdas/ack_backend/tests/test_update_ack_file_flow.py index 6ad16c148..333629e3b 100644 --- a/lambdas/ack_backend/tests/test_update_ack_file_flow.py +++ b/lambdas/ack_backend/tests/test_update_ack_file_flow.py @@ -1,10 +1,9 @@ -from unittest.mock import patch +import unittest from io import StringIO +from unittest.mock import patch -import update_ack_file -import unittest import boto3 - +import update_ack_file from moto import mock_s3 diff --git a/lambdas/ack_backend/tests/utils/generic_setup_and_teardown_for_ack_backend.py b/lambdas/ack_backend/tests/utils/generic_setup_and_teardown_for_ack_backend.py index f30dc8244..fbdc4706a 100644 --- a/lambdas/ack_backend/tests/utils/generic_setup_and_teardown_for_ack_backend.py +++ b/lambdas/ack_backend/tests/utils/generic_setup_and_teardown_for_ack_backend.py @@ -1,6 +1,6 @@ """Generic setup and teardown for ACK backend tests""" -from tests.utils.mock_environment_variables import BucketNames, Firehose, REGION_NAME +from tests.utils.mock_environment_variables import REGION_NAME, BucketNames, Firehose class GenericSetUp: @@ -12,7 +12,6 @@ class GenericSetUp: """ def __init__(self, s3_client=None, firehose_client=None): - if s3_client: for bucket_name in [ BucketNames.SOURCE, @@ -40,7 +39,6 @@ class GenericTearDown: """Performs generic tear down of mock resources""" def __init__(self, s3_client=None, firehose_client=None): - if s3_client: for bucket_name in [ BucketNames.SOURCE, diff --git a/lambdas/ack_backend/tests/utils/utils_for_ack_backend_tests.py b/lambdas/ack_backend/tests/utils/utils_for_ack_backend_tests.py index f2153743b..649eea49d 100644 --- a/lambdas/ack_backend/tests/utils/utils_for_ack_backend_tests.py +++ b/lambdas/ack_backend/tests/utils/utils_for_ack_backend_tests.py @@ -1,9 +1,10 @@ """Utils functions for the ack backend tests""" import json + from boto3 import client as boto3_client -from tests.utils.values_for_ack_backend_tests import ValidValues, MOCK_MESSAGE_DETAILS from tests.utils.mock_environment_variables import REGION_NAME, BucketNames +from tests.utils.values_for_ack_backend_tests import MOCK_MESSAGE_DETAILS, ValidValues firehose_client = boto3_client("firehose", region_name=REGION_NAME) diff --git a/lambdas/id_sync/src/id_sync.py b/lambdas/id_sync/src/id_sync.py index a79ca20a4..070b927f7 100644 --- a/lambdas/id_sync/src/id_sync.py +++ b/lambdas/id_sync/src/id_sync.py @@ -6,8 +6,9 @@ """ from typing import Any, Dict + from common.aws_lambda_event import AwsLambdaEvent -from common.clients import logger, STREAM_NAME +from common.clients import STREAM_NAME, logger from common.log_decorator import logging_decorator from exceptions.id_sync_exception import IdSyncException from record_processor import process_record diff --git a/lambdas/id_sync/src/ieds_db_operations.py b/lambdas/id_sync/src/ieds_db_operations.py index 2ecac4a7a..fd88a25cb 100644 --- a/lambdas/id_sync/src/ieds_db_operations.py +++ b/lambdas/id_sync/src/ieds_db_operations.py @@ -1,10 +1,11 @@ +import json + from boto3.dynamodb.conditions import Key -from os_vars import get_ieds_table_name from common.aws_dynamodb import get_dynamodb_table -from common.clients import logger, dynamodb_client -import json -from utils import make_status +from common.clients import dynamodb_client, logger from exceptions.id_sync_exception import IdSyncException +from os_vars import get_ieds_table_name +from utils import make_status ieds_table = None BATCH_SIZE = 25 # DynamoDB TransactWriteItems max batch size diff --git a/lambdas/id_sync/src/pds_details.py b/lambdas/id_sync/src/pds_details.py index 7f6271aa5..d38ece5f9 100644 --- a/lambdas/id_sync/src/pds_details.py +++ b/lambdas/id_sync/src/pds_details.py @@ -3,12 +3,13 @@ """ import tempfile -from os_vars import get_pds_env + from common.authentication import AppRestrictedAuth, Service from common.cache import Cache from common.clients import logger, secrets_manager_client from common.pds_service import PdsService from exceptions.id_sync_exception import IdSyncException +from os_vars import get_pds_env pds_env = get_pds_env() safe_tmp_dir = tempfile.mkdtemp(dir="/tmp") # NOSONAR diff --git a/lambdas/id_sync/src/record_processor.py b/lambdas/id_sync/src/record_processor.py index 2918d9b18..6d42d93e8 100644 --- a/lambdas/id_sync/src/record_processor.py +++ b/lambdas/id_sync/src/record_processor.py @@ -1,18 +1,18 @@ +import ast +import json +from typing import Any, Dict + from common.clients import logger -from typing import Dict, Any -from pds_details import pds_get_patient_id, pds_get_patient_details from ieds_db_operations import ( - ieds_update_patient_id, extract_patient_resource_from_item, get_items_from_patient_id, + ieds_update_patient_id, ) +from pds_details import pds_get_patient_details, pds_get_patient_id from utils import make_status -import json -import ast def process_record(event_record: Dict[str, Any]) -> Dict[str, Any]: - logger.info("process_record. Processing record: %s", event_record) body_text = event_record.get("body", "") diff --git a/lambdas/id_sync/src/utils.py b/lambdas/id_sync/src/utils.py index ea9dcdef4..920ad7b84 100644 --- a/lambdas/id_sync/src/utils.py +++ b/lambdas/id_sync/src/utils.py @@ -1,4 +1,4 @@ -from typing import Dict, Any +from typing import Any, Dict def make_status(msg: str, nhs_number: str | None = None, status: str = "success") -> Dict[str, Any]: diff --git a/lambdas/id_sync/tests/test_id_sync.py b/lambdas/id_sync/tests/test_id_sync.py index 81ca598a1..f86b242c9 100644 --- a/lambdas/id_sync/tests/test_id_sync.py +++ b/lambdas/id_sync/tests/test_id_sync.py @@ -1,15 +1,13 @@ import unittest -from unittest.mock import patch, MagicMock - +from unittest.mock import MagicMock, patch with patch("common.log_decorator.logging_decorator") as mock_decorator: mock_decorator.return_value = lambda f: f # Pass-through decorator - from id_sync import handler from exceptions.id_sync_exception import IdSyncException + from id_sync import handler class TestIdSyncHandler(unittest.TestCase): - def setUp(self): """Set up all patches and test fixtures""" # Patch all dependencies diff --git a/lambdas/id_sync/tests/test_ieds_db_operations.py b/lambdas/id_sync/tests/test_ieds_db_operations.py index 2138a7954..4a67d41a3 100644 --- a/lambdas/id_sync/tests/test_ieds_db_operations.py +++ b/lambdas/id_sync/tests/test_ieds_db_operations.py @@ -1,13 +1,12 @@ import unittest +from unittest.mock import MagicMock, patch -from ieds_db_operations import extract_patient_resource_from_item -from unittest.mock import patch, MagicMock -from exceptions.id_sync_exception import IdSyncException import ieds_db_operations +from exceptions.id_sync_exception import IdSyncException +from ieds_db_operations import extract_patient_resource_from_item class TestExtractPatientResourceFromItem(unittest.TestCase): - def test_extract_from_dict_with_contained_patient(self): item = { "Resource": { @@ -67,7 +66,6 @@ def tearDown(self): class TestGetIedsTable(TestIedsDbOperations): - def setUp(self): """Set up test fixtures""" super().setUp() @@ -302,7 +300,6 @@ def test_get_ieds_table_exception_handling(self): class TestUpdatePatientIdInIEDS(TestIedsDbOperations): - def setUp(self): super().setUp() # Mock get_ieds_table() and subsequent calls @@ -541,7 +538,6 @@ def test_ieds_update_patient_id_special_characters(self): class TestGetItemsToUpdate(TestIedsDbOperations): - def setUp(self): super().setUp() # Mock get_ieds_table() diff --git a/lambdas/id_sync/tests/test_os_vars.py b/lambdas/id_sync/tests/test_os_vars.py index 8796b3044..f06d7fb47 100644 --- a/lambdas/id_sync/tests/test_os_vars.py +++ b/lambdas/id_sync/tests/test_os_vars.py @@ -1,12 +1,11 @@ -import unittest import os +import unittest from unittest.mock import patch import os_vars class TestOsVars(unittest.TestCase): - def setUp(self): os_vars._ieds_table_name = None os_vars._delta_table_name = None diff --git a/lambdas/id_sync/tests/test_pds_details.py b/lambdas/id_sync/tests/test_pds_details.py index f490e9b26..a5f159588 100644 --- a/lambdas/id_sync/tests/test_pds_details.py +++ b/lambdas/id_sync/tests/test_pds_details.py @@ -1,11 +1,11 @@ import unittest -from unittest.mock import patch, MagicMock -from pds_details import pds_get_patient_details, pds_get_patient_id +from unittest.mock import MagicMock, patch + from exceptions.id_sync_exception import IdSyncException +from pds_details import pds_get_patient_details, pds_get_patient_id class TestGetPdsPatientDetails(unittest.TestCase): - def setUp(self): """Set up test fixtures and mocks""" self.test_patient_id = "9912003888" diff --git a/lambdas/id_sync/tests/test_record_processor.py b/lambdas/id_sync/tests/test_record_processor.py index 19e6e0715..d0e24daa0 100644 --- a/lambdas/id_sync/tests/test_record_processor.py +++ b/lambdas/id_sync/tests/test_record_processor.py @@ -1,10 +1,10 @@ import unittest from unittest.mock import patch + from record_processor import process_record class TestRecordProcessor(unittest.TestCase): - def setUp(self): """Set up test fixtures and mocks""" # Patch logger diff --git a/lambdas/mns_subscription/src/mns_service.py b/lambdas/mns_subscription/src/mns_service.py index cf8e4d7d5..7a6eee6bf 100644 --- a/lambdas/mns_subscription/src/mns_service.py +++ b/lambdas/mns_subscription/src/mns_service.py @@ -1,17 +1,18 @@ -import requests +import json +import logging import os import uuid -import logging -import json + +import requests from common.authentication import AppRestrictedAuth from common.models.errors import ( - UnhandledResponseError, + BadRequestError, + ConflictError, ResourceNotFoundError, - UnauthorizedError, ServerError, - BadRequestError, TokenValidationError, - ConflictError, + UnauthorizedError, + UnhandledResponseError, ) SQS_ARN = os.getenv("SQS_ARN") @@ -48,7 +49,6 @@ def __init__(self, authenticator: AppRestrictedAuth): logging.info(f"Using SQS ARN for subscription: {SQS_ARN}") def subscribe_notification(self) -> dict | None: - response = requests.post( MNS_URL, headers=self.request_headers, diff --git a/lambdas/mns_subscription/src/mns_setup.py b/lambdas/mns_subscription/src/mns_setup.py index 11012096a..ea39e3642 100644 --- a/lambdas/mns_subscription/src/mns_setup.py +++ b/lambdas/mns_subscription/src/mns_setup.py @@ -1,5 +1,6 @@ -import boto3 import logging + +import boto3 from botocore.config import Config from common.authentication import AppRestrictedAuth, Service from common.cache import Cache diff --git a/lambdas/mns_subscription/src/subscribe_mns.py b/lambdas/mns_subscription/src/subscribe_mns.py index 64340769a..78539d044 100644 --- a/lambdas/mns_subscription/src/subscribe_mns.py +++ b/lambdas/mns_subscription/src/subscribe_mns.py @@ -1,4 +1,5 @@ import logging + from mns_setup import get_mns_service diff --git a/lambdas/mns_subscription/src/unsubscribe_mns.py b/lambdas/mns_subscription/src/unsubscribe_mns.py index 789a0c5c0..b934ccff3 100644 --- a/lambdas/mns_subscription/src/unsubscribe_mns.py +++ b/lambdas/mns_subscription/src/unsubscribe_mns.py @@ -1,4 +1,5 @@ import logging + from mns_setup import get_mns_service diff --git a/lambdas/mns_subscription/tests/test_mns_service.py b/lambdas/mns_subscription/tests/test_mns_service.py index f90d5375d..a9fe6d998 100644 --- a/lambdas/mns_subscription/tests/test_mns_service.py +++ b/lambdas/mns_subscription/tests/test_mns_service.py @@ -1,17 +1,17 @@ -import unittest import os -from unittest.mock import patch, MagicMock, Mock, create_autospec -from mns_service import MnsService, MNS_URL +import unittest +from unittest.mock import MagicMock, Mock, create_autospec, patch + from common.authentication import AppRestrictedAuth from common.models.errors import ( + BadRequestError, + ResourceNotFoundError, ServerError, - UnhandledResponseError, TokenValidationError, - BadRequestError, UnauthorizedError, - ResourceNotFoundError, + UnhandledResponseError, ) - +from mns_service import MNS_URL, MnsService SQS_ARN = "arn:aws:sqs:eu-west-2:123456789012:my-queue" @@ -29,7 +29,6 @@ def setUp(self): @patch("mns_service.requests.post") @patch("mns_service.requests.get") def test_successful_subscription(self, mock_get, mock_post): - # Arrange GET to return no subscription found mock_get_response = MagicMock() mock_get_response.status_code = 200 diff --git a/lambdas/mns_subscription/tests/test_mns_setup.py b/lambdas/mns_subscription/tests/test_mns_setup.py index 9616d5232..53aa67941 100644 --- a/lambdas/mns_subscription/tests/test_mns_setup.py +++ b/lambdas/mns_subscription/tests/test_mns_setup.py @@ -1,10 +1,10 @@ import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch + from mns_setup import get_mns_service class TestGetMnsService(unittest.TestCase): - @patch("mns_setup.boto3.client") @patch("mns_setup.AppRestrictedAuth") @patch("mns_setup.MnsService") diff --git a/lambdas/mns_subscription/tests/test_subscribe_mns.py b/lambdas/mns_subscription/tests/test_subscribe_mns.py index ea3dcad41..f62c56560 100644 --- a/lambdas/mns_subscription/tests/test_subscribe_mns.py +++ b/lambdas/mns_subscription/tests/test_subscribe_mns.py @@ -1,10 +1,10 @@ import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch + from subscribe_mns import run_subscription class TestRunSubscription(unittest.TestCase): - @patch("subscribe_mns.get_mns_service") # patch where it's imported/used! def test_run_subscription_success(self, mock_get_mns_service): mock_mns_instance = MagicMock() diff --git a/lambdas/mns_subscription/tests/test_unsubscribe_mns.py b/lambdas/mns_subscription/tests/test_unsubscribe_mns.py index 344ffb77b..aa568d998 100644 --- a/lambdas/mns_subscription/tests/test_unsubscribe_mns.py +++ b/lambdas/mns_subscription/tests/test_unsubscribe_mns.py @@ -1,10 +1,10 @@ import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch + from unsubscribe_mns import run_unsubscribe class TestRunUnsubscribe(unittest.TestCase): - @patch("unsubscribe_mns.get_mns_service") def test_run_unsubscribe_success(self, mock_get_mns_service): # Arrange diff --git a/lambdas/redis_sync/src/record_processor.py b/lambdas/redis_sync/src/record_processor.py index e5d732eb2..0daff29f1 100644 --- a/lambdas/redis_sync/src/record_processor.py +++ b/lambdas/redis_sync/src/record_processor.py @@ -1,6 +1,6 @@ -from redis_cacher import RedisCacher from common.clients import logger from common.s3_event import S3EventRecord +from redis_cacher import RedisCacher """ Record Processor diff --git a/lambdas/redis_sync/src/redis_cacher.py b/lambdas/redis_sync/src/redis_cacher.py index aba419e79..45d0a73a3 100644 --- a/lambdas/redis_sync/src/redis_cacher.py +++ b/lambdas/redis_sync/src/redis_cacher.py @@ -1,10 +1,11 @@ "Upload the content from a config file in S3 to ElastiCache (Redis)" import json -from transform_map import transform_map + from common.clients import logger from common.redis_client import get_redis_client from common.s3_reader import S3Reader +from transform_map import transform_map class RedisCacher: diff --git a/lambdas/redis_sync/src/redis_sync.py b/lambdas/redis_sync/src/redis_sync.py index fc2a11da1..710fc144b 100644 --- a/lambdas/redis_sync/src/redis_sync.py +++ b/lambdas/redis_sync/src/redis_sync.py @@ -1,9 +1,9 @@ -from event_read import read_event -from record_processor import process_record from common.clients import STREAM_NAME, logger from common.log_decorator import logging_decorator from common.redis_client import get_redis_client from common.s3_event import S3Event +from event_read import read_event +from record_processor import process_record """ Event Processor @@ -38,7 +38,6 @@ def _process_all_records(s3_records: list) -> dict: @logging_decorator(prefix="redis_sync", stream_name=STREAM_NAME) def handler(event, _): - try: no_records = "No records found in event" # check if the event requires a read, ie {"read": "my-hashmap"} diff --git a/lambdas/redis_sync/src/transform_map.py b/lambdas/redis_sync/src/transform_map.py index 578ae0cf1..b3ee88f8e 100644 --- a/lambdas/redis_sync/src/transform_map.py +++ b/lambdas/redis_sync/src/transform_map.py @@ -1,10 +1,10 @@ +from common.clients import logger from constants import RedisCacheKey from transform_configs import ( - transform_vaccine_map, transform_supplier_permissions, + transform_vaccine_map, transform_validation_rules, ) -from common.clients import logger """ Transform config file to format required in REDIS cache. diff --git a/lambdas/redis_sync/tests/test_event_read.py b/lambdas/redis_sync/tests/test_event_read.py index 0537471c6..db48d0664 100644 --- a/lambdas/redis_sync/tests/test_event_read.py +++ b/lambdas/redis_sync/tests/test_event_read.py @@ -1,5 +1,6 @@ import unittest from unittest.mock import Mock + from event_read import read_event diff --git a/lambdas/redis_sync/tests/test_handler.py b/lambdas/redis_sync/tests/test_handler.py index 31b995eae..e858ba262 100644 --- a/lambdas/redis_sync/tests/test_handler.py +++ b/lambdas/redis_sync/tests/test_handler.py @@ -1,9 +1,11 @@ """unit tests for redis_sync.py""" -import unittest import importlib +import unittest from unittest.mock import patch + from constants import RedisCacheKey + import redis_sync diff --git a/lambdas/redis_sync/tests/test_handler_decorator.py b/lambdas/redis_sync/tests/test_handler_decorator.py index ef2484ac2..7dd44698e 100644 --- a/lambdas/redis_sync/tests/test_handler_decorator.py +++ b/lambdas/redis_sync/tests/test_handler_decorator.py @@ -1,11 +1,13 @@ """unit tests for redis_sync.py""" -import unittest import json +import unittest from unittest.mock import patch -from redis_sync import handler -from constants import RedisCacheKey + from common.s3_event import S3EventRecord +from constants import RedisCacheKey + +from redis_sync import handler class TestHandlerDecorator(unittest.TestCase): diff --git a/lambdas/redis_sync/tests/test_record_processor.py b/lambdas/redis_sync/tests/test_record_processor.py index 6a3c6f339..43a64fad8 100644 --- a/lambdas/redis_sync/tests/test_record_processor.py +++ b/lambdas/redis_sync/tests/test_record_processor.py @@ -1,9 +1,9 @@ -from record_processor import process_record import unittest from unittest.mock import patch -from constants import RedisCacheKey from common.s3_event import S3EventRecord +from constants import RedisCacheKey +from record_processor import process_record class TestRecordProcessor(unittest.TestCase): diff --git a/lambdas/redis_sync/tests/test_redis_cacher.py b/lambdas/redis_sync/tests/test_redis_cacher.py index afdb158cb..5adf1a94f 100644 --- a/lambdas/redis_sync/tests/test_redis_cacher.py +++ b/lambdas/redis_sync/tests/test_redis_cacher.py @@ -1,10 +1,10 @@ import unittest from unittest.mock import patch + from redis_cacher import RedisCacher class TestRedisCacher(unittest.TestCase): - def setUp(self): self.mock_s3_reader = patch("redis_cacher.S3Reader").start() self.mock_transform_map = patch("redis_cacher.transform_map").start() diff --git a/lambdas/redis_sync/tests/test_transform_config.py b/lambdas/redis_sync/tests/test_transform_config.py index 4aa3b18c7..408dd572d 100644 --- a/lambdas/redis_sync/tests/test_transform_config.py +++ b/lambdas/redis_sync/tests/test_transform_config.py @@ -1,9 +1,10 @@ -import unittest import json +import unittest from unittest.mock import patch + from transform_configs import ( - transform_vaccine_map, transform_supplier_permissions, + transform_vaccine_map, transform_validation_rules, ) diff --git a/lambdas/redis_sync/tests/test_transform_map.py b/lambdas/redis_sync/tests/test_transform_map.py index e0279f301..a3e2a3973 100644 --- a/lambdas/redis_sync/tests/test_transform_map.py +++ b/lambdas/redis_sync/tests/test_transform_map.py @@ -1,7 +1,8 @@ import unittest from unittest.mock import patch -from transform_map import transform_map + from constants import RedisCacheKey +from transform_map import transform_map class TestTransformMap(unittest.TestCase): diff --git a/lambdas/shared/src/common/authentication.py b/lambdas/shared/src/common/authentication.py index d9cb75284..16b900439 100644 --- a/lambdas/shared/src/common/authentication.py +++ b/lambdas/shared/src/common/authentication.py @@ -1,15 +1,16 @@ import base64 import json -import jwt -import requests import time import uuid from enum import Enum -from .cache import Cache +import jwt +import requests from common.clients import logger from common.models.errors import UnhandledResponseError +from .cache import Cache + class Service(Enum): PDS = "pds" diff --git a/lambdas/shared/src/common/aws_lambda_event.py b/lambdas/shared/src/common/aws_lambda_event.py index 69eb0dbe1..b73c898c6 100644 --- a/lambdas/shared/src/common/aws_lambda_event.py +++ b/lambdas/shared/src/common/aws_lambda_event.py @@ -1,5 +1,5 @@ -from typing import Dict, Any from enum import Enum +from typing import Any, Dict class AwsEventType(Enum): @@ -10,7 +10,6 @@ class AwsEventType(Enum): class AwsLambdaEvent: - def __init__(self, event: Dict[str, Any]): self.event_source = None self.event_type = AwsEventType.UNKNOWN diff --git a/lambdas/shared/src/common/clients.py b/lambdas/shared/src/common/clients.py index e6a2bde62..de54dbd3d 100644 --- a/lambdas/shared/src/common/clients.py +++ b/lambdas/shared/src/common/clients.py @@ -1,6 +1,8 @@ -import os import logging -from boto3 import client as boto3_client, resource as boto3_resource +import os + +from boto3 import client as boto3_client +from boto3 import resource as boto3_resource logging.basicConfig(level=logging.INFO) logger = logging.getLogger() diff --git a/lambdas/shared/src/common/log_decorator.py b/lambdas/shared/src/common/log_decorator.py index 725f597e0..63c81610b 100644 --- a/lambdas/shared/src/common/log_decorator.py +++ b/lambdas/shared/src/common/log_decorator.py @@ -8,7 +8,8 @@ import time from datetime import datetime from functools import wraps -from common.clients import logger, firehose_client + +from common.clients import firehose_client, logger def send_log_to_firehose(stream_name, log_data: dict) -> None: diff --git a/lambdas/shared/src/common/pds_service.py b/lambdas/shared/src/common/pds_service.py index 6bdeeaa38..78c6d0a2c 100644 --- a/lambdas/shared/src/common/pds_service.py +++ b/lambdas/shared/src/common/pds_service.py @@ -1,6 +1,6 @@ -import requests import uuid +import requests from common.authentication import AppRestrictedAuth from common.clients import logger from common.models.errors import UnhandledResponseError diff --git a/lambdas/shared/src/common/redis_client.py b/lambdas/shared/src/common/redis_client.py index da530b192..87ae876f0 100644 --- a/lambdas/shared/src/common/redis_client.py +++ b/lambdas/shared/src/common/redis_client.py @@ -1,4 +1,5 @@ import os + import redis from common.clients import logger diff --git a/lambdas/shared/src/common/s3_reader.py b/lambdas/shared/src/common/s3_reader.py index 28cd00e97..6b0505b91 100644 --- a/lambdas/shared/src/common/s3_reader.py +++ b/lambdas/shared/src/common/s3_reader.py @@ -1,4 +1,4 @@ -from common.clients import s3_client, logger +from common.clients import logger, s3_client class S3Reader: diff --git a/lambdas/shared/tests/test_common/test_authentication.py b/lambdas/shared/tests/test_common/test_authentication.py index 728601e3e..44c956d24 100644 --- a/lambdas/shared/tests/test_common/test_authentication.py +++ b/lambdas/shared/tests/test_common/test_authentication.py @@ -1,13 +1,13 @@ import base64 import json -import responses import time import unittest -from responses import matchers -from unittest.mock import MagicMock, patch, ANY +from unittest.mock import ANY, MagicMock, patch +import responses from common.authentication import AppRestrictedAuth, Service from common.models.errors import UnhandledResponseError +from responses import matchers class TestAuthenticator(unittest.TestCase): diff --git a/lambdas/shared/tests/test_common/test_aws_dynamodb.py b/lambdas/shared/tests/test_common/test_aws_dynamodb.py index 7575d9156..b4a025bb5 100644 --- a/lambdas/shared/tests/test_common/test_aws_dynamodb.py +++ b/lambdas/shared/tests/test_common/test_aws_dynamodb.py @@ -1,10 +1,10 @@ import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch + from common.aws_dynamodb import get_dynamodb_table class TestGetIedsTable(unittest.TestCase): - AWS_REGION = "eu-west-2" # Add this missing constant def setUp(self): diff --git a/lambdas/shared/tests/test_common/test_aws_lambda_event.py b/lambdas/shared/tests/test_common/test_aws_lambda_event.py index 3c1f73142..3f4ac8787 100644 --- a/lambdas/shared/tests/test_common/test_aws_lambda_event.py +++ b/lambdas/shared/tests/test_common/test_aws_lambda_event.py @@ -1,9 +1,9 @@ import unittest -from common.aws_lambda_event import AwsLambdaEvent, AwsEventType +from common.aws_lambda_event import AwsEventType, AwsLambdaEvent -class TestAwsLambdaEvent(unittest.TestCase): +class TestAwsLambdaEvent(unittest.TestCase): def setUp(self): """Set up test fixtures""" self.sqs_record_dict = { diff --git a/lambdas/shared/tests/test_common/test_clients.py b/lambdas/shared/tests/test_common/test_clients.py index 561e9c9d6..b6944af45 100644 --- a/lambdas/shared/tests/test_common/test_clients.py +++ b/lambdas/shared/tests/test_common/test_clients.py @@ -1,7 +1,8 @@ -import unittest -from unittest.mock import patch, MagicMock -import logging import importlib +import logging +import unittest +from unittest.mock import MagicMock, patch + import common.clients as clients diff --git a/lambdas/shared/tests/test_common/test_errors.py b/lambdas/shared/tests/test_common/test_errors.py index aae4d66e5..2c1bda8e3 100644 --- a/lambdas/shared/tests/test_common/test_errors.py +++ b/lambdas/shared/tests/test_common/test_errors.py @@ -1,10 +1,10 @@ import unittest from unittest.mock import patch + import src.common.models.errors as errors class TestErrors(unittest.TestCase): - def setUp(self): TEST_UUID = "01234567-89ab-cdef-0123-4567890abcde" # Patch uuid4 diff --git a/lambdas/shared/tests/test_common/test_log_decorator.py b/lambdas/shared/tests/test_common/test_log_decorator.py index 5731762bb..cdcc613a9 100644 --- a/lambdas/shared/tests/test_common/test_log_decorator.py +++ b/lambdas/shared/tests/test_common/test_log_decorator.py @@ -1,17 +1,16 @@ -import unittest -from unittest.mock import patch import json +import unittest from datetime import datetime +from unittest.mock import patch from common.log_decorator import ( - logging_decorator, generate_and_send_logs, + logging_decorator, send_log_to_firehose, ) class TestLogDecorator(unittest.TestCase): - def setUp(self): self.test_stream = "test-stream" self.test_prefix = "test" diff --git a/lambdas/shared/tests/test_common/test_pds_service.py b/lambdas/shared/tests/test_common/test_pds_service.py index 0cdb11138..ebe22063c 100644 --- a/lambdas/shared/tests/test_common/test_pds_service.py +++ b/lambdas/shared/tests/test_common/test_pds_service.py @@ -1,11 +1,11 @@ -import responses import unittest -from responses import matchers from unittest.mock import create_autospec +import responses from common.authentication import AppRestrictedAuth from common.models.errors import UnhandledResponseError from common.pds_service import PdsService +from responses import matchers class TestPdsService(unittest.TestCase): diff --git a/lambdas/shared/tests/test_common/test_redis_client.py b/lambdas/shared/tests/test_common/test_redis_client.py index d965541d2..0ac13e3f8 100644 --- a/lambdas/shared/tests/test_common/test_redis_client.py +++ b/lambdas/shared/tests/test_common/test_redis_client.py @@ -1,11 +1,11 @@ +import importlib import unittest from unittest.mock import patch + import common.redis_client as redis_client -import importlib class TestRedisClient(unittest.TestCase): - REDIS_HOST = "mock-redis-host" REDIS_PORT = 6379 diff --git a/lambdas/shared/tests/test_common/test_s3_event.py b/lambdas/shared/tests/test_common/test_s3_event.py index 302746513..f11cd7901 100644 --- a/lambdas/shared/tests/test_common/test_s3_event.py +++ b/lambdas/shared/tests/test_common/test_s3_event.py @@ -1,10 +1,10 @@ import unittest + from common.aws_lambda_event import AwsEventType from common.s3_event import S3Event class TestS3Event(unittest.TestCase): - def setUp(self): """Set up test fixtures""" self.s3_record_dict = { diff --git a/lambdas/shared/tests/test_common/test_s3_reader.py b/lambdas/shared/tests/test_common/test_s3_reader.py index 4be69a2c7..f56cae4bc 100644 --- a/lambdas/shared/tests/test_common/test_s3_reader.py +++ b/lambdas/shared/tests/test_common/test_s3_reader.py @@ -1,5 +1,6 @@ import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch + from common.s3_reader import S3Reader diff --git a/package.json b/package.json index 3ad4849d1..a0fcf2877 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "lint-staged": { "*": "prettier --ignore-unknown --write", "*.py": [ - "poetry -P quality_checks run flake8", - "poetry -P quality_checks run black -l 121" + "poetry -P quality_checks run ruff check", + "poetry -P quality_checks run ruff format" ], "*.tf": "terraform fmt", "immunisation-fhir-api.{yaml,json}": "redocly lint --skip-rule=security-defined" diff --git a/quality_checks/.flake8 b/quality_checks/.flake8 deleted file mode 100644 index 7c61ead7c..000000000 --- a/quality_checks/.flake8 +++ /dev/null @@ -1,16 +0,0 @@ -[flake8] -max-line-length = 121 - -# TODO - add flake8-bugbear and switch to the following config? -# extend-select = B950 -# extend-ignore = E203,E501,E701 -extend-ignore = E203,E701 - -exclude = - .git, - __pycache__, - dist, - .venv, - node_modules, - .terraform, - tests, # TODO - we really should be linting tests as well but they're full of line too long errors diff --git a/quality_checks/Makefile b/quality_checks/Makefile index 8f144bddd..28a9a4124 100644 --- a/quality_checks/Makefile +++ b/quality_checks/Makefile @@ -1,8 +1,8 @@ lint: - poetry run flake8 .. + poetry run ruff check .. format: - poetry run black -l 121 .. + poetry run ruff format .. format-check: - poetry run black -l 121 --check .. + poetry run ruff format --check .. diff --git a/quality_checks/poetry.lock b/quality_checks/poetry.lock index 43185f0e3..0d0ccc461 100644 --- a/quality_checks/poetry.lock +++ b/quality_checks/poetry.lock @@ -1,201 +1,35 @@ # This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. [[package]] -name = "black" -version = "25.9.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "black-25.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ce41ed2614b706fd55fd0b4a6909d06b5bab344ffbfadc6ef34ae50adba3d4f7"}, - {file = "black-25.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ab0ce111ef026790e9b13bd216fa7bc48edd934ffc4cbf78808b235793cbc92"}, - {file = "black-25.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f96b6726d690c96c60ba682955199f8c39abc1ae0c3a494a9c62c0184049a713"}, - {file = "black-25.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:d119957b37cc641596063cd7db2656c5be3752ac17877017b2ffcdb9dfc4d2b1"}, - {file = "black-25.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa"}, - {file = "black-25.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d"}, - {file = "black-25.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608"}, - {file = "black-25.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f"}, - {file = "black-25.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0"}, - {file = "black-25.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4"}, - {file = "black-25.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e"}, - {file = "black-25.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a"}, - {file = "black-25.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0172a012f725b792c358d57fe7b6b6e8e67375dd157f64fa7a3097b3ed3e2175"}, - {file = "black-25.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3bec74ee60f8dfef564b573a96b8930f7b6a538e846123d5ad77ba14a8d7a64f"}, - {file = "black-25.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b756fc75871cb1bcac5499552d771822fd9db5a2bb8db2a7247936ca48f39831"}, - {file = "black-25.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:846d58e3ce7879ec1ffe816bb9df6d006cd9590515ed5d17db14e17666b2b357"}, - {file = "black-25.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef69351df3c84485a8beb6f7b8f9721e2009e20ef80a8d619e2d1788b7816d47"}, - {file = "black-25.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e3c1f4cd5e93842774d9ee4ef6cd8d17790e65f44f7cdbaab5f2cf8ccf22a823"}, - {file = "black-25.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:154b06d618233fe468236ba1f0e40823d4eb08b26f5e9261526fde34916b9140"}, - {file = "black-25.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:e593466de7b998374ea2585a471ba90553283fb9beefcfa430d84a2651ed5933"}, - {file = "black-25.9.0-py3-none-any.whl", hash = "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae"}, - {file = "black-25.9.0.tar.gz", hash = "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -pytokens = ">=0.1.10" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "click" -version = "8.3.0" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"}, - {file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "flake8" -version = "7.3.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e"}, - {file = "flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872"}, +name = "ruff" +version = "0.14.0" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "ruff-0.14.0-py3-none-linux_armv6l.whl", hash = "sha256:58e15bffa7054299becf4bab8a1187062c6f8cafbe9f6e39e0d5aface455d6b3"}, + {file = "ruff-0.14.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:838d1b065f4df676b7c9957992f2304e41ead7a50a568185efd404297d5701e8"}, + {file = "ruff-0.14.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:703799d059ba50f745605b04638fa7e9682cc3da084b2092feee63500ff3d9b8"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ba9a8925e90f861502f7d974cc60e18ca29c72bb0ee8bfeabb6ade35a3abde7"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e41f785498bd200ffc276eb9e1570c019c1d907b07cfb081092c8ad51975bbe7"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30a58c087aef4584c193aebf2700f0fbcfc1e77b89c7385e3139956fa90434e2"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f8d07350bc7af0a5ce8812b7d5c1a7293cf02476752f23fdfc500d24b79b783c"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eec3bbbf3a7d5482b5c1f42d5fc972774d71d107d447919fca620b0be3e3b75e"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16b68e183a0e28e5c176d51004aaa40559e8f90065a10a559176713fcf435206"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb732d17db2e945cfcbbc52af0143eda1da36ca8ae25083dd4f66f1542fdf82e"}, + {file = "ruff-0.14.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c958f66ab884b7873e72df38dcabee03d556a8f2ee1b8538ee1c2bbd619883dd"}, + {file = "ruff-0.14.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7eb0499a2e01f6e0c285afc5bac43ab380cbfc17cd43a2e1dd10ec97d6f2c42d"}, + {file = "ruff-0.14.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4c63b2d99fafa05efca0ab198fd48fa6030d57e4423df3f18e03aa62518c565f"}, + {file = "ruff-0.14.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:668fce701b7a222f3f5327f86909db2bbe99c30877c8001ff934c5413812ac02"}, + {file = "ruff-0.14.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a86bf575e05cb68dcb34e4c7dfe1064d44d3f0c04bbc0491949092192b515296"}, + {file = "ruff-0.14.0-py3-none-win32.whl", hash = "sha256:7450a243d7125d1c032cb4b93d9625dea46c8c42b4f06c6b709baac168e10543"}, + {file = "ruff-0.14.0-py3-none-win_amd64.whl", hash = "sha256:ea95da28cd874c4d9c922b39381cbd69cb7e7b49c21b8152b014bd4f52acddc2"}, + {file = "ruff-0.14.0-py3-none-win_arm64.whl", hash = "sha256:f42c9495f5c13ff841b1da4cb3c2a42075409592825dada7c5885c2c844ac730"}, + {file = "ruff-0.14.0.tar.gz", hash = "sha256:62ec8969b7510f77945df916de15da55311fade8d6050995ff7f680afe582c57"}, ] -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.14.0,<2.15.0" -pyflakes = ">=3.4.0,<3.5.0" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.4.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, - {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pycodestyle" -version = "2.14.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d"}, - {file = "pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783"}, -] - -[[package]] -name = "pyflakes" -version = "3.4.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f"}, - {file = "pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58"}, -] - -[[package]] -name = "pytokens" -version = "0.1.10" -description = "A Fast, spec compliant Python 3.12+ tokenizer that runs on older Pythons." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pytokens-0.1.10-py3-none-any.whl", hash = "sha256:db7b72284e480e69fb085d9f251f66b3d2df8b7166059261258ff35f50fb711b"}, - {file = "pytokens-0.1.10.tar.gz", hash = "sha256:c9a4bfa0be1d26aebce03e6884ba454e842f186a59ea43a6d3b25af58223c044"}, -] - -[package.extras] -dev = ["black", "build", "mypy", "pytest", "pytest-cov", "setuptools", "tox", "twine", "wheel"] - [metadata] lock-version = "2.1" python-versions = ">=3.11" -content-hash = "70c45a4fa3975c3574bbf014931571fa196ed9f09d3da9bce3fbe086d6db048f" +content-hash = "0fd5cb0b1adfe11fa1a428906fa7f1aa06a0a24b694d4e35d51086b8ca30b97d" diff --git a/quality_checks/pyproject.toml b/quality_checks/pyproject.toml index ce53a3710..5ad8c23d2 100644 --- a/quality_checks/pyproject.toml +++ b/quality_checks/pyproject.toml @@ -8,11 +8,9 @@ authors = [ readme = "README.md" requires-python = ">=3.11" dependencies = [ - "flake8 (>=7.3.0,<8.0.0)", - "black (>=25.9.0,<26.0.0)", + "ruff (>=0.14.0,<0.15.0)", ] - [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api" diff --git a/recordprocessor/src/audit_table.py b/recordprocessor/src/audit_table.py index b31c72254..2352dda14 100644 --- a/recordprocessor/src/audit_table.py +++ b/recordprocessor/src/audit_table.py @@ -3,8 +3,8 @@ from typing import Optional from clients import dynamodb_client, logger -from errors import UnhandledAuditTableError from constants import AUDIT_TABLE_NAME, AuditTableKeys +from errors import UnhandledAuditTableError def update_audit_table_status(file_key: str, message_id: str, status: str, error_details: Optional[str] = None) -> None: diff --git a/recordprocessor/src/batch_processor.py b/recordprocessor/src/batch_processor.py index fccd9d0bc..048292c27 100644 --- a/recordprocessor/src/batch_processor.py +++ b/recordprocessor/src/batch_processor.py @@ -5,22 +5,22 @@ import time from csv import DictReader from json import JSONDecodeError +from typing import Optional +from audit_table import update_audit_table_status +from clients import logger from constants import ( - FileStatus, - FileNotProcessedReason, - SOURCE_BUCKET_NAME, ARCHIVE_DIR_NAME, PROCESSING_DIR_NAME, + SOURCE_BUCKET_NAME, + FileNotProcessedReason, + FileStatus, ) -from process_row import process_row +from file_level_validation import file_is_empty, file_level_validation, move_file from mappings import map_target_disease -from audit_table import update_audit_table_status +from process_row import process_row from send_to_kinesis import send_to_kinesis -from clients import logger -from file_level_validation import file_level_validation, file_is_empty, move_file from utils_for_recordprocessor import get_csv_content_dict_reader -from typing import Optional def process_csv_to_fhir(incoming_message_body: dict) -> int: @@ -125,9 +125,9 @@ def process_rows( logger.info("MESSAGE ID : %s", row_id) # Log progress every 1000 rows and the first 10 rows after a restart if total_rows_processed_count % 1000 == 0: - logger.info(f"Process: {total_rows_processed_count+1}") + logger.info(f"Process: {total_rows_processed_count + 1}") if start_row > 0 and row_count <= start_row + 10: - logger.info(f"Restarted Process (log up to first 10): {total_rows_processed_count+1}") + logger.info(f"Restarted Process (log up to first 10): {total_rows_processed_count + 1}") # Process the row to obtain the details needed for the message_body and ack file details_from_processing = process_row(target_disease, allowed_operations, row) # Create the message body for sending diff --git a/recordprocessor/src/clients.py b/recordprocessor/src/clients.py index 4628d36e0..79f7b494b 100644 --- a/recordprocessor/src/clients.py +++ b/recordprocessor/src/clients.py @@ -4,7 +4,8 @@ import os import redis -from boto3 import client as boto3_client, resource as boto3_resource +from boto3 import client as boto3_client +from boto3 import resource as boto3_resource from botocore.config import Config REGION_NAME = "eu-west-2" diff --git a/recordprocessor/src/convert_to_fhir_imms_resource.py b/recordprocessor/src/convert_to_fhir_imms_resource.py index 08ef17624..0731c3562 100644 --- a/recordprocessor/src/convert_to_fhir_imms_resource.py +++ b/recordprocessor/src/convert_to_fhir_imms_resource.py @@ -1,10 +1,9 @@ """Decorators to add the relevant fields to the FHIR immunization resource from the batch stream""" -from typing import List, Callable, Dict +from typing import Callable, Dict, List -from utils_for_fhir_conversion import _is_not_empty, Generate, Add, Convert from constants import Operation, Urls - +from utils_for_fhir_conversion import Add, Convert, Generate, _is_not_empty ImmunizationDecorator = Callable[[Dict, Dict[str, str]], None] """ @@ -43,7 +42,6 @@ def _decorate_patient(imms: dict, row: Dict[str, str]) -> None: # Add patient if there is at least one non-empty patient value if any(_is_not_empty(value) for value in patient_values): - # Set up patient internal_patient_id = "Patient1" imms["patient"] = {"reference": f"#{internal_patient_id}"} @@ -207,7 +205,6 @@ def _decorate_performer(imms: dict, row: Dict[str, str]) -> None: # Add practitioner if there is at least one practitioner value if any(_is_not_empty(value) for value in practitioner_values): - # Set up the practitioner internal_practitioner_id = "Practitioner1" practitioner = { diff --git a/recordprocessor/src/file_level_validation.py b/recordprocessor/src/file_level_validation.py index 1bcf62359..d379354aa 100644 --- a/recordprocessor/src/file_level_validation.py +++ b/recordprocessor/src/file_level_validation.py @@ -5,22 +5,22 @@ from csv import DictReader -from clients import logger, s3_client -from make_and_upload_ack_file import make_and_upload_ack_file -from utils_for_recordprocessor import get_csv_content_dict_reader -from errors import InvalidHeaders, NoOperationPermissions -from logging_decorator import file_level_validation_logging_decorator from audit_table import update_audit_table_status +from clients import logger, s3_client from constants import ( - SOURCE_BUCKET_NAME, + ARCHIVE_DIR_NAME, EXPECTED_CSV_HEADERS, - permission_to_operation_map, + PROCESSING_DIR_NAME, + SOURCE_BUCKET_NAME, + FileNotProcessedReason, FileStatus, Permission, - FileNotProcessedReason, - ARCHIVE_DIR_NAME, - PROCESSING_DIR_NAME, + permission_to_operation_map, ) +from errors import InvalidHeaders, NoOperationPermissions +from logging_decorator import file_level_validation_logging_decorator +from make_and_upload_ack_file import make_and_upload_ack_file +from utils_for_recordprocessor import get_csv_content_dict_reader def validate_content_headers(csv_content_reader: DictReader) -> None: diff --git a/recordprocessor/src/logging_decorator.py b/recordprocessor/src/logging_decorator.py index 4901f4e52..8947be872 100644 --- a/recordprocessor/src/logging_decorator.py +++ b/recordprocessor/src/logging_decorator.py @@ -5,8 +5,9 @@ import time from datetime import datetime from functools import wraps + from clients import firehose_client, logger -from errors import NoOperationPermissions, InvalidHeaders +from errors import InvalidHeaders, NoOperationPermissions STREAM_NAME = os.getenv("SPLUNK_FIREHOSE_NAME", "immunisation-fhir-api-internal-dev-splunk-firehose") diff --git a/recordprocessor/src/make_and_upload_ack_file.py b/recordprocessor/src/make_and_upload_ack_file.py index d71e137d4..68854697f 100644 --- a/recordprocessor/src/make_and_upload_ack_file.py +++ b/recordprocessor/src/make_and_upload_ack_file.py @@ -1,7 +1,8 @@ """Create ack file and upload to S3 bucket""" from csv import writer -from io import StringIO, BytesIO +from io import BytesIO, StringIO + from clients import s3_client from constants import ACK_BUCKET_NAME diff --git a/recordprocessor/src/mappings.py b/recordprocessor/src/mappings.py index c82e6ef4c..7871a0294 100644 --- a/recordprocessor/src/mappings.py +++ b/recordprocessor/src/mappings.py @@ -1,8 +1,9 @@ """Mappings for converting vaccine type into target disease FHIR element""" import json -from constants import Urls + from clients import redis_client +from constants import Urls def map_target_disease(vaccine: str) -> list: diff --git a/recordprocessor/src/models/utils.py b/recordprocessor/src/models/utils.py index 33b1b4397..ddb70163d 100644 --- a/recordprocessor/src/models/utils.py +++ b/recordprocessor/src/models/utils.py @@ -1,7 +1,7 @@ import uuid from dataclasses import dataclass -from typing import Union from enum import Enum +from typing import Union class Severity(str, Enum): diff --git a/recordprocessor/src/process_row.py b/recordprocessor/src/process_row.py index 88dd65902..d9cb52ec4 100644 --- a/recordprocessor/src/process_row.py +++ b/recordprocessor/src/process_row.py @@ -1,8 +1,8 @@ """Function to process a single row of a csv file""" -from convert_to_fhir_imms_resource import convert_to_fhir_imms_resource -from constants import Diagnostics from clients import logger +from constants import Diagnostics +from convert_to_fhir_imms_resource import convert_to_fhir_imms_resource from utils_for_recordprocessor import create_diagnostics_dictionary diff --git a/recordprocessor/src/send_to_kinesis.py b/recordprocessor/src/send_to_kinesis.py index 16419a501..2184d499e 100644 --- a/recordprocessor/src/send_to_kinesis.py +++ b/recordprocessor/src/send_to_kinesis.py @@ -1,6 +1,7 @@ """Function to send the message to kinesis""" import os + import simplejson as json from botocore.exceptions import ClientError from clients import kinesis_client, logger diff --git a/recordprocessor/src/utils_for_fhir_conversion.py b/recordprocessor/src/utils_for_fhir_conversion.py index e25b4418d..8e91ed63a 100644 --- a/recordprocessor/src/utils_for_fhir_conversion.py +++ b/recordprocessor/src/utils_for_fhir_conversion.py @@ -3,6 +3,7 @@ import re from datetime import datetime from decimal import Decimal, InvalidOperation + from constants import Urls diff --git a/recordprocessor/src/utils_for_recordprocessor.py b/recordprocessor/src/utils_for_recordprocessor.py index 1c874d010..b11dee656 100644 --- a/recordprocessor/src/utils_for_recordprocessor.py +++ b/recordprocessor/src/utils_for_recordprocessor.py @@ -3,6 +3,7 @@ import os from csv import DictReader from io import TextIOWrapper + from clients import s3_client diff --git a/recordprocessor/tests/test_audit_table.py b/recordprocessor/tests/test_audit_table.py index 91fd79c44..85e7d5cf7 100644 --- a/recordprocessor/tests/test_audit_table.py +++ b/recordprocessor/tests/test_audit_table.py @@ -3,35 +3,35 @@ import unittest from unittest import TestCase from unittest.mock import patch + from boto3 import client as boto3_client -from moto import mock_dynamodb from errors import UnhandledAuditTableError +from moto import mock_dynamodb -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, -) from tests.utils_for_recordprocessor_tests.generic_setup_and_teardown import ( GenericSetUp, GenericTearDown, ) -from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MockFileDetails, - FileDetails, +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, ) from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( add_entry_to_table, ) +from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + FileDetails, + MockFileDetails, +) # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): + from audit_table import update_audit_table_status + from clients import REGION_NAME from constants import ( AUDIT_TABLE_NAME, FileStatus, ) - from audit_table import update_audit_table_status - from clients import REGION_NAME - dynamodb_client = boto3_client("dynamodb", region_name=REGION_NAME) diff --git a/recordprocessor/tests/test_convert_to_fhir_imms_decorators.py b/recordprocessor/tests/test_convert_to_fhir_imms_decorators.py index a3f12fbb3..4a8bf0e97 100644 --- a/recordprocessor/tests/test_convert_to_fhir_imms_decorators.py +++ b/recordprocessor/tests/test_convert_to_fhir_imms_decorators.py @@ -5,32 +5,32 @@ NOTE: the public function `decorate` is tested in `TestDecorate` class. """ -from decimal import Decimal import copy import unittest +from decimal import Decimal from unittest.mock import patch from tests.utils_for_recordprocessor_tests.decorator_constants import ( + RSV_TARGET_DISEASE_ELEMENT, AllHeaders, AllHeadersExpectedOutput, ExtensionItems, - RSV_TARGET_DISEASE_ELEMENT, -) -from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MockFieldDictionaries, ) from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, ) +from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + MockFieldDictionaries, +) with patch("os.environ", MOCK_ENVIRONMENT_DICT): from constants import Urls from convert_to_fhir_imms_resource import ( + _decorate_immunization, _decorate_patient, + _decorate_performer, _decorate_vaccination, _decorate_vaccine, - _decorate_performer, - _decorate_immunization, ) empty_csv_data = {k: "" for k in MockFieldDictionaries.all_fields} diff --git a/recordprocessor/tests/test_convert_to_fhir_imms_resource.py b/recordprocessor/tests/test_convert_to_fhir_imms_resource.py index 27dd97921..adb1e2c24 100644 --- a/recordprocessor/tests/test_convert_to_fhir_imms_resource.py +++ b/recordprocessor/tests/test_convert_to_fhir_imms_resource.py @@ -1,25 +1,25 @@ """Tests for convert_to_fhir_imms_resource""" import unittest -from typing import Tuple, List +from typing import List, Tuple from unittest.mock import patch +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, +) from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( MockFhirImmsResources, MockFieldDictionaries, TargetDiseaseElements, ) -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, -) with patch("os.environ", MOCK_ENVIRONMENT_DICT): from convert_to_fhir_imms_resource import ( + ImmunizationDecorator, _decorate_immunization, _get_decorators_for_action_flag, all_decorators, convert_to_fhir_imms_resource, - ImmunizationDecorator, ) diff --git a/recordprocessor/tests/test_file_level_validation.py b/recordprocessor/tests/test_file_level_validation.py index b94b6aa07..8a0e807a4 100644 --- a/recordprocessor/tests/test_file_level_validation.py +++ b/recordprocessor/tests/test_file_level_validation.py @@ -5,20 +5,19 @@ # If mock_s3 is not imported here then tests in other files fail when running 'make test'. It is not clear why this is. from moto import mock_s3 # noqa: F401 + from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( convert_string_to_dict_reader, ) from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + MOCK_ENVIRONMENT_DICT, MockFileDetails, ValidMockFileContent, ) -from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MOCK_ENVIRONMENT_DICT, -) with patch("os.environ", MOCK_ENVIRONMENT_DICT): - from errors import NoOperationPermissions, InvalidHeaders - from file_level_validation import validate_content_headers, get_permitted_operations + from errors import InvalidHeaders, NoOperationPermissions + from file_level_validation import get_permitted_operations, validate_content_headers test_file = MockFileDetails.rsv_emis diff --git a/recordprocessor/tests/test_logging_decorator.py b/recordprocessor/tests/test_logging_decorator.py index c8359b230..05831e70e 100644 --- a/recordprocessor/tests/test_logging_decorator.py +++ b/recordprocessor/tests/test_logging_decorator.py @@ -1,29 +1,30 @@ """Tests for the logging_decorator and its helper functions""" +import json import unittest -from unittest.mock import patch from contextlib import ExitStack -from datetime import datetime -import json from copy import deepcopy +from datetime import datetime +from unittest.mock import patch + from boto3 import client as boto3_client -from moto import mock_s3, mock_firehose +from moto import mock_firehose, mock_s3 -from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MockFileDetails, - ValidMockFileContent, -) from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, BucketNames, Firehose, ) +from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + MockFileDetails, + ValidMockFileContent, +) with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): from clients import REGION_NAME from errors import InvalidHeaders, NoOperationPermissions - from logging_decorator import send_log_to_firehose, generate_and_send_logs from file_level_validation import file_level_validation + from logging_decorator import generate_and_send_logs, send_log_to_firehose from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( @@ -203,7 +204,6 @@ def test_splunk_logger_handled_failure(self): expected_error_message, ) in test_cases: with self.subTest(expected_error_message): - s3_client.put_object( Bucket=BucketNames.SOURCE, Key=MOCK_FILE_DETAILS.file_key, diff --git a/recordprocessor/tests/test_make_and_upload_ack_file.py b/recordprocessor/tests/test_make_and_upload_ack_file.py index 60bf80139..2ef45d81f 100644 --- a/recordprocessor/tests/test_make_and_upload_ack_file.py +++ b/recordprocessor/tests/test_make_and_upload_ack_file.py @@ -1,10 +1,12 @@ """Tests for make_and_upload_ack_file functions""" import unittest -from unittest.mock import patch from copy import deepcopy +from unittest.mock import patch + from boto3 import client as boto3_client from moto import mock_s3 + from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, BucketNames, @@ -17,12 +19,12 @@ ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): + from clients import REGION_NAME from make_and_upload_ack_file import ( make_ack_data, - upload_ack_file, make_and_upload_ack_file, + upload_ack_file, ) - from clients import REGION_NAME from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( GenericSetUp, diff --git a/recordprocessor/tests/test_map_target_disease.py b/recordprocessor/tests/test_map_target_disease.py index 5ec0b2aa4..20c353223 100644 --- a/recordprocessor/tests/test_map_target_disease.py +++ b/recordprocessor/tests/test_map_target_disease.py @@ -3,6 +3,7 @@ import json import unittest from unittest.mock import patch + from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, ) diff --git a/recordprocessor/tests/test_process_csv_to_fhir.py b/recordprocessor/tests/test_process_csv_to_fhir.py index 3ab097e67..eadd6d8df 100644 --- a/recordprocessor/tests/test_process_csv_to_fhir.py +++ b/recordprocessor/tests/test_process_csv_to_fhir.py @@ -2,31 +2,32 @@ import json import unittest -from unittest.mock import patch from copy import deepcopy +from unittest.mock import patch + import boto3 -from moto import mock_s3, mock_firehose, mock_dynamodb +from moto import mock_dynamodb, mock_firehose, mock_s3 from tests.utils_for_recordprocessor_tests.generic_setup_and_teardown import ( GenericSetUp, GenericTearDown, ) +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, + BucketNames, +) from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( add_entry_to_table, ) from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + REGION_NAME, MockFileDetails, ValidMockFileContent, - REGION_NAME, -) -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, - BucketNames, ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): - from constants import FileStatus, AUDIT_TABLE_NAME from batch_processor import process_csv_to_fhir + from constants import AUDIT_TABLE_NAME, FileStatus dynamodb_client = boto3.client("dynamodb", region_name=REGION_NAME) s3_client = boto3.client("s3", region_name=REGION_NAME) diff --git a/recordprocessor/tests/test_process_row.py b/recordprocessor/tests/test_process_row.py index d730a2fe3..0cdd7b9fa 100644 --- a/recordprocessor/tests/test_process_row.py +++ b/recordprocessor/tests/test_process_row.py @@ -1,24 +1,23 @@ """Tests for the process_row module""" import unittest -from unittest.mock import patch from copy import deepcopy -from boto3 import client as boto3_client -from moto import mock_s3 from decimal import Decimal +from unittest.mock import patch +from boto3 import client as boto3_client +from moto import mock_s3 -from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MockFieldDictionaries, - TargetDiseaseElements, +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, ) - from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( GenericSetUp, GenericTearDown, ) -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, +from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + MockFieldDictionaries, + TargetDiseaseElements, ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): diff --git a/recordprocessor/tests/test_recordprocessor_edge_cases.py b/recordprocessor/tests/test_recordprocessor_edge_cases.py index 20140e233..7bde32bb1 100644 --- a/recordprocessor/tests/test_recordprocessor_edge_cases.py +++ b/recordprocessor/tests/test_recordprocessor_edge_cases.py @@ -1,15 +1,16 @@ -import unittest import os +import unittest from io import BytesIO from unittest.mock import call, patch + from batch_processor import process_csv_to_fhir + from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( create_patch, ) class TestProcessorEdgeCases(unittest.TestCase): - def setUp(self): self.mock_logger_info = create_patch("logging.Logger.info") self.mock_logger_warning = create_patch("logging.Logger.warning") diff --git a/recordprocessor/tests/test_recordprocessor_main.py b/recordprocessor/tests/test_recordprocessor_main.py index a79e6247e..0221c1634 100644 --- a/recordprocessor/tests/test_recordprocessor_main.py +++ b/recordprocessor/tests/test_recordprocessor_main.py @@ -1,48 +1,47 @@ "Tests for main function for RecordProcessor" -import unittest import json +import unittest +from datetime import datetime, timedelta, timezone from decimal import Decimal from json import JSONDecodeError from unittest.mock import patch -from datetime import datetime, timedelta, timezone -from moto import mock_s3, mock_kinesis, mock_firehose, mock_dynamodb + from boto3 import client as boto3_client +from moto import mock_dynamodb, mock_firehose, mock_kinesis, mock_s3 +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, + BucketNames, + Kinesis, +) from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( GenericSetUp, GenericTearDown, add_entry_to_table, assert_audit_table_entry, + create_patch, ) from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MockFileDetails, + REGION_NAME, FileDetails, - ValidMockFileContent, + InfAckFileRows, MockFhirImmsResources, MockFieldDictionaries, + MockFileDetails, MockLocalIds, - InfAckFileRows, - REGION_NAME, -) -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, - BucketNames, - Kinesis, -) -from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( - create_patch, + ValidMockFileContent, ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): + from batch_processor import main from constants import ( - Diagnostics, - FileStatus, - FileNotProcessedReason, AUDIT_TABLE_NAME, AuditTableKeys, + Diagnostics, + FileNotProcessedReason, + FileStatus, ) - from batch_processor import main s3_client = boto3_client("s3", region_name=REGION_NAME) kinesis_client = boto3_client("kinesis", region_name=REGION_NAME) @@ -149,10 +148,9 @@ def make_kinesis_assertions(self, test_cases): for test_name, index, expected_kinesis_data, expect_success in test_cases: with self.subTest(test_name): - kinesis_record = kinesis_records[index] self.assertEqual(kinesis_record["PartitionKey"], mock_rsv_emis_file.queue_name) - self.assertEqual(kinesis_record["SequenceNumber"], f"{index+1}") + self.assertEqual(kinesis_record["SequenceNumber"], f"{index + 1}") # Ensure that arrival times are sequential approximate_arrival_timestamp = kinesis_record["ApproximateArrivalTimestamp"] @@ -164,7 +162,7 @@ def make_kinesis_assertions(self, test_cases): kinesis_data = json.loads(kinesis_record["Data"].decode("utf-8"), parse_float=Decimal) expected_kinesis_data = { - "row_id": f"{mock_rsv_emis_file.message_id}^{index+1}", + "row_id": f"{mock_rsv_emis_file.message_id}^{index + 1}", "file_key": mock_rsv_emis_file.file_key, "supplier": mock_rsv_emis_file.supplier, "vax_type": mock_rsv_emis_file.vaccine_type, @@ -493,7 +491,6 @@ def test_e2e_empty_file_is_flagged_and_processed_correctly(self): ), ] for description, file_content in test_cases: - with self.subTest(description=description): self.mock_batch_processor_logger.reset_mock() test_file = mock_rsv_emis_file diff --git a/recordprocessor/tests/test_send_to_kinesis.py b/recordprocessor/tests/test_send_to_kinesis.py index d46e471f8..4a6d3deae 100644 --- a/recordprocessor/tests/test_send_to_kinesis.py +++ b/recordprocessor/tests/test_send_to_kinesis.py @@ -1,8 +1,12 @@ import unittest from unittest.mock import patch -from moto import mock_kinesis + from boto3 import client as boto3_client +from moto import mock_kinesis +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, +) from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( GenericSetUp, GenericTearDown, @@ -10,9 +14,6 @@ from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( REGION_NAME, ) -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, -) with patch("os.environ", MOCK_ENVIRONMENT_DICT): from send_to_kinesis import send_to_kinesis @@ -22,7 +23,6 @@ @mock_kinesis class TestSendToKinesis(unittest.TestCase): - def setUp(self) -> None: GenericSetUp(None, None, kinesis_client) @@ -31,7 +31,6 @@ def tearDown(self) -> None: @patch.dict("os.environ", MOCK_ENVIRONMENT_DICT) def test_send_to_kinesis_success(self): - kinesis_client.return_value = {"ResponseMetadata": {"HTTPStatusCode": 200}} # arrange required parameters diff --git a/recordprocessor/tests/test_utils_for_fhir_conversion.py b/recordprocessor/tests/test_utils_for_fhir_conversion.py index 37431673d..7b77b2ad5 100644 --- a/recordprocessor/tests/test_utils_for_fhir_conversion.py +++ b/recordprocessor/tests/test_utils_for_fhir_conversion.py @@ -1,15 +1,16 @@ """Unit tests for batch utils""" import unittest -from unittest.mock import patch from decimal import Decimal +from unittest.mock import patch + from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): from constants import Urls - from utils_for_fhir_conversion import _is_not_empty, Generate, Add, Convert + from utils_for_fhir_conversion import Add, Convert, Generate, _is_not_empty class TestBatchUtils(unittest.TestCase): diff --git a/recordprocessor/tests/test_utils_for_recordprocessor.py b/recordprocessor/tests/test_utils_for_recordprocessor.py index f7d31d8c4..ab3ba099b 100644 --- a/recordprocessor/tests/test_utils_for_recordprocessor.py +++ b/recordprocessor/tests/test_utils_for_recordprocessor.py @@ -1,32 +1,34 @@ """Tests for the utils_for_recordprocessor module""" +import csv import unittest -from unittest.mock import patch from io import StringIO -import csv +from unittest.mock import patch + import boto3 from moto import mock_s3 + +from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, + BucketNames, +) from tests.utils_for_recordprocessor_tests.utils_for_recordprocessor_tests import ( GenericSetUp, GenericTearDown, ) from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + REGION_NAME, MockFileDetails, ValidMockFileContent, - REGION_NAME, -) -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, - BucketNames, ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): + from file_level_validation import move_file from utils_for_recordprocessor import ( - get_environment, - get_csv_content_dict_reader, create_diagnostics_dictionary, + get_csv_content_dict_reader, + get_environment, ) - from file_level_validation import move_file s3_client = boto3.client("s3", region_name=REGION_NAME) test_file = MockFileDetails.rsv_emis diff --git a/recordprocessor/tests/utils_for_recordprocessor_tests/decorator_constants.py b/recordprocessor/tests/utils_for_recordprocessor_tests/decorator_constants.py index 0f15b43f5..eb391411c 100644 --- a/recordprocessor/tests/utils_for_recordprocessor_tests/decorator_constants.py +++ b/recordprocessor/tests/utils_for_recordprocessor_tests/decorator_constants.py @@ -1,13 +1,14 @@ """Constants for use when testing decorators""" -from unittest.mock import patch from decimal import Decimal -from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - TargetDiseaseElements, -) +from unittest.mock import patch + from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, ) +from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( + TargetDiseaseElements, +) with patch("os.environ", MOCK_ENVIRONMENT_DICT): from constants import Urls diff --git a/recordprocessor/tests/utils_for_recordprocessor_tests/generic_setup_and_teardown.py b/recordprocessor/tests/utils_for_recordprocessor_tests/generic_setup_and_teardown.py index cbd03a663..7f5f2c32a 100644 --- a/recordprocessor/tests/utils_for_recordprocessor_tests/generic_setup_and_teardown.py +++ b/recordprocessor/tests/utils_for_recordprocessor_tests/generic_setup_and_teardown.py @@ -3,20 +3,20 @@ from unittest.mock import patch from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - BucketNames, MOCK_ENVIRONMENT_DICT, - Sqs, + BucketNames, Firehose, + Sqs, ) # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): from clients import REGION_NAME from constants import ( - AuditTableKeys, - AUDIT_TABLE_QUEUE_NAME_GSI, AUDIT_TABLE_FILENAME_GSI, AUDIT_TABLE_NAME, + AUDIT_TABLE_QUEUE_NAME_GSI, + AuditTableKeys, ) @@ -120,7 +120,6 @@ def __init__( sqs_client=None, dynamodb_client=None, ): - if s3_client: for bucket_name in [ BucketNames.SOURCE, diff --git a/recordprocessor/tests/utils_for_recordprocessor_tests/utils_for_recordprocessor_tests.py b/recordprocessor/tests/utils_for_recordprocessor_tests/utils_for_recordprocessor_tests.py index d36a7c1e4..8c0bc2776 100644 --- a/recordprocessor/tests/utils_for_recordprocessor_tests/utils_for_recordprocessor_tests.py +++ b/recordprocessor/tests/utils_for_recordprocessor_tests/utils_for_recordprocessor_tests.py @@ -1,32 +1,33 @@ """Utils for the recordprocessor tests""" from io import StringIO +from unittest.mock import patch + +from boto3 import client as boto3_client +from boto3.dynamodb.types import TypeDeserializer + from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( + MOCK_ENVIRONMENT_DICT, BucketNames, Firehose, Kinesis, ) from tests.utils_for_recordprocessor_tests.values_for_recordprocessor_tests import ( - MockFileDetails, FileDetails, -) -from boto3.dynamodb.types import TypeDeserializer -from boto3 import client as boto3_client -from unittest.mock import patch -from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( - MOCK_ENVIRONMENT_DICT, + MockFileDetails, ) # Ensure environment variables are mocked before importing from src files with patch.dict("os.environ", MOCK_ENVIRONMENT_DICT): - from clients import REGION_NAME from csv import DictReader + + from clients import REGION_NAME from constants import ( - AuditTableKeys, - AUDIT_TABLE_NAME, - FileStatus, AUDIT_TABLE_FILENAME_GSI, + AUDIT_TABLE_NAME, AUDIT_TABLE_QUEUE_NAME_GSI, + AuditTableKeys, + FileStatus, ) dynamodb_client = boto3_client("dynamodb", region_name=REGION_NAME) @@ -60,7 +61,6 @@ def __init__( kinesis_client=None, dynamo_db_client=None, ): - if s3_client: for bucket_name in [ BucketNames.SOURCE, @@ -144,7 +144,6 @@ def __init__( kinesis_client=None, dynamo_db_client=None, ): - if s3_client: for bucket_name in [BucketNames.SOURCE, BucketNames.DESTINATION]: for obj in s3_client.list_objects_v2(Bucket=bucket_name).get("Contents", []): diff --git a/recordprocessor/tests/utils_for_recordprocessor_tests/values_for_recordprocessor_tests.py b/recordprocessor/tests/utils_for_recordprocessor_tests/values_for_recordprocessor_tests.py index 365014356..9381babb7 100644 --- a/recordprocessor/tests/utils_for_recordprocessor_tests/values_for_recordprocessor_tests.py +++ b/recordprocessor/tests/utils_for_recordprocessor_tests/values_for_recordprocessor_tests.py @@ -1,14 +1,15 @@ """Values for use in tests""" -from unittest.mock import patch import json from decimal import Decimal +from unittest.mock import patch + from tests.utils_for_recordprocessor_tests.mock_environment_variables import ( MOCK_ENVIRONMENT_DICT, ) with patch("os.environ", MOCK_ENVIRONMENT_DICT): - from constants import Urls, AuditTableKeys + from constants import AuditTableKeys, Urls REGION_NAME = "eu-west-2" diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 000000000..deab3eba9 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,7 @@ +line-length = 121 + +[lint] +# TODO - consider enabling more rulesets, e.g. B, C90, N, RET, S, UP +select = ["E", "F", "I", "W"] +# Recommended exclusions as per the docs, plus E501 line-too-long +ignore = ["E111", "E114", "E117", "E501", "W191"] diff --git a/scripts/calculate_version.py b/scripts/calculate_version.py index 905d7de7c..6fe09935a 100644 --- a/scripts/calculate_version.py +++ b/scripts/calculate_version.py @@ -16,12 +16,12 @@ +startversioning Reset version to v1.0.0-alpha """ -import os.path import itertools +import os.path + import git import semver - SCRIPT_LOCATION = os.path.join(os.path.dirname(os.path.abspath(__file__))) REPO_ROOT = os.path.abspath(os.path.join(SCRIPT_LOCATION, "..")) REPO = git.Repo(REPO_ROOT) diff --git a/scripts/destroy_unused_workspaces.py b/scripts/destroy_unused_workspaces.py index 7a58858d5..b1dc82750 100644 --- a/scripts/destroy_unused_workspaces.py +++ b/scripts/destroy_unused_workspaces.py @@ -1,5 +1,5 @@ -import subprocess import os +import subprocess def execute_terraform_command(command, cwd=None): @@ -59,7 +59,7 @@ def list_pr_workspaces(prefix): def destroy_workspace(workspace_name, project_name, project_short_name): command_select = f"terraform workspace select {workspace_name}" - tf_vars = f"-var=project_name={project_name} " f"-var=project_short_name={project_short_name} " + tf_vars = f"-var=project_name={project_name} -var=project_short_name={project_short_name} " command_destroy = f"terraform destroy {tf_vars} -auto-approve" command_delete = f"terraform workspace select default && terraform workspace delete {workspace_name}" diff --git a/scripts/set_version.py b/scripts/set_version.py index bec5c846b..0009394ee 100644 --- a/scripts/set_version.py +++ b/scripts/set_version.py @@ -5,8 +5,10 @@ Reads an openapi spec on stdin and adds the calculated version to it, then prints it on stdout. """ -import sys + import json +import sys + from calculate_version import calculate_version diff --git a/scripts/yaml2json.py b/scripts/yaml2json.py index 1842fda69..35793175a 100644 --- a/scripts/yaml2json.py +++ b/scripts/yaml2json.py @@ -4,9 +4,11 @@ Takes yaml on stdin and writes json on stdout, converting dates correctly. """ -import sys -import json + import datetime +import json +import sys + import yaml diff --git a/temporary_sandbox/fhir_api/__init__.py b/temporary_sandbox/fhir_api/__init__.py index 875867b54..1de14b85e 100644 --- a/temporary_sandbox/fhir_api/__init__.py +++ b/temporary_sandbox/fhir_api/__init__.py @@ -3,16 +3,16 @@ """ import os + from fastapi import FastAPI +from fhir_api.models.fhir_r4.common import Identifier, Reference from fhir_api.routes import ( - root, dynamodb, + root, status_endpoints, ) -from fhir_api.models.fhir_r4.common import Reference, Identifier - Reference.update_forward_refs(identifier=Identifier) @@ -20,7 +20,7 @@ title=os.getenv("FASTAPI_TITLE", "Immunisation Fhir API"), description=os.getenv("FASTAPI_DESC", "API"), version=os.getenv("VERSION", "DEVELOPMENT"), - root_path=f'/{os.getenv("SERVICE_BASE_PATH")}/', + root_path=f"/{os.getenv('SERVICE_BASE_PATH')}/", docs_url="/documentation", redoc_url="/redocumentation", ) diff --git a/temporary_sandbox/fhir_api/exceptions/base_exceptions.py b/temporary_sandbox/fhir_api/exceptions/base_exceptions.py index b2cf0a4f0..a3620cf37 100644 --- a/temporary_sandbox/fhir_api/exceptions/base_exceptions.py +++ b/temporary_sandbox/fhir_api/exceptions/base_exceptions.py @@ -3,14 +3,16 @@ # pylint: disable=W0231 from typing import Type + import fastapi from fastapi.responses import JSONResponse + from fhir_api.models.errors import ( - NotFoundError, AlreadyExistsError, - WebSocketError, BaseError, BaseIdentifiedError, + NotFoundError, + WebSocketError, ) diff --git a/temporary_sandbox/fhir_api/models/dynamodb/data_input.py b/temporary_sandbox/fhir_api/models/dynamodb/data_input.py index a926ab875..be0188752 100644 --- a/temporary_sandbox/fhir_api/models/dynamodb/data_input.py +++ b/temporary_sandbox/fhir_api/models/dynamodb/data_input.py @@ -1,12 +1,12 @@ """Data input model for DynamoDB""" from typing import Optional + +from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields from pydantic import ( BaseModel, ) -from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields - class DataInput(BaseModel): """Data input model""" diff --git a/temporary_sandbox/fhir_api/models/dynamodb/read_models.py b/temporary_sandbox/fhir_api/models/dynamodb/read_models.py index b34c3557d..1440831ab 100644 --- a/temporary_sandbox/fhir_api/models/dynamodb/read_models.py +++ b/temporary_sandbox/fhir_api/models/dynamodb/read_models.py @@ -1,18 +1,18 @@ """Read Models for Dynamodb""" from typing import ( - Union, Literal, Optional, -) -from pydantic import ( - BaseModel, - Field, + Union, ) from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields from fhir_api.models.fhir_r4.immunization import Immunization from fhir_api.models.fhir_r4.patient import Patient +from pydantic import ( + BaseModel, + Field, +) class Resource(BaseModel): diff --git a/temporary_sandbox/fhir_api/models/dynamodb/update_model.py b/temporary_sandbox/fhir_api/models/dynamodb/update_model.py index 33cb38266..c89d6ba01 100644 --- a/temporary_sandbox/fhir_api/models/dynamodb/update_model.py +++ b/temporary_sandbox/fhir_api/models/dynamodb/update_model.py @@ -1,19 +1,17 @@ """Update Model for Immunization Records""" import datetime - -from typing import Optional, Literal, Any -from pydantic import BaseModel, Field +from typing import Any, Literal, Optional import fhir_api.models.fhir_r4.code_types as code_types -from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields from fhir_api.models.fhir_r4.common import ( CodeableConceptType, - Reference, Quantity, + Reference, ) - -from fhir_api.models.fhir_r4.immunization import Performer, ProtocolApplied, Annotation +from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields +from fhir_api.models.fhir_r4.immunization import Annotation, Performer, ProtocolApplied +from pydantic import BaseModel, Field class UpdateImmunizationRecord(BaseModel): diff --git a/temporary_sandbox/fhir_api/models/fhir_r4/common.py b/temporary_sandbox/fhir_api/models/fhir_r4/common.py index d303a4589..ba648ad78 100644 --- a/temporary_sandbox/fhir_api/models/fhir_r4/common.py +++ b/temporary_sandbox/fhir_api/models/fhir_r4/common.py @@ -1,15 +1,13 @@ """Common FHIR Data Models""" +from datetime import datetime from typing import ( Optional, ) -from pydantic import BaseModel, validator, PositiveInt - -from datetime import datetime - import fhir_api.models.fhir_r4.code_types as code_types from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields +from pydantic import BaseModel, PositiveInt, validator class CodingType(BaseModel): diff --git a/temporary_sandbox/fhir_api/models/fhir_r4/fhir_datatype_fields.py b/temporary_sandbox/fhir_api/models/fhir_r4/fhir_datatype_fields.py index e3a276ae2..cd4906321 100644 --- a/temporary_sandbox/fhir_api/models/fhir_r4/fhir_datatype_fields.py +++ b/temporary_sandbox/fhir_api/models/fhir_r4/fhir_datatype_fields.py @@ -1,14 +1,14 @@ """Generic Fields for FHIR Revision 4""" import datetime - -from typing import Union from functools import partial +from typing import Union + from pydantic import ( - Field, AnyUrl, - conint, + Field, PositiveInt, + conint, ) diff --git a/temporary_sandbox/fhir_api/models/fhir_r4/immunization.py b/temporary_sandbox/fhir_api/models/fhir_r4/immunization.py index da4b53fb4..7e8a634fa 100644 --- a/temporary_sandbox/fhir_api/models/fhir_r4/immunization.py +++ b/temporary_sandbox/fhir_api/models/fhir_r4/immunization.py @@ -1,17 +1,17 @@ """Immunization Data Model based on Fhir Revision 4 spec""" -from typing import Optional, Literal, Any -from pydantic import BaseModel, PositiveInt import datetime +from typing import Any, Literal, Optional import fhir_api.models.fhir_r4.code_types as code_types -from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields from fhir_api.models.fhir_r4.common import ( - Identifier, CodeableConceptType, - Reference, + Identifier, Quantity, + Reference, ) +from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields +from pydantic import BaseModel, PositiveInt class Performer(BaseModel): diff --git a/temporary_sandbox/fhir_api/models/fhir_r4/patient.py b/temporary_sandbox/fhir_api/models/fhir_r4/patient.py index d77d09d51..1e4019976 100644 --- a/temporary_sandbox/fhir_api/models/fhir_r4/patient.py +++ b/temporary_sandbox/fhir_api/models/fhir_r4/patient.py @@ -1,22 +1,22 @@ """Patient Data Model based on Fhir Revision 4 spec""" from datetime import datetime -from typing import Optional, Literal -from pydantic import ( - BaseModel, -) +from typing import Literal, Optional import fhir_api.models.fhir_r4.code_types as code_types -from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields from fhir_api.models.fhir_r4.common import ( - Identifier, - HumanName, - ContactPoint, Address, - CodeableConceptType, Attachment, - Reference, + CodeableConceptType, + ContactPoint, + HumanName, + Identifier, Period, + Reference, +) +from fhir_api.models.fhir_r4.fhir_datatype_fields import FhirR4Fields +from pydantic import ( + BaseModel, ) diff --git a/temporary_sandbox/fhir_api/routes/dynamodb.py b/temporary_sandbox/fhir_api/routes/dynamodb.py index 1548fe0eb..efcd975d9 100644 --- a/temporary_sandbox/fhir_api/routes/dynamodb.py +++ b/temporary_sandbox/fhir_api/routes/dynamodb.py @@ -1,9 +1,9 @@ """DynamoDB Router Methods""" import json +from typing import Optional from fastapi import APIRouter -from typing import Optional from fhir_api.models.dynamodb.read_models import BatchImmunizationRead @@ -24,7 +24,6 @@ def read_immunization_record( to_date: Optional[str] = "9999-01-01", include_record: Optional[str] = None, ) -> BatchImmunizationRead: - with open("/sandbox/fhir_api/sandbox_data.json", "r") as input: data = json.load(input) diff --git a/temporary_sandbox/fhir_api/routes/root.py b/temporary_sandbox/fhir_api/routes/root.py index f900ec312..e30cc7eae 100644 --- a/temporary_sandbox/fhir_api/routes/root.py +++ b/temporary_sandbox/fhir_api/routes/root.py @@ -3,7 +3,6 @@ from fastapi import APIRouter from fastapi.responses import PlainTextResponse - router = APIRouter() From badf0ced16cdea04fb7dddd4847826555b6adfdf Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 15:51:52 +0100 Subject: [PATCH 7/9] Auto apply safe fixes on commit. --- package.json | 2 +- quality_checks/Makefile | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a0fcf2877..29adda7f0 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "lint-staged": { "*": "prettier --ignore-unknown --write", "*.py": [ - "poetry -P quality_checks run ruff check", + "poetry -P quality_checks run ruff check --fix", "poetry -P quality_checks run ruff format" ], "*.tf": "terraform fmt", diff --git a/quality_checks/Makefile b/quality_checks/Makefile index 28a9a4124..8b5ee6ad0 100644 --- a/quality_checks/Makefile +++ b/quality_checks/Makefile @@ -1,3 +1,6 @@ +lint-fix: + poetry run ruff check --fix .. + lint: poetry run ruff check .. From 181c2569667ee3672558426d4d7b94a6c0f97427 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 16:29:38 +0100 Subject: [PATCH 8/9] Attempt to fix first-party import detection. --- ruff.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/ruff.toml b/ruff.toml index deab3eba9..4c6fbe7c5 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,3 +1,4 @@ +src = ["."] line-length = 121 [lint] From 7183ce366b959f2470c9c36d9d348104ab574083 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 10 Oct 2025 16:37:12 +0100 Subject: [PATCH 9/9] Revert failed attempt. Specify target Python version and apply automatic fixes. --- lambdas/redis_sync/tests/test_handler.py | 3 +-- lambdas/redis_sync/tests/test_handler_decorator.py | 1 - ruff.toml | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lambdas/redis_sync/tests/test_handler.py b/lambdas/redis_sync/tests/test_handler.py index e858ba262..eb2e10e26 100644 --- a/lambdas/redis_sync/tests/test_handler.py +++ b/lambdas/redis_sync/tests/test_handler.py @@ -4,9 +4,8 @@ import unittest from unittest.mock import patch -from constants import RedisCacheKey - import redis_sync +from constants import RedisCacheKey class TestHandler(unittest.TestCase): diff --git a/lambdas/redis_sync/tests/test_handler_decorator.py b/lambdas/redis_sync/tests/test_handler_decorator.py index 7dd44698e..a61882b45 100644 --- a/lambdas/redis_sync/tests/test_handler_decorator.py +++ b/lambdas/redis_sync/tests/test_handler_decorator.py @@ -6,7 +6,6 @@ from common.s3_event import S3EventRecord from constants import RedisCacheKey - from redis_sync import handler diff --git a/ruff.toml b/ruff.toml index 4c6fbe7c5..ecb080d4d 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,5 +1,5 @@ -src = ["."] line-length = 121 +target-version = "py311" [lint] # TODO - consider enabling more rulesets, e.g. B, C90, N, RET, S, UP