From 4606e8d08e7a31b4b261388285cd548c2ca5ffe4 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 17:40:42 +0100 Subject: [PATCH 01/24] VED-305: Testing simple approach to fixing Sonar pipeline. --- .github/workflows/sonarcloud.yml | 42 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index cc87454fe5..5324648395 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -28,61 +28,77 @@ jobs: - name: Initialize Unit Test Failure Tracker run: echo "false" > test_failed.txt + - name: Create venvs and install dependencies + run: | + pip install poetry==1.8.4 + for subproject in filenameprocessor recordprocessor backend ack_backend delta_backend mesh_processor + do + cd $subproject + python -m venv .venv + source .venv/activate + poetry install + deactivate + cd .. + done + - name: Run unittest with filenameprocessor-coverage + working-directory: filenameprocessor id: filenameprocessor continue-on-error: true run: | - pip install poetry==1.8.4 moto==4.2.11 coverage redis botocore==1.35.49 simplejson pandas freezegun responses structlog fhir.resources jsonpath_ng pydantic==1.10.13 requests aws-lambda-typing cffi pyjwt boto3-stubs-lite[dynamodb]~=1.26.90 python-stdnum==1.20 fakeredis - poetry run coverage run --source=filenameprocessor -m unittest discover -s filenameprocessor || echo "filenameprocessor tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-filenameprocessor-coverage.xml - name: Run unittest with recordprocessor-coverage + working-directory: recordprocessor id: recordprocessor continue-on-error: true run: | - poetry run coverage run --source=recordprocessor -m unittest discover -s recordprocessor || echo "recordprocessor tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordprocessor-coverage.xml - name: Run unittest with recordforwarder-coverage + working-directory: backend id: recordforwarder + env: + PYTHONPATH: backend/src:backend/tests continue-on-error: true run: | - pip install poetry==1.8.4 moto==5.1.4 - PYTHONPATH=$(pwd)/backend:$(pwd)/backend/tests poetry run coverage run --source=backend -m unittest discover -s backend/tests -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda + working-directory: ack_backend id: acklambda continue-on-error: true run: | - pip install poetry==1.8.4 coverage moto==4.2.11 freezegun - poetry run coverage run --source=ack_backend -m unittest discover -s ack_backend || echo "ack-lambda tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-ack-lambda.xml - name: Run unittest with coverage-delta + working-directory: delta_backend id: delta env: PYTHONPATH: delta_backend/src:delta_backend/tests continue-on-error: true run: | - pip install poetry==1.8.4 moto==5.1.4 mypy-boto3-dynamodb==1.35.54 boto3==1.26.165 coverage botocore==1.29.165 jmespath==1.0.1 python-dateutil==2.9.0 urllib3==1.26.20 s3transfer==0.6.2 typing-extensions==4.12.2 - poetry run coverage run --source=delta_backend -m unittest discover -s delta_backend || echo "delta tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover || echo "delta tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-delta.xml - name: Run unittest with coverage-fhir-api + working-directory: backend id: fhirapi continue-on-error: true run: | - pip install poetry==1.8.4 moto==5.1.4 coverage redis botocore==1.35.49 simplejson responses structlog fhir.resources jsonpath_ng pydantic==1.10.13 requests aws-lambda-typing cffi pyjwt boto3-stubs-lite[dynamodb]~=1.26.90 python-stdnum==1.20 - poetry run coverage run --source=backend -m unittest discover -s backend || echo "fhir-api tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage.xml - name: Run unittest with coverage-mesh-processor + working-directory: mesh_processor id: meshprocessor continue-on-error: true run: | - pip install poetry==1.8.4 moto==4.2.11 coverage redis botocore==1.35.49 simplejson responses structlog fhir.resources jsonpath_ng pydantic==1.10.13 requests aws-lambda-typing cffi pyjwt boto3-stubs-lite[dynamodb]~=1.26.90 python-stdnum==1.20 - poetry run coverage run --source=mesh_processor -m unittest discover -s mesh_processor || echo "mesh_processor tests failed" >> failed_tests.txt + poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-mesh_processor-coverage.xml - name: Run Test Failure Summary From e6826304e2b72b2679de612bdcf10d766a610e8c Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 17:42:04 +0100 Subject: [PATCH 02/24] VED-305: Correct activate path. --- .github/workflows/sonarcloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 5324648395..d928c0f8c9 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -35,7 +35,7 @@ jobs: do cd $subproject python -m venv .venv - source .venv/activate + source .venv/bin/activate poetry install deactivate cd .. From 351d4ad9d16535ac79670dfcdbf4f409d19a62df Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 17:46:53 +0100 Subject: [PATCH 03/24] VED-305: Use Python 3.10 --- .github/workflows/sonarcloud.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index d928c0f8c9..8ac63aa356 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -17,6 +17,11 @@ jobs: with: fetch-depth: 0 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: 'poetry' + - name: Set up AWS credentials env: AWS_ACCESS_KEY_ID: "FOOBARKEY" From ed199089b2e147442d57305ad8bdfbaeec9ded45 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 17:49:06 +0100 Subject: [PATCH 04/24] VED-305: Install poetry earlier. --- .github/workflows/sonarcloud.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 8ac63aa356..dded601494 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -17,6 +17,9 @@ jobs: with: fetch-depth: 0 + - name: Install poetry + run: pip install poetry==1.8.4 + - uses: actions/setup-python@v5 with: python-version: '3.10' @@ -35,7 +38,6 @@ jobs: - name: Create venvs and install dependencies run: | - pip install poetry==1.8.4 for subproject in filenameprocessor recordprocessor backend ack_backend delta_backend mesh_processor do cd $subproject From 1f15f94f0ff3d1b0e5edab944a85d56d18b1c478 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 23:14:33 +0100 Subject: [PATCH 05/24] VED-305: Attempt to use the correct python versions. --- .github/workflows/sonarcloud.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index dded601494..bb7b7313ad 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -22,7 +22,9 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: | + 3.10 + 3.11 cache: 'poetry' - name: Set up AWS credentials @@ -53,6 +55,7 @@ jobs: id: filenameprocessor continue-on-error: true run: | + poetry env use 3.10 poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-filenameprocessor-coverage.xml @@ -61,6 +64,7 @@ jobs: id: recordprocessor continue-on-error: true run: | + poetry env use 3.10 poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordprocessor-coverage.xml @@ -71,6 +75,7 @@ jobs: PYTHONPATH: backend/src:backend/tests continue-on-error: true run: | + poetry env use 3.11 poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordforwarder-coverage.xml @@ -79,6 +84,7 @@ jobs: id: acklambda continue-on-error: true run: | + poetry env use 3.10 poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-ack-lambda.xml @@ -89,6 +95,7 @@ jobs: PYTHONPATH: delta_backend/src:delta_backend/tests continue-on-error: true run: | + poetry env use 3.11 poetry run coverage run -m unittest discover || echo "delta tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-delta.xml @@ -97,6 +104,7 @@ jobs: id: fhirapi continue-on-error: true run: | + poetry env use 3.11 poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage.xml @@ -105,6 +113,7 @@ jobs: id: meshprocessor continue-on-error: true run: | + poetry env use 3.10 poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-mesh_processor-coverage.xml From 885b757eb6ed7aa92dd9563b8218668a8efd2500 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 23:33:53 +0100 Subject: [PATCH 06/24] VED-305: Stop trying to be clever. --- .github/workflows/sonarcloud.yml | 40 ++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index bb7b7313ad..f9c571239d 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -38,26 +38,18 @@ jobs: - name: Initialize Unit Test Failure Tracker run: echo "false" > test_failed.txt - - name: Create venvs and install dependencies - run: | - for subproject in filenameprocessor recordprocessor backend ack_backend delta_backend mesh_processor - do - cd $subproject - python -m venv .venv - source .venv/bin/activate - poetry install - deactivate - cd .. - done - - name: Run unittest with filenameprocessor-coverage working-directory: filenameprocessor id: filenameprocessor continue-on-error: true run: | poetry env use 3.10 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-filenameprocessor-coverage.xml + deactivate - name: Run unittest with recordprocessor-coverage working-directory: recordprocessor @@ -65,8 +57,12 @@ jobs: continue-on-error: true run: | poetry env use 3.10 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordprocessor-coverage.xml + deactivate - name: Run unittest with recordforwarder-coverage working-directory: backend @@ -76,8 +72,12 @@ jobs: continue-on-error: true run: | poetry env use 3.11 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordforwarder-coverage.xml + deactivate - name: Run unittest with coverage-ack-lambda working-directory: ack_backend @@ -85,8 +85,12 @@ jobs: continue-on-error: true run: | poetry env use 3.10 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-ack-lambda.xml + deactivate - name: Run unittest with coverage-delta working-directory: delta_backend @@ -96,8 +100,12 @@ jobs: continue-on-error: true run: | poetry env use 3.11 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover || echo "delta tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-delta.xml + deactivate - name: Run unittest with coverage-fhir-api working-directory: backend @@ -105,8 +113,12 @@ jobs: continue-on-error: true run: | poetry env use 3.11 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage.xml + deactivate - name: Run unittest with coverage-mesh-processor working-directory: mesh_processor @@ -114,8 +126,12 @@ jobs: continue-on-error: true run: | poetry env use 3.10 + python -m venv .venv + source .venv/bin/activate + poetry install poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-mesh_processor-coverage.xml + deactivate - name: Run Test Failure Summary id: check_failure From cda1720b7b40596c336633e10825d7736dfa9a17 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Thu, 29 May 2025 23:37:20 +0100 Subject: [PATCH 07/24] VED-305: One more try. --- .github/workflows/sonarcloud.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index f9c571239d..0e78b96766 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -44,8 +44,6 @@ jobs: continue-on-error: true run: | poetry env use 3.10 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-filenameprocessor-coverage.xml @@ -57,8 +55,6 @@ jobs: continue-on-error: true run: | poetry env use 3.10 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordprocessor-coverage.xml @@ -72,8 +68,6 @@ jobs: continue-on-error: true run: | poetry env use 3.11 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordforwarder-coverage.xml @@ -85,8 +79,6 @@ jobs: continue-on-error: true run: | poetry env use 3.10 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-ack-lambda.xml @@ -100,8 +92,6 @@ jobs: continue-on-error: true run: | poetry env use 3.11 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover || echo "delta tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-delta.xml @@ -113,8 +103,6 @@ jobs: continue-on-error: true run: | poetry env use 3.11 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage.xml @@ -126,8 +114,6 @@ jobs: continue-on-error: true run: | poetry env use 3.10 - python -m venv .venv - source .venv/bin/activate poetry install poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-mesh_processor-coverage.xml From a940c742b45f8490cc23c826853b248f4e9c9c3e Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 30 May 2025 00:26:21 +0100 Subject: [PATCH 08/24] VED-305: Remove deactivate call. --- .github/workflows/sonarcloud.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 0e78b96766..21e51157a7 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -47,7 +47,6 @@ jobs: poetry install poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-filenameprocessor-coverage.xml - deactivate - name: Run unittest with recordprocessor-coverage working-directory: recordprocessor @@ -58,7 +57,6 @@ jobs: poetry install poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordprocessor-coverage.xml - deactivate - name: Run unittest with recordforwarder-coverage working-directory: backend @@ -71,7 +69,6 @@ jobs: poetry install poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-recordforwarder-coverage.xml - deactivate - name: Run unittest with coverage-ack-lambda working-directory: ack_backend @@ -82,7 +79,6 @@ jobs: poetry install poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-ack-lambda.xml - deactivate - name: Run unittest with coverage-delta working-directory: delta_backend @@ -95,7 +91,6 @@ jobs: poetry install poetry run coverage run -m unittest discover || echo "delta tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage-delta.xml - deactivate - name: Run unittest with coverage-fhir-api working-directory: backend @@ -106,7 +101,6 @@ jobs: poetry install poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-coverage.xml - deactivate - name: Run unittest with coverage-mesh-processor working-directory: mesh_processor @@ -117,7 +111,6 @@ jobs: poetry install poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> failed_tests.txt poetry run coverage xml -o sonarcloud-mesh_processor-coverage.xml - deactivate - name: Run Test Failure Summary id: check_failure From bc7f7236351105c2449954a9bcdfd096da4ccb80 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 30 May 2025 00:30:48 +0100 Subject: [PATCH 09/24] VED-305: Save coverage and test failure to correct location. --- .github/workflows/sonarcloud.yml | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 21e51157a7..0bd7f1b59d 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -35,9 +35,6 @@ jobs: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - - name: Initialize Unit Test Failure Tracker - run: echo "false" > test_failed.txt - - name: Run unittest with filenameprocessor-coverage working-directory: filenameprocessor id: filenameprocessor @@ -45,8 +42,8 @@ jobs: run: | poetry env use 3.10 poetry install - poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-coverage-filenameprocessor-coverage.xml + poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml - name: Run unittest with recordprocessor-coverage working-directory: recordprocessor @@ -55,8 +52,8 @@ jobs: run: | poetry env use 3.10 poetry install - poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-coverage-recordprocessor-coverage.xml + poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml - name: Run unittest with recordforwarder-coverage working-directory: backend @@ -67,8 +64,8 @@ jobs: run: | poetry env use 3.11 poetry install - poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-coverage-recordforwarder-coverage.xml + poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda working-directory: ack_backend @@ -77,8 +74,8 @@ jobs: run: | poetry env use 3.10 poetry install - poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-coverage-ack-lambda.xml + poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml - name: Run unittest with coverage-delta working-directory: delta_backend @@ -89,8 +86,8 @@ jobs: run: | poetry env use 3.11 poetry install - poetry run coverage run -m unittest discover || echo "delta tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-coverage-delta.xml + poetry run coverage run -m unittest discover || echo "delta tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-delta.xml - name: Run unittest with coverage-fhir-api working-directory: backend @@ -99,8 +96,8 @@ jobs: run: | poetry env use 3.11 poetry install - poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-coverage.xml + poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage.xml - name: Run unittest with coverage-mesh-processor working-directory: mesh_processor @@ -109,8 +106,8 @@ jobs: run: | poetry env use 3.10 poetry install - poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> failed_tests.txt - poetry run coverage xml -o sonarcloud-mesh_processor-coverage.xml + poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml - name: Run Test Failure Summary id: check_failure From 3bdca0258f61a14cea5f6b1c09adbbbd20a0c17c Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 30 May 2025 01:43:52 +0100 Subject: [PATCH 10/24] VED-305: Ensure all subprojects have coverage dependency. --- ack_backend/poetry.lock | 117 +++++++++++++----- ack_backend/pyproject.toml | 1 + backend/poetry.lock | 134 +++++++++++++------- backend/pyproject.toml | 1 + delta_backend/poetry.lock | 177 ++++++++++++--------------- filenameprocessor/poetry.lock | 204 ++++++++++++------------------- filenameprocessor/pyproject.toml | 2 +- mesh_processor/poetry.lock | 122 ++++++++++++------ mesh_processor/pyproject.toml | 1 + recordprocessor/poetry.lock | 137 +++++++++++++-------- recordprocessor/pyproject.toml | 1 + 11 files changed, 507 insertions(+), 390 deletions(-) diff --git a/ack_backend/poetry.lock b/ack_backend/poetry.lock index ebd966e430..d5947cee51 100644 --- a/ack_backend/poetry.lock +++ b/ack_backend/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "boto3" @@ -6,7 +6,6 @@ version = "1.38.17" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "boto3-1.38.17-py3-none-any.whl", hash = "sha256:9b56c98fe7acb6559c24dacd838989878c60f3df2fb8ca5f311128419fd9f953"}, {file = "boto3-1.38.17.tar.gz", hash = "sha256:6058feef976ece2878ad3555f39933e63d20d02e2bbd40610ab2926d4555710a"}, @@ -26,7 +25,6 @@ version = "1.38.17" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "botocore-1.38.17-py3-none-any.whl", hash = "sha256:ec75cf02fbd3dbec18187085ce387761eab16afdccfd0774fd168db3689c6cb6"}, {file = "botocore-1.38.17.tar.gz", hash = "sha256:f2db4c4bdcfbc41d78bfe73b9affe7d217c7840f8ce120cff815536969418b18"}, @@ -46,7 +44,6 @@ version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, @@ -58,8 +55,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -139,7 +134,6 @@ version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, @@ -248,13 +242,91 @@ files = [ {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] +[[package]] +name = "coverage" +version = "7.8.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "cryptography" version = "43.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, @@ -304,7 +376,6 @@ version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, @@ -319,7 +390,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -334,7 +404,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -352,7 +421,6 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -364,7 +432,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -435,7 +502,6 @@ version = "5.1.4" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, @@ -481,7 +547,6 @@ version = "1.38.4" description = "Type annotations for boto3 DynamoDB 1.38.4 service generated with mypy-boto3-builder 8.10.1" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "mypy_boto3_dynamodb-1.38.4-py3-none-any.whl", hash = "sha256:6b29d89c649eeb1e894118bee002cb8b1304c78da735b1503aa08e46b0abfdec"}, {file = "mypy_boto3_dynamodb-1.38.4.tar.gz", hash = "sha256:5cf3787631e312b3d75f89a6cbbbd4ad786a76f5d565af023febf03fbf23c0b5"}, @@ -496,8 +561,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -509,7 +572,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -524,7 +586,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -587,7 +648,6 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -609,7 +669,6 @@ version = "0.25.3" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "responses-0.25.3-py3-none-any.whl", hash = "sha256:521efcbc82081ab8daa588e08f7e8a64ce79b91c39f6e62199b19159bea7dbcb"}, {file = "responses-0.25.3.tar.gz", hash = "sha256:617b9247abd9ae28313d57a75880422d55ec63c29d33d629697590a034358dba"}, @@ -621,7 +680,7 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "s3transfer" @@ -629,7 +688,6 @@ version = "0.12.0" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "s3transfer-0.12.0-py3-none-any.whl", hash = "sha256:35b314d7d82865756edab59f7baebc6b477189e6ab4c53050e28c1de4d9cce18"}, {file = "s3transfer-0.12.0.tar.gz", hash = "sha256:8ac58bc1989a3fdb7c7f3ee0918a66b160d038a147c7b5db1500930a607e9a1c"}, @@ -647,7 +705,6 @@ version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -659,7 +716,6 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -671,15 +727,14 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [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"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -688,7 +743,6 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -706,13 +760,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "~3.10" -content-hash = "11fa113f9e447006e421e6343e52d0e46b1098fcab76fcaeb0a31aa58bcdc1c8" +content-hash = "6dcc58b41268bee85d7fc1d788554e74fc9cefc10d1f686a81fb63fefaa55150" diff --git a/ack_backend/pyproject.toml b/ack_backend/pyproject.toml index 78dcf1d34b..cc9183ad82 100644 --- a/ack_backend/pyproject.toml +++ b/ack_backend/pyproject.toml @@ -11,6 +11,7 @@ boto3 = "~1.38.17" mypy-boto3-dynamodb = "^1.38.4" freezegun = "^1.5.1" moto = "~5.1.4" +coverage = "^7.8.0" [build-system] diff --git a/backend/poetry.lock b/backend/poetry.lock index 1c859a48f7..ff4369c2d1 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aws-lambda-typing" @@ -6,7 +6,6 @@ version = "2.18.0" description = "A package that provides type hints for AWS Lambda event, context and response objects" optional = false python-versions = ">=3.6,<4.0" -groups = ["main"] files = [ {file = "aws-lambda-typing-2.18.0.tar.gz", hash = "sha256:2725cb620ee3e36c2175faa94c8faeed25823bd3b6ec738e08dcb7e29b18d0d0"}, {file = "aws_lambda_typing-2.18.0-py3-none-any.whl", hash = "sha256:a2be544aa508a7c8abfa7f9b59c661f2ce4a74fd03dbe37f8cd8ea70f57c5502"}, @@ -18,7 +17,6 @@ version = "1.38.17" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "boto3-1.38.17-py3-none-any.whl", hash = "sha256:9b56c98fe7acb6559c24dacd838989878c60f3df2fb8ca5f311128419fd9f953"}, {file = "boto3-1.38.17.tar.gz", hash = "sha256:6058feef976ece2878ad3555f39933e63d20d02e2bbd40610ab2926d4555710a"}, @@ -38,7 +36,6 @@ version = "1.26.165" description = "Type annotations for boto3 1.26.165 generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "boto3-stubs-lite-1.26.165.tar.gz", hash = "sha256:56fe506b9b94dbeefaf53fc0fbc332258c87011606ff9c7a51fd2017a51ec220"}, {file = "boto3_stubs_lite-1.26.165-py3-none-any.whl", hash = "sha256:9340fe195c7309b4db6fe50eb146f49625b9fcfa4c7a8bd642ceaeb6087610cc"}, @@ -410,7 +407,6 @@ version = "1.38.17" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "botocore-1.38.17-py3-none-any.whl", hash = "sha256:ec75cf02fbd3dbec18187085ce387761eab16afdccfd0774fd168db3689c6cb6"}, {file = "botocore-1.38.17.tar.gz", hash = "sha256:f2db4c4bdcfbc41d78bfe73b9affe7d217c7840f8ce120cff815536969418b18"}, @@ -430,7 +426,6 @@ version = "1.35.72" description = "Type annotations and code completion for botocore" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "botocore_stubs-1.35.72-py3-none-any.whl", hash = "sha256:089221dd326344d0a7ceaed851be25709cf1680a5452e41618b3631e31bf1597"}, {file = "botocore_stubs-1.35.72.tar.gz", hash = "sha256:6dd2044714fa27824d49b49e8e78cd951f44a3cc3cbdc48114d81a73b7be0d32"}, @@ -448,7 +443,6 @@ version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, @@ -460,7 +454,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -540,7 +533,6 @@ version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, @@ -649,13 +641,91 @@ files = [ {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] +[[package]] +name = "coverage" +version = "7.8.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "cryptography" version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, @@ -710,7 +780,6 @@ version = "2.7.0" description = "DNS toolkit" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, @@ -731,7 +800,6 @@ version = "2.2.0" description = "A robust email address syntax and deliverability validation library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"}, {file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"}, @@ -747,7 +815,6 @@ version = "7.0.2" description = "FHIR Resources as Model Class" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "fhir.resources-7.0.2-py2.py3-none-any.whl", hash = "sha256:ba16b3348821614650dd2e7f04db170210ce4406f65a5cc873beb10317d595ff"}, {file = "fhir.resources-7.0.2.tar.gz", hash = "sha256:1e6392f7bc3b143463b07ada87a3b6a92dd8fe97947670423317fea69226f6de"}, @@ -758,9 +825,9 @@ pydantic = {version = ">=1.7.2,<2.0.0", extras = ["email"]} [package.extras] all = ["PyYAML (>=5.4.1)", "lxml", "orjson (>=3.4.3)"] -dev = ["Jinja2 (==2.11.1)", "MarkupSafe (==1.1.1)", "black", "certifi", "colorlog (==2.10.0)", "coverage", "fhirspec", "flake8 (==5.0.4) ; python_version < \"3.10\"", "flake8-bugbear (==20.1.4) ; python_version < \"3.10\"", "flake8-isort (==4.2.0) ; python_version < \"3.10\"", "isort (==4.3.21)", "mypy (==0.812)", "pytest (>5.4.0) ; python_version >= \"3.6\"", "pytest-cov (>=2.10.0) ; python_version >= \"3.6\"", "requests (==2.23.0) ; python_version < \"3.10\"", "setuptools (==65.6.3) ; python_version >= \"3.7\"", "zest-releaser[recommended]"] +dev = ["Jinja2 (==2.11.1)", "MarkupSafe (==1.1.1)", "black", "certifi", "colorlog (==2.10.0)", "coverage", "fhirspec", "flake8 (==5.0.4)", "flake8-bugbear (==20.1.4)", "flake8-isort (==4.2.0)", "isort (==4.3.21)", "mypy (==0.812)", "pytest (>5.4.0)", "pytest-cov (>=2.10.0)", "requests (==2.23.0)", "setuptools (==65.6.3)", "zest-releaser[recommended]"] orjson = ["orjson (>=3.4.3)"] -test = ["PyYAML (>=5.4.1)", "black", "coverage", "flake8 (==5.0.4) ; python_version < \"3.10\"", "flake8-bugbear (==20.1.4) ; python_version < \"3.10\"", "flake8-isort (==4.2.0) ; python_version < \"3.10\"", "isort (==4.3.21)", "lxml", "mypy (==0.812)", "orjson (>=3.4.3)", "pytest (>5.4.0) ; python_version >= \"3.6\"", "pytest-cov (>=2.10.0) ; python_version >= \"3.6\"", "pytest-runner", "requests (==2.23.0) ; python_version < \"3.10\"", "setuptools (==65.6.3) ; python_version >= \"3.7\""] +test = ["PyYAML (>=5.4.1)", "black", "coverage", "flake8 (==5.0.4)", "flake8-bugbear (==20.1.4)", "flake8-isort (==4.2.0)", "isort (==4.3.21)", "lxml", "mypy (==0.812)", "orjson (>=3.4.3)", "pytest (>5.4.0)", "pytest-cov (>=2.10.0)", "pytest-runner", "requests (==2.23.0)", "setuptools (==65.6.3)"] xml = ["lxml"] yaml = ["PyYAML (>=5.4.1)"] @@ -770,7 +837,6 @@ version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, @@ -785,7 +851,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -800,7 +865,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -818,7 +882,6 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -830,7 +893,6 @@ version = "1.7.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c"}, {file = "jsonpath_ng-1.7.0-py2-none-any.whl", hash = "sha256:898c93fc173f0c336784a3fa63d7434297544b7198124a68f9a3ef9597b0ae6e"}, @@ -846,7 +908,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -917,7 +978,6 @@ version = "5.1.4" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, @@ -963,7 +1023,6 @@ version = "1.26.164" description = "Type annotations for boto3.DynamoDB 1.26.164 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "mypy-boto3-dynamodb-1.26.164.tar.gz", hash = "sha256:5a832531ac2c81b01dea20ef79f7dd5a2014c3736566a498585f5f46d642adc4"}, {file = "mypy_boto3_dynamodb-1.26.164-py3-none-any.whl", hash = "sha256:a527270b304f1a517093fff3709c7831fc5616a91bb1c9b6164fa71e37481d84"}, @@ -975,7 +1034,6 @@ version = "3.11" description = "Python Lex & Yacc" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, @@ -987,7 +1045,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -999,7 +1056,6 @@ version = "1.10.19" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "pydantic-1.10.19-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a415b9e95fa602b10808113967f72b2da8722061265d6af69268c111c254832d"}, {file = "pydantic-1.10.19-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:11965f421f7eb026439d4eb7464e9182fe6d69c3d4d416e464a4485d1ba61ab6"}, @@ -1060,7 +1116,6 @@ version = "2.8.0" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, @@ -1078,7 +1133,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1093,7 +1147,6 @@ version = "2.1" description = "Python module to handle standardized numbers and codes" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "python_stdnum-2.1-py3-none-any.whl", hash = "sha256:25eabcf5f307dd4150fd8f1c03f4512a6caeb84c9f09be1448711f5803373c58"}, {file = "python_stdnum-2.1.tar.gz", hash = "sha256:6b01645969eb3dfd55061a0114d593753cd9e653cea9083198b7eea12644397a"}, @@ -1108,7 +1161,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1171,7 +1223,6 @@ version = "2.31.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, @@ -1193,7 +1244,6 @@ version = "0.24.1" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "responses-0.24.1-py3-none-any.whl", hash = "sha256:a2b43f4c08bfb9c9bd242568328c65a34b318741d3fab884ac843c5ceeb543f9"}, {file = "responses-0.24.1.tar.gz", hash = "sha256:b127c6ca3f8df0eb9cc82fd93109a3007a86acb24871834c47b77765152ecf8c"}, @@ -1205,7 +1255,7 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "s3transfer" @@ -1213,7 +1263,6 @@ version = "0.12.0" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "s3transfer-0.12.0-py3-none-any.whl", hash = "sha256:35b314d7d82865756edab59f7baebc6b477189e6ab4c53050e28c1de4d9cce18"}, {file = "s3transfer-0.12.0.tar.gz", hash = "sha256:8ac58bc1989a3fdb7c7f3ee0918a66b160d038a147c7b5db1500930a607e9a1c"}, @@ -1231,7 +1280,6 @@ version = "3.19.3" description = "Simple, fast, extensible JSON encoder/decoder for Python" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.5" -groups = ["main"] files = [ {file = "simplejson-3.19.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f39caec26007a2d0efab6b8b1d74873ede9351962707afab622cc2285dd26ed0"}, {file = "simplejson-3.19.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:83c87706265ae3028e8460d08b05f30254c569772e859e5ba61fe8af2c883468"}, @@ -1351,7 +1399,6 @@ version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -1363,7 +1410,6 @@ version = "24.4.0" description = "Structured Logging for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610"}, {file = "structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4"}, @@ -1381,7 +1427,6 @@ version = "0.23.1" description = "Type annotations and code completion for awscrt" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "types_awscrt-0.23.1-py3-none-any.whl", hash = "sha256:0d362a5d62d68ca4216f458172f41c1123ec04791d68364de8ee8b61b528b262"}, {file = "types_awscrt-0.23.1.tar.gz", hash = "sha256:a20b425dabb258bc3d07a5e7de503fd9558dd1542d72de796e74e402c6d493b2"}, @@ -1393,7 +1438,6 @@ version = "0.10.4" description = "Type annotations and code completion for s3transfer" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "types_s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:22ac1aabc98f9d7f2928eb3fb4d5c02bf7435687f0913345a97dd3b84d0c217d"}, {file = "types_s3transfer-0.10.4.tar.gz", hash = "sha256:03123477e3064c81efe712bf9d372c7c72f2790711431f9baa59cf96ea607267"}, @@ -1405,7 +1449,6 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1417,15 +1460,14 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [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"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -1434,7 +1476,6 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -1452,13 +1493,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "~3.11" -content-hash = "82f12520e6eb611a1e6bee99d32dc8d44d4cfd278fa42f3d700d5f69d824e055" +content-hash = "c1a83dc0d3320999216b17e21921b2f0c255e8bdc080d2026c9f918c9ff94fde" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index f192a93cfb..b763f4c6f6 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -24,6 +24,7 @@ simplejson = "^3.19.2" structlog = "^24.1.0" python-stdnum = "^2.1" freezegun = "^1.5.1" +coverage = "^7.8.0" [build-system] requires = ["poetry-core ~= 1.5.0"] diff --git a/delta_backend/poetry.lock b/delta_backend/poetry.lock index 6983e04696..a63721aa79 100644 --- a/delta_backend/poetry.lock +++ b/delta_backend/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "boto3" @@ -6,7 +6,6 @@ version = "1.38.17" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "boto3-1.38.17-py3-none-any.whl", hash = "sha256:9b56c98fe7acb6559c24dacd838989878c60f3df2fb8ca5f311128419fd9f953"}, {file = "boto3-1.38.17.tar.gz", hash = "sha256:6058feef976ece2878ad3555f39933e63d20d02e2bbd40610ab2926d4555710a"}, @@ -26,7 +25,6 @@ version = "1.38.17" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "botocore-1.38.17-py3-none-any.whl", hash = "sha256:ec75cf02fbd3dbec18187085ce387761eab16afdccfd0774fd168db3689c6cb6"}, {file = "botocore-1.38.17.tar.gz", hash = "sha256:f2db4c4bdcfbc41d78bfe73b9affe7d217c7840f8ce120cff815536969418b18"}, @@ -46,7 +44,6 @@ version = "2025.4.26" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, @@ -58,8 +55,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -139,7 +134,6 @@ version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, @@ -237,79 +231,82 @@ files = [ [[package]] name = "coverage" -version = "7.8.0" +version = "7.8.2" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" -groups = ["main", "dev"] files = [ - {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, - {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, - {file = "coverage-7.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c8a5c139aae4c35cbd7cadca1df02ea8cf28a911534fc1b0456acb0b14234f3"}, - {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a26c0c795c3e0b63ec7da6efded5f0bc856d7c0b24b2ac84b4d1d7bc578d676"}, - {file = "coverage-7.8.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821f7bcbaa84318287115d54becb1915eece6918136c6f91045bb84e2f88739d"}, - {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a321c61477ff8ee705b8a5fed370b5710c56b3a52d17b983d9215861e37b642a"}, - {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ed2144b8a78f9d94d9515963ed273d620e07846acd5d4b0a642d4849e8d91a0c"}, - {file = "coverage-7.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:042e7841a26498fff7a37d6fda770d17519982f5b7d8bf5278d140b67b61095f"}, - {file = "coverage-7.8.0-cp310-cp310-win32.whl", hash = "sha256:f9983d01d7705b2d1f7a95e10bbe4091fabc03a46881a256c2787637b087003f"}, - {file = "coverage-7.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5a570cd9bd20b85d1a0d7b009aaf6c110b52b5755c17be6962f8ccd65d1dbd23"}, - {file = "coverage-7.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7ac22a0bb2c7c49f441f7a6d46c9c80d96e56f5a8bc6972529ed43c8b694e27"}, - {file = "coverage-7.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf13d564d310c156d1c8e53877baf2993fb3073b2fc9f69790ca6a732eb4bfea"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5761c70c017c1b0d21b0815a920ffb94a670c8d5d409d9b38857874c21f70d7"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ff52d790c7e1628241ffbcaeb33e07d14b007b6eb00a19320c7b8a7024c040"}, - {file = "coverage-7.8.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d39fc4817fd67b3915256af5dda75fd4ee10621a3d484524487e33416c6f3543"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b44674870709017e4b4036e3d0d6c17f06a0e6d4436422e0ad29b882c40697d2"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8f99eb72bf27cbb167b636eb1726f590c00e1ad375002230607a844d9e9a2318"}, - {file = "coverage-7.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b571bf5341ba8c6bc02e0baeaf3b061ab993bf372d982ae509807e7f112554e9"}, - {file = "coverage-7.8.0-cp311-cp311-win32.whl", hash = "sha256:e75a2ad7b647fd8046d58c3132d7eaf31b12d8a53c0e4b21fa9c4d23d6ee6d3c"}, - {file = "coverage-7.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:3043ba1c88b2139126fc72cb48574b90e2e0546d4c78b5299317f61b7f718b78"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbb5cc845a0292e0c520656d19d7ce40e18d0e19b22cb3e0409135a575bf79fc"}, - {file = "coverage-7.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4dfd9a93db9e78666d178d4f08a5408aa3f2474ad4d0e0378ed5f2ef71640cb6"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f017a61399f13aa6d1039f75cd467be388d157cd81f1a119b9d9a68ba6f2830d"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0915742f4c82208ebf47a2b154a5334155ed9ef9fe6190674b8a46c2fb89cb05"}, - {file = "coverage-7.8.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a40fcf208e021eb14b0fac6bdb045c0e0cab53105f93ba0d03fd934c956143a"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a1f406a8e0995d654b2ad87c62caf6befa767885301f3b8f6f73e6f3c31ec3a6"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:77af0f6447a582fdc7de5e06fa3757a3ef87769fbb0fdbdeba78c23049140a47"}, - {file = "coverage-7.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f2d32f95922927186c6dbc8bc60df0d186b6edb828d299ab10898ef3f40052fe"}, - {file = "coverage-7.8.0-cp312-cp312-win32.whl", hash = "sha256:769773614e676f9d8e8a0980dd7740f09a6ea386d0f383db6821df07d0f08545"}, - {file = "coverage-7.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e5d2b9be5b0693cf21eb4ce0ec8d211efb43966f6657807f6859aab3814f946b"}, - {file = "coverage-7.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ac46d0c2dd5820ce93943a501ac5f6548ea81594777ca585bf002aa8854cacd"}, - {file = "coverage-7.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:771eb7587a0563ca5bb6f622b9ed7f9d07bd08900f7589b4febff05f469bea00"}, - {file = "coverage-7.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42421e04069fb2cbcbca5a696c4050b84a43b05392679d4068acbe65449b5c64"}, - {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554fec1199d93ab30adaa751db68acec2b41c5602ac944bb19187cb9a41a8067"}, - {file = "coverage-7.8.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aaeb00761f985007b38cf463b1d160a14a22c34eb3f6a39d9ad6fc27cb73008"}, - {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:581a40c7b94921fffd6457ffe532259813fc68eb2bdda60fa8cc343414ce3733"}, - {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f319bae0321bc838e205bf9e5bc28f0a3165f30c203b610f17ab5552cff90323"}, - {file = "coverage-7.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04bfec25a8ef1c5f41f5e7e5c842f6b615599ca8ba8391ec33a9290d9d2db3a3"}, - {file = "coverage-7.8.0-cp313-cp313-win32.whl", hash = "sha256:dd19608788b50eed889e13a5d71d832edc34fc9dfce606f66e8f9f917eef910d"}, - {file = "coverage-7.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:a9abbccd778d98e9c7e85038e35e91e67f5b520776781d9a1e2ee9d400869487"}, - {file = "coverage-7.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:18c5ae6d061ad5b3e7eef4363fb27a0576012a7447af48be6c75b88494c6cf25"}, - {file = "coverage-7.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:95aa6ae391a22bbbce1b77ddac846c98c5473de0372ba5c463480043a07bff42"}, - {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e013b07ba1c748dacc2a80e69a46286ff145935f260eb8c72df7185bf048f502"}, - {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d766a4f0e5aa1ba056ec3496243150698dc0481902e2b8559314368717be82b1"}, - {file = "coverage-7.8.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad80e6b4a0c3cb6f10f29ae4c60e991f424e6b14219d46f1e7d442b938ee68a4"}, - {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b87eb6fc9e1bb8f98892a2458781348fa37e6925f35bb6ceb9d4afd54ba36c73"}, - {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d1ba00ae33be84066cfbe7361d4e04dec78445b2b88bdb734d0d1cbab916025a"}, - {file = "coverage-7.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f3c38e4e5ccbdc9198aecc766cedbb134b2d89bf64533973678dfcf07effd883"}, - {file = "coverage-7.8.0-cp313-cp313t-win32.whl", hash = "sha256:379fe315e206b14e21db5240f89dc0774bdd3e25c3c58c2c733c99eca96f1ada"}, - {file = "coverage-7.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2e4b6b87bb0c846a9315e3ab4be2d52fac905100565f4b92f02c445c8799e257"}, - {file = "coverage-7.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa260de59dfb143af06dcf30c2be0b200bed2a73737a8a59248fcb9fa601ef0f"}, - {file = "coverage-7.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:96121edfa4c2dfdda409877ea8608dd01de816a4dc4a0523356067b305e4e17a"}, - {file = "coverage-7.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b8af63b9afa1031c0ef05b217faa598f3069148eeee6bb24b79da9012423b82"}, - {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89b1f4af0d4afe495cd4787a68e00f30f1d15939f550e869de90a86efa7e0814"}, - {file = "coverage-7.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ec0be97723ae72d63d3aa41961a0b9a6f5a53ff599813c324548d18e3b9e8c"}, - {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a1d96e780bdb2d0cbb297325711701f7c0b6f89199a57f2049e90064c29f6bd"}, - {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f1d8a2a57b47142b10374902777e798784abf400a004b14f1b0b9eaf1e528ba4"}, - {file = "coverage-7.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cf60dd2696b457b710dd40bf17ad269d5f5457b96442f7f85722bdb16fa6c899"}, - {file = "coverage-7.8.0-cp39-cp39-win32.whl", hash = "sha256:be945402e03de47ba1872cd5236395e0f4ad635526185a930735f66710e1bd3f"}, - {file = "coverage-7.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:90e7fbc6216ecaffa5a880cdc9c77b7418c1dcb166166b78dbc630d07f278cc3"}, - {file = "coverage-7.8.0-pp39.pp310.pp311-none-any.whl", hash = "sha256:b8194fb8e50d556d5849753de991d390c5a1edeeba50f68e3a9253fbd8bf8ccd"}, - {file = "coverage-7.8.0-py3-none-any.whl", hash = "sha256:dbf364b4c5e7bae9250528167dfe40219b62e2d573c854d74be213e1e52069f7"}, - {file = "coverage-7.8.0.tar.gz", hash = "sha256:7a3d62b3b03b4b6fd41a085f3574874cf946cb4604d2b4d3e8dca8cd570ca501"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, ] [package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] +toml = ["tomli"] [[package]] name = "cryptography" @@ -317,7 +314,6 @@ version = "44.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] files = [ {file = "cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88"}, {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137"}, @@ -362,10 +358,10 @@ files = [ cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] -pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.3)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] @@ -377,7 +373,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -392,7 +387,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -410,7 +404,6 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -422,7 +415,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -493,7 +485,6 @@ version = "5.1.4" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, @@ -539,7 +530,6 @@ version = "1.38.4" description = "Type annotations for boto3 DynamoDB 1.38.4 service generated with mypy-boto3-builder 8.10.1" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "mypy_boto3_dynamodb-1.38.4-py3-none-any.whl", hash = "sha256:6b29d89c649eeb1e894118bee002cb8b1304c78da735b1503aa08e46b0abfdec"}, {file = "mypy_boto3_dynamodb-1.38.4.tar.gz", hash = "sha256:5cf3787631e312b3d75f89a6cbbbd4ad786a76f5d565af023febf03fbf23c0b5"}, @@ -554,8 +544,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -567,7 +555,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -582,7 +569,6 @@ version = "2.1" description = "Python module to handle standardized numbers and codes" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "python_stdnum-2.1-py3-none-any.whl", hash = "sha256:25eabcf5f307dd4150fd8f1c03f4512a6caeb84c9f09be1448711f5803373c58"}, {file = "python_stdnum-2.1.tar.gz", hash = "sha256:6b01645969eb3dfd55061a0114d593753cd9e653cea9083198b7eea12644397a"}, @@ -597,7 +583,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -660,7 +645,6 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -682,7 +666,6 @@ version = "0.25.7" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "responses-0.25.7-py3-none-any.whl", hash = "sha256:92ca17416c90fe6b35921f52179bff29332076bb32694c0df02dcac2c6bc043c"}, {file = "responses-0.25.7.tar.gz", hash = "sha256:8ebae11405d7a5df79ab6fd54277f6f2bc29b2d002d0dd2d5c632594d1ddcedb"}, @@ -694,7 +677,7 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "s3transfer" @@ -702,7 +685,6 @@ version = "0.12.0" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "s3transfer-0.12.0-py3-none-any.whl", hash = "sha256:35b314d7d82865756edab59f7baebc6b477189e6ab4c53050e28c1de4d9cce18"}, {file = "s3transfer-0.12.0.tar.gz", hash = "sha256:8ac58bc1989a3fdb7c7f3ee0918a66b160d038a147c7b5db1500930a607e9a1c"}, @@ -720,7 +702,6 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -732,7 +713,6 @@ version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, @@ -744,15 +724,14 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [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"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -761,7 +740,6 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -779,13 +757,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "~3.11" content-hash = "f3868516ea876fc5281d2eb130250ca08bfbc0e017d8ed02813ac436da5f337e" diff --git a/filenameprocessor/poetry.lock b/filenameprocessor/poetry.lock index 26dd136e2f..6c9b04ffb8 100644 --- a/filenameprocessor/poetry.lock +++ b/filenameprocessor/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "async-timeout" @@ -6,7 +6,6 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -18,7 +17,6 @@ version = "2.18.0" description = "A package that provides type hints for AWS Lambda event, context and response objects" optional = false python-versions = ">=3.6,<4.0" -groups = ["main"] files = [ {file = "aws-lambda-typing-2.18.0.tar.gz", hash = "sha256:2725cb620ee3e36c2175faa94c8faeed25823bd3b6ec738e08dcb7e29b18d0d0"}, {file = "aws_lambda_typing-2.18.0-py3-none-any.whl", hash = "sha256:a2be544aa508a7c8abfa7f9b59c661f2ce4a74fd03dbe37f8cd8ea70f57c5502"}, @@ -30,7 +28,6 @@ version = "1.38.17" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "boto3-1.38.17-py3-none-any.whl", hash = "sha256:9b56c98fe7acb6559c24dacd838989878c60f3df2fb8ca5f311128419fd9f953"}, {file = "boto3-1.38.17.tar.gz", hash = "sha256:6058feef976ece2878ad3555f39933e63d20d02e2bbd40610ab2926d4555710a"}, @@ -50,7 +47,6 @@ version = "1.26.165" description = "Type annotations for boto3 1.26.165 generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "boto3-stubs-lite-1.26.165.tar.gz", hash = "sha256:56fe506b9b94dbeefaf53fc0fbc332258c87011606ff9c7a51fd2017a51ec220"}, {file = "boto3_stubs_lite-1.26.165-py3-none-any.whl", hash = "sha256:9340fe195c7309b4db6fe50eb146f49625b9fcfa4c7a8bd642ceaeb6087610cc"}, @@ -422,7 +418,6 @@ version = "1.38.17" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "botocore-1.38.17-py3-none-any.whl", hash = "sha256:ec75cf02fbd3dbec18187085ce387761eab16afdccfd0774fd168db3689c6cb6"}, {file = "botocore-1.38.17.tar.gz", hash = "sha256:f2db4c4bdcfbc41d78bfe73b9affe7d217c7840f8ce120cff815536969418b18"}, @@ -442,7 +437,6 @@ version = "1.36.14" description = "Type annotations and code completion for botocore" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "botocore_stubs-1.36.14-py3-none-any.whl", hash = "sha256:58f8e6eb37427b7bb81aa24984b10c90d124526b2ba741ebbe7d6e5690454ad0"}, {file = "botocore_stubs-1.36.14.tar.gz", hash = "sha256:54c7b6fe68d6e2a1eac827b1c0525554509a3481ed6ad5a0f4f2c487e00768d2"}, @@ -460,7 +454,6 @@ version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, @@ -472,7 +465,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -552,7 +544,6 @@ version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, @@ -650,88 +641,82 @@ files = [ [[package]] name = "coverage" -version = "7.6.1" +version = "7.8.2" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" -groups = ["main"] +python-versions = ">=3.9" files = [ - {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, - {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, - {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, - {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, - {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, - {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, - {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, - {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, - {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, - {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, - {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, - {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, - {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, - {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, - {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, - {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, - {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, - {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, - {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, - {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, - {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, - {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, - {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, - {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, - {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, - {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, - {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, - {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, - {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, - {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, - {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, - {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, - {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, - {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, - {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, - {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, - {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, - {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, ] [package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] +toml = ["tomli"] [[package]] name = "cryptography" @@ -739,7 +724,6 @@ version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, @@ -794,7 +778,6 @@ version = "2.7.0" description = "DNS toolkit" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, @@ -815,7 +798,6 @@ version = "2.2.0" description = "A robust email address syntax and deliverability validation library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"}, {file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"}, @@ -831,7 +813,6 @@ version = "2.26.2" description = "Python implementation of redis API, can be used for testing purposes." optional = false python-versions = "<4.0,>=3.7" -groups = ["main"] files = [ {file = "fakeredis-2.26.2-py3-none-any.whl", hash = "sha256:86d4129df001efc25793cb334008160fccc98425d9f94de47884a92b63988c14"}, {file = "fakeredis-2.26.2.tar.gz", hash = "sha256:3ee5003a314954032b96b1365290541346c9cc24aab071b52cc983bb99ecafbf"}, @@ -855,7 +836,6 @@ version = "7.0.2" description = "FHIR Resources as Model Class" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "fhir.resources-7.0.2-py2.py3-none-any.whl", hash = "sha256:ba16b3348821614650dd2e7f04db170210ce4406f65a5cc873beb10317d595ff"}, {file = "fhir.resources-7.0.2.tar.gz", hash = "sha256:1e6392f7bc3b143463b07ada87a3b6a92dd8fe97947670423317fea69226f6de"}, @@ -866,9 +846,9 @@ pydantic = {version = ">=1.7.2,<2.0.0", extras = ["email"]} [package.extras] all = ["PyYAML (>=5.4.1)", "lxml", "orjson (>=3.4.3)"] -dev = ["Jinja2 (==2.11.1)", "MarkupSafe (==1.1.1)", "black", "certifi", "colorlog (==2.10.0)", "coverage", "fhirspec", "flake8 (==5.0.4) ; python_version < \"3.10\"", "flake8-bugbear (==20.1.4) ; python_version < \"3.10\"", "flake8-isort (==4.2.0) ; python_version < \"3.10\"", "isort (==4.3.21)", "mypy (==0.812)", "pytest (>5.4.0) ; python_version >= \"3.6\"", "pytest-cov (>=2.10.0) ; python_version >= \"3.6\"", "requests (==2.23.0) ; python_version < \"3.10\"", "setuptools (==65.6.3) ; python_version >= \"3.7\"", "zest-releaser[recommended]"] +dev = ["Jinja2 (==2.11.1)", "MarkupSafe (==1.1.1)", "black", "certifi", "colorlog (==2.10.0)", "coverage", "fhirspec", "flake8 (==5.0.4)", "flake8-bugbear (==20.1.4)", "flake8-isort (==4.2.0)", "isort (==4.3.21)", "mypy (==0.812)", "pytest (>5.4.0)", "pytest-cov (>=2.10.0)", "requests (==2.23.0)", "setuptools (==65.6.3)", "zest-releaser[recommended]"] orjson = ["orjson (>=3.4.3)"] -test = ["PyYAML (>=5.4.1)", "black", "coverage", "flake8 (==5.0.4) ; python_version < \"3.10\"", "flake8-bugbear (==20.1.4) ; python_version < \"3.10\"", "flake8-isort (==4.2.0) ; python_version < \"3.10\"", "isort (==4.3.21)", "lxml", "mypy (==0.812)", "orjson (>=3.4.3)", "pytest (>5.4.0) ; python_version >= \"3.6\"", "pytest-cov (>=2.10.0) ; python_version >= \"3.6\"", "pytest-runner", "requests (==2.23.0) ; python_version < \"3.10\"", "setuptools (==65.6.3) ; python_version >= \"3.7\""] +test = ["PyYAML (>=5.4.1)", "black", "coverage", "flake8 (==5.0.4)", "flake8-bugbear (==20.1.4)", "flake8-isort (==4.2.0)", "isort (==4.3.21)", "lxml", "mypy (==0.812)", "orjson (>=3.4.3)", "pytest (>5.4.0)", "pytest-cov (>=2.10.0)", "pytest-runner", "requests (==2.23.0)", "setuptools (==65.6.3)"] xml = ["lxml"] yaml = ["PyYAML (>=5.4.1)"] @@ -878,7 +858,6 @@ version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, @@ -893,7 +872,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -908,7 +886,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -926,7 +903,6 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -938,7 +914,6 @@ version = "1.7.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c"}, {file = "jsonpath_ng-1.7.0-py2-none-any.whl", hash = "sha256:898c93fc173f0c336784a3fa63d7434297544b7198124a68f9a3ef9597b0ae6e"}, @@ -954,7 +929,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1025,7 +999,6 @@ version = "5.1.4" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, @@ -1071,7 +1044,6 @@ version = "1.26.164" description = "Type annotations for boto3.DynamoDB 1.26.164 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "mypy-boto3-dynamodb-1.26.164.tar.gz", hash = "sha256:5a832531ac2c81b01dea20ef79f7dd5a2014c3736566a498585f5f46d642adc4"}, {file = "mypy_boto3_dynamodb-1.26.164-py3-none-any.whl", hash = "sha256:a527270b304f1a517093fff3709c7831fc5616a91bb1c9b6164fa71e37481d84"}, @@ -1083,7 +1055,6 @@ version = "3.11" description = "Python Lex & Yacc" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, @@ -1095,7 +1066,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -1107,7 +1077,6 @@ version = "1.10.21" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "pydantic-1.10.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:245e486e0fec53ec2366df9cf1cba36e0bbf066af7cd9c974bbbd9ba10e1e586"}, {file = "pydantic-1.10.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c54f8d4c151c1de784c5b93dfbb872067e3414619e10e21e695f7bb84d1d1fd"}, @@ -1175,7 +1144,6 @@ version = "2.8.0" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, @@ -1193,7 +1161,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1208,7 +1175,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1271,7 +1237,6 @@ version = "5.2.1" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4"}, {file = "redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f"}, @@ -1290,7 +1255,6 @@ version = "2.31.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, @@ -1312,7 +1276,6 @@ version = "0.24.1" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "responses-0.24.1-py3-none-any.whl", hash = "sha256:a2b43f4c08bfb9c9bd242568328c65a34b318741d3fab884ac843c5ceeb543f9"}, {file = "responses-0.24.1.tar.gz", hash = "sha256:b127c6ca3f8df0eb9cc82fd93109a3007a86acb24871834c47b77765152ecf8c"}, @@ -1324,7 +1287,7 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "s3transfer" @@ -1332,7 +1295,6 @@ version = "0.12.0" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "s3transfer-0.12.0-py3-none-any.whl", hash = "sha256:35b314d7d82865756edab59f7baebc6b477189e6ab4c53050e28c1de4d9cce18"}, {file = "s3transfer-0.12.0.tar.gz", hash = "sha256:8ac58bc1989a3fdb7c7f3ee0918a66b160d038a147c7b5db1500930a607e9a1c"}, @@ -1350,7 +1312,6 @@ version = "3.19.3" description = "Simple, fast, extensible JSON encoder/decoder for Python" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.5" -groups = ["main"] files = [ {file = "simplejson-3.19.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f39caec26007a2d0efab6b8b1d74873ede9351962707afab622cc2285dd26ed0"}, {file = "simplejson-3.19.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:83c87706265ae3028e8460d08b05f30254c569772e859e5ba61fe8af2c883468"}, @@ -1470,7 +1431,6 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -1482,7 +1442,6 @@ version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, @@ -1494,7 +1453,6 @@ version = "24.4.0" description = "Structured Logging for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610"}, {file = "structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4"}, @@ -1512,7 +1470,6 @@ version = "0.23.9" description = "Type annotations and code completion for awscrt" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "types_awscrt-0.23.9-py3-none-any.whl", hash = "sha256:71181a6c5188352ae934e74a7633d80c82ac5c6f89054bd7d653bb1b5bba240b"}, {file = "types_awscrt-0.23.9.tar.gz", hash = "sha256:57ec68d45ef873458df7307ec80578a6334696f088549ab349c3d655e7e3562b"}, @@ -1524,7 +1481,6 @@ version = "0.11.2" description = "Type annotations and code completion for s3transfer" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "types_s3transfer-0.11.2-py3-none-any.whl", hash = "sha256:09c31cff8c79a433fcf703b840b66d1f694a6c70c410ef52015dd4fe07ee0ae2"}, {file = "types_s3transfer-0.11.2.tar.gz", hash = "sha256:3ccb8b90b14434af2fb0d6c08500596d93f3a83fb804a2bb843d9bf4f7c2ca60"}, @@ -1536,7 +1492,6 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1548,15 +1503,14 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [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"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -1565,7 +1519,6 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -1583,13 +1536,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "~3.10" -content-hash = "29071fe5f1fe9920bc5316087c3ef58ceb94c54917cf22662f207c4dd75a6a1d" +content-hash = "ea582438fa201fbbc4bed73427c932c6c716e3e57fd300371b5d4c9bfb77606a" diff --git a/filenameprocessor/pyproject.toml b/filenameprocessor/pyproject.toml index da1d0a2348..38210f0610 100644 --- a/filenameprocessor/pyproject.toml +++ b/filenameprocessor/pyproject.toml @@ -23,7 +23,7 @@ jsonpath-ng = "^1.6.0" simplejson = "^3.19.2" structlog = "^24.1.0" redis = "^5.1.1" -coverage = "7.6.1" +coverage = "^7.8.0" freezegun = "^1.5.1" fakeredis = "^2.0.0" diff --git a/mesh_processor/poetry.lock b/mesh_processor/poetry.lock index 2ad9c9109c..8048a0e30d 100644 --- a/mesh_processor/poetry.lock +++ b/mesh_processor/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "boto3" @@ -6,7 +6,6 @@ version = "1.38.17" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "boto3-1.38.17-py3-none-any.whl", hash = "sha256:9b56c98fe7acb6559c24dacd838989878c60f3df2fb8ca5f311128419fd9f953"}, {file = "boto3-1.38.17.tar.gz", hash = "sha256:6058feef976ece2878ad3555f39933e63d20d02e2bbd40610ab2926d4555710a"}, @@ -26,7 +25,6 @@ version = "1.38.17" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "botocore-1.38.17-py3-none-any.whl", hash = "sha256:ec75cf02fbd3dbec18187085ce387761eab16afdccfd0774fd168db3689c6cb6"}, {file = "botocore-1.38.17.tar.gz", hash = "sha256:f2db4c4bdcfbc41d78bfe73b9affe7d217c7840f8ce120cff815536969418b18"}, @@ -46,7 +44,6 @@ version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, @@ -58,8 +55,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -139,7 +134,6 @@ version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, @@ -235,13 +229,91 @@ files = [ {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] +[[package]] +name = "coverage" +version = "7.8.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "cryptography" version = "44.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] files = [ {file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"}, @@ -284,10 +356,10 @@ files = [ cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] -pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] @@ -299,7 +371,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -314,7 +385,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -332,7 +402,6 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -344,7 +413,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -415,7 +483,6 @@ version = "5.1.4" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, @@ -461,7 +528,6 @@ version = "1.38.4" description = "Type annotations for boto3 DynamoDB 1.38.4 service generated with mypy-boto3-builder 8.10.1" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "mypy_boto3_dynamodb-1.38.4-py3-none-any.whl", hash = "sha256:6b29d89c649eeb1e894118bee002cb8b1304c78da735b1503aa08e46b0abfdec"}, {file = "mypy_boto3_dynamodb-1.38.4.tar.gz", hash = "sha256:5cf3787631e312b3d75f89a6cbbbd4ad786a76f5d565af023febf03fbf23c0b5"}, @@ -476,8 +542,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -489,7 +553,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -504,7 +567,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -567,7 +629,6 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -589,7 +650,6 @@ version = "0.25.7" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "responses-0.25.7-py3-none-any.whl", hash = "sha256:92ca17416c90fe6b35921f52179bff29332076bb32694c0df02dcac2c6bc043c"}, {file = "responses-0.25.7.tar.gz", hash = "sha256:8ebae11405d7a5df79ab6fd54277f6f2bc29b2d002d0dd2d5c632594d1ddcedb"}, @@ -601,7 +661,7 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "s3transfer" @@ -609,7 +669,6 @@ version = "0.12.0" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "s3transfer-0.12.0-py3-none-any.whl", hash = "sha256:35b314d7d82865756edab59f7baebc6b477189e6ab4c53050e28c1de4d9cce18"}, {file = "s3transfer-0.12.0.tar.gz", hash = "sha256:8ac58bc1989a3fdb7c7f3ee0918a66b160d038a147c7b5db1500930a607e9a1c"}, @@ -627,7 +686,6 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -639,7 +697,6 @@ version = "4.13.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5"}, {file = "typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b"}, @@ -651,15 +708,14 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [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"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -668,7 +724,6 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -686,13 +741,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "~3.10" -content-hash = "331f9834b925ee92e5a654fa4be54eb15c864661d251777d9cd9f04fbcce6a11" +content-hash = "bcf9e951212ef2d6c4bf26ed940dfa71cdd4d9639702897dd68132b8f9b7289e" diff --git a/mesh_processor/pyproject.toml b/mesh_processor/pyproject.toml index 7679a56949..56eb2c8191 100644 --- a/mesh_processor/pyproject.toml +++ b/mesh_processor/pyproject.toml @@ -11,6 +11,7 @@ python = "~3.10" boto3 = "~1.38.17" mypy-boto3-dynamodb = "^1.38.4" moto = "~5.1.4" +coverage = "^7.8.0" [build-system] requires = ["poetry-core"] diff --git a/recordprocessor/poetry.lock b/recordprocessor/poetry.lock index 5f15cf79ec..a4014c35d0 100644 --- a/recordprocessor/poetry.lock +++ b/recordprocessor/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aws-lambda-typing" @@ -6,7 +6,6 @@ version = "2.18.0" description = "A package that provides type hints for AWS Lambda event, context and response objects" optional = false python-versions = ">=3.6,<4.0" -groups = ["main"] files = [ {file = "aws-lambda-typing-2.18.0.tar.gz", hash = "sha256:2725cb620ee3e36c2175faa94c8faeed25823bd3b6ec738e08dcb7e29b18d0d0"}, {file = "aws_lambda_typing-2.18.0-py3-none-any.whl", hash = "sha256:a2be544aa508a7c8abfa7f9b59c661f2ce4a74fd03dbe37f8cd8ea70f57c5502"}, @@ -18,7 +17,6 @@ version = "1.38.17" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "boto3-1.38.17-py3-none-any.whl", hash = "sha256:9b56c98fe7acb6559c24dacd838989878c60f3df2fb8ca5f311128419fd9f953"}, {file = "boto3-1.38.17.tar.gz", hash = "sha256:6058feef976ece2878ad3555f39933e63d20d02e2bbd40610ab2926d4555710a"}, @@ -38,7 +36,6 @@ version = "1.26.165" description = "Type annotations for boto3 1.26.165 generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "boto3-stubs-lite-1.26.165.tar.gz", hash = "sha256:56fe506b9b94dbeefaf53fc0fbc332258c87011606ff9c7a51fd2017a51ec220"}, {file = "boto3_stubs_lite-1.26.165-py3-none-any.whl", hash = "sha256:9340fe195c7309b4db6fe50eb146f49625b9fcfa4c7a8bd642ceaeb6087610cc"}, @@ -410,7 +407,6 @@ version = "1.38.17" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "botocore-1.38.17-py3-none-any.whl", hash = "sha256:ec75cf02fbd3dbec18187085ce387761eab16afdccfd0774fd168db3689c6cb6"}, {file = "botocore-1.38.17.tar.gz", hash = "sha256:f2db4c4bdcfbc41d78bfe73b9affe7d217c7840f8ce120cff815536969418b18"}, @@ -430,7 +426,6 @@ version = "1.35.68" description = "Type annotations and code completion for botocore" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "botocore_stubs-1.35.68-py3-none-any.whl", hash = "sha256:4563178783cb2cc894bbec94cc06143fd6d5249f293c164b012c1a97471bce9a"}, {file = "botocore_stubs-1.35.68.tar.gz", hash = "sha256:658d17ab2c5caef07e08aefc86ce7ae8e50fb3b54b5a4f28ed6adae135c5db10"}, @@ -448,7 +443,6 @@ version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, @@ -460,7 +454,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -540,7 +533,6 @@ version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, @@ -649,13 +641,91 @@ files = [ {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] +[[package]] +name = "coverage" +version = "7.8.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a"}, + {file = "coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6"}, + {file = "coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3"}, + {file = "coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404"}, + {file = "coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7"}, + {file = "coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9"}, + {file = "coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5"}, + {file = "coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb"}, + {file = "coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54"}, + {file = "coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a"}, + {file = "coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975"}, + {file = "coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c"}, + {file = "coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99"}, + {file = "coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57"}, + {file = "coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f"}, + {file = "coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8"}, + {file = "coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223"}, + {file = "coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca"}, + {file = "coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257"}, + {file = "coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050"}, + {file = "coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48"}, + {file = "coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7"}, + {file = "coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3"}, + {file = "coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008"}, + {file = "coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be"}, + {file = "coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b"}, + {file = "coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199"}, + {file = "coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8"}, + {file = "coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d"}, + {file = "coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a"}, + {file = "coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d"}, + {file = "coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3"}, + {file = "coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7"}, + {file = "coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a"}, + {file = "coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e"}, + {file = "coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837"}, + {file = "coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32"}, + {file = "coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "cryptography" version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, @@ -710,7 +780,6 @@ version = "2.7.0" description = "DNS toolkit" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, @@ -731,7 +800,6 @@ version = "2.2.0" description = "A robust email address syntax and deliverability validation library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"}, {file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"}, @@ -747,7 +815,6 @@ version = "7.0.2" description = "FHIR Resources as Model Class" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "fhir.resources-7.0.2-py2.py3-none-any.whl", hash = "sha256:ba16b3348821614650dd2e7f04db170210ce4406f65a5cc873beb10317d595ff"}, {file = "fhir.resources-7.0.2.tar.gz", hash = "sha256:1e6392f7bc3b143463b07ada87a3b6a92dd8fe97947670423317fea69226f6de"}, @@ -758,9 +825,9 @@ pydantic = {version = ">=1.7.2,<2.0.0", extras = ["email"]} [package.extras] all = ["PyYAML (>=5.4.1)", "lxml", "orjson (>=3.4.3)"] -dev = ["Jinja2 (==2.11.1)", "MarkupSafe (==1.1.1)", "black", "certifi", "colorlog (==2.10.0)", "coverage", "fhirspec", "flake8 (==5.0.4) ; python_version < \"3.10\"", "flake8-bugbear (==20.1.4) ; python_version < \"3.10\"", "flake8-isort (==4.2.0) ; python_version < \"3.10\"", "isort (==4.3.21)", "mypy (==0.812)", "pytest (>5.4.0) ; python_version >= \"3.6\"", "pytest-cov (>=2.10.0) ; python_version >= \"3.6\"", "requests (==2.23.0) ; python_version < \"3.10\"", "setuptools (==65.6.3) ; python_version >= \"3.7\"", "zest-releaser[recommended]"] +dev = ["Jinja2 (==2.11.1)", "MarkupSafe (==1.1.1)", "black", "certifi", "colorlog (==2.10.0)", "coverage", "fhirspec", "flake8 (==5.0.4)", "flake8-bugbear (==20.1.4)", "flake8-isort (==4.2.0)", "isort (==4.3.21)", "mypy (==0.812)", "pytest (>5.4.0)", "pytest-cov (>=2.10.0)", "requests (==2.23.0)", "setuptools (==65.6.3)", "zest-releaser[recommended]"] orjson = ["orjson (>=3.4.3)"] -test = ["PyYAML (>=5.4.1)", "black", "coverage", "flake8 (==5.0.4) ; python_version < \"3.10\"", "flake8-bugbear (==20.1.4) ; python_version < \"3.10\"", "flake8-isort (==4.2.0) ; python_version < \"3.10\"", "isort (==4.3.21)", "lxml", "mypy (==0.812)", "orjson (>=3.4.3)", "pytest (>5.4.0) ; python_version >= \"3.6\"", "pytest-cov (>=2.10.0) ; python_version >= \"3.6\"", "pytest-runner", "requests (==2.23.0) ; python_version < \"3.10\"", "setuptools (==65.6.3) ; python_version >= \"3.7\""] +test = ["PyYAML (>=5.4.1)", "black", "coverage", "flake8 (==5.0.4)", "flake8-bugbear (==20.1.4)", "flake8-isort (==4.2.0)", "isort (==4.3.21)", "lxml", "mypy (==0.812)", "orjson (>=3.4.3)", "pytest (>5.4.0)", "pytest-cov (>=2.10.0)", "pytest-runner", "requests (==2.23.0)", "setuptools (==65.6.3)"] xml = ["lxml"] yaml = ["PyYAML (>=5.4.1)"] @@ -770,7 +837,6 @@ version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, @@ -785,7 +851,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -800,7 +865,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -818,7 +882,6 @@ version = "1.0.1" description = "JSON Matching Expressions" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, @@ -830,7 +893,6 @@ version = "1.7.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c"}, {file = "jsonpath_ng-1.7.0-py2-none-any.whl", hash = "sha256:898c93fc173f0c336784a3fa63d7434297544b7198124a68f9a3ef9597b0ae6e"}, @@ -846,7 +908,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -917,7 +978,6 @@ version = "5.1.4" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, @@ -963,7 +1023,6 @@ version = "1.26.164" description = "Type annotations for boto3.DynamoDB 1.26.164 service generated with mypy-boto3-builder 7.14.5" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "mypy-boto3-dynamodb-1.26.164.tar.gz", hash = "sha256:5a832531ac2c81b01dea20ef79f7dd5a2014c3736566a498585f5f46d642adc4"}, {file = "mypy_boto3_dynamodb-1.26.164-py3-none-any.whl", hash = "sha256:a527270b304f1a517093fff3709c7831fc5616a91bb1c9b6164fa71e37481d84"}, @@ -975,7 +1034,6 @@ version = "2.1.3" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "numpy-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff"}, {file = "numpy-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5"}, @@ -1040,7 +1098,6 @@ version = "2.2.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, @@ -1123,7 +1180,6 @@ version = "3.11" description = "Python Lex & Yacc" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, @@ -1135,7 +1191,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -1147,7 +1202,6 @@ version = "1.10.19" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "pydantic-1.10.19-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a415b9e95fa602b10808113967f72b2da8722061265d6af69268c111c254832d"}, {file = "pydantic-1.10.19-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:11965f421f7eb026439d4eb7464e9182fe6d69c3d4d416e464a4485d1ba61ab6"}, @@ -1208,7 +1262,6 @@ version = "2.8.0" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, @@ -1226,7 +1279,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1241,7 +1293,6 @@ version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, @@ -1253,7 +1304,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1316,7 +1366,6 @@ version = "2.31.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, @@ -1338,7 +1387,6 @@ version = "0.24.1" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "responses-0.24.1-py3-none-any.whl", hash = "sha256:a2b43f4c08bfb9c9bd242568328c65a34b318741d3fab884ac843c5ceeb543f9"}, {file = "responses-0.24.1.tar.gz", hash = "sha256:b127c6ca3f8df0eb9cc82fd93109a3007a86acb24871834c47b77765152ecf8c"}, @@ -1350,7 +1398,7 @@ requests = ">=2.30.0,<3.0" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-PyYAML", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] [[package]] name = "s3transfer" @@ -1358,7 +1406,6 @@ version = "0.12.0" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "s3transfer-0.12.0-py3-none-any.whl", hash = "sha256:35b314d7d82865756edab59f7baebc6b477189e6ab4c53050e28c1de4d9cce18"}, {file = "s3transfer-0.12.0.tar.gz", hash = "sha256:8ac58bc1989a3fdb7c7f3ee0918a66b160d038a147c7b5db1500930a607e9a1c"}, @@ -1376,7 +1423,6 @@ version = "3.19.3" description = "Simple, fast, extensible JSON encoder/decoder for Python" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.5" -groups = ["main"] files = [ {file = "simplejson-3.19.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f39caec26007a2d0efab6b8b1d74873ede9351962707afab622cc2285dd26ed0"}, {file = "simplejson-3.19.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:83c87706265ae3028e8460d08b05f30254c569772e859e5ba61fe8af2c883468"}, @@ -1496,7 +1542,6 @@ version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -1508,7 +1553,6 @@ version = "24.4.0" description = "Structured Logging for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "structlog-24.4.0-py3-none-any.whl", hash = "sha256:597f61e80a91cc0749a9fd2a098ed76715a1c8a01f73e336b746504d1aad7610"}, {file = "structlog-24.4.0.tar.gz", hash = "sha256:b27bfecede327a6d2da5fbc96bd859f114ecc398a6389d664f62085ee7ae6fc4"}, @@ -1526,7 +1570,6 @@ version = "0.23.0" description = "Type annotations and code completion for awscrt" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "types_awscrt-0.23.0-py3-none-any.whl", hash = "sha256:517d9d06f19cf58d778ca90ad01e52e0489466bf70dcf78c7f47f74fdf151a60"}, {file = "types_awscrt-0.23.0.tar.gz", hash = "sha256:3fd1edeac923d1956c0e907c973fb83bda465beae7f054716b371b293f9b5fdc"}, @@ -1538,7 +1581,6 @@ version = "0.10.4" description = "Type annotations and code completion for s3transfer" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "types_s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:22ac1aabc98f9d7f2928eb3fb4d5c02bf7435687f0913345a97dd3b84d0c217d"}, {file = "types_s3transfer-0.10.4.tar.gz", hash = "sha256:03123477e3064c81efe712bf9d372c7c72f2790711431f9baa59cf96ea607267"}, @@ -1550,7 +1592,6 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1562,7 +1603,6 @@ version = "2024.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["main"] files = [ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, @@ -1574,15 +1614,14 @@ version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] files = [ {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [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"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -1591,7 +1630,6 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -1609,13 +1647,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "~3.10" -content-hash = "42310bcc15c1ba89a768d30f62d35a41732c841c87f1f18cab37df5b78a89f5c" +content-hash = "fdb658b3f3c37de7b412c795c82f2b5a84818f403dc81dbc1c9b3dd82017ddd4" diff --git a/recordprocessor/pyproject.toml b/recordprocessor/pyproject.toml index d38746da97..c7a802d397 100644 --- a/recordprocessor/pyproject.toml +++ b/recordprocessor/pyproject.toml @@ -24,6 +24,7 @@ simplejson = "^3.19.2" structlog = "^24.1.0" pandas = "^2.2.3" freezegun = "^1.5.1" +coverage = "^7.8.0" [build-system] requires = ["poetry-core ~= 1.5.0"] From cc1efcb51ad99ff46688a351d51eed835e6f9c74 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 30 May 2025 11:53:03 +0100 Subject: [PATCH 11/24] VED-305: Downgrade moto where it's causing issues. Remove custom PYTHONPATH for recordforwarder tests. --- .github/workflows/sonarcloud.yml | 2 -- ack_backend/poetry.lock | 47 ++++++++++++++++---------------- ack_backend/pyproject.toml | 2 +- filenameprocessor/poetry.lock | 47 ++++++++++++++++---------------- filenameprocessor/pyproject.toml | 2 +- recordprocessor/poetry.lock | 47 ++++++++++++++++---------------- recordprocessor/pyproject.toml | 2 +- 7 files changed, 72 insertions(+), 77 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 0bd7f1b59d..d6bad3a83b 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -58,8 +58,6 @@ jobs: - name: Run unittest with recordforwarder-coverage working-directory: backend id: recordforwarder - env: - PYTHONPATH: backend/src:backend/tests continue-on-error: true run: | poetry env use 3.11 diff --git a/ack_backend/poetry.lock b/ack_backend/poetry.lock index d5947cee51..0a1b813f3f 100644 --- a/ack_backend/poetry.lock +++ b/ack_backend/poetry.lock @@ -498,47 +498,46 @@ files = [ [[package]] name = "moto" -version = "5.1.4" -description = "A library that allows you to easily mock out tests based on AWS infrastructure" +version = "4.2.14" +description = "" optional = false -python-versions = ">=3.9" +python-versions = ">=3.7" files = [ - {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, - {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, + {file = "moto-4.2.14-py2.py3-none-any.whl", hash = "sha256:6d242dbbabe925bb385ddb6958449e5c827670b13b8e153ed63f91dbdb50372c"}, + {file = "moto-4.2.14.tar.gz", hash = "sha256:8f9263ca70b646f091edcc93e97cda864a542e6d16ed04066b1370ed217bd190"}, ] [package.dependencies] boto3 = ">=1.9.201" -botocore = ">=1.20.88,<1.35.45 || >1.35.45,<1.35.46 || >1.35.46" -cryptography = ">=35.0.0" +botocore = ">=1.12.201" +cryptography = ">=3.3.1" Jinja2 = ">=2.10.1" python-dateutil = ">=2.1,<3.0.0" requests = ">=2.5" -responses = ">=0.15.0,<0.25.5 || >0.25.5" +responses = ">=0.13.0" werkzeug = ">=0.5,<2.2.0 || >2.2.0,<2.2.1 || >2.2.1" xmltodict = "*" [package.extras] -all = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "jsonschema", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -apigateway = ["PyYAML (>=5.1)", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)"] -apigatewayv2 = ["PyYAML (>=5.1)", "openapi-spec-validator (>=0.5.0)"] +all = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +apigateway = ["PyYAML (>=5.1)", "ecdsa (!=0.15)", "openapi-spec-validator (>=0.5.0)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +apigatewayv2 = ["PyYAML (>=5.1)"] appsync = ["graphql-core"] awslambda = ["docker (>=3.0.0)"] batch = ["docker (>=3.0.0)"] -cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -cognitoidp = ["joserfc (>=0.9.0)"] -dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.6.1)"] -dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.6.1)"] -events = ["jsonpath_ng"] +cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] +dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] +ec2 = ["sshpubkeys (>=3.1.0)"] glue = ["pyparsing (>=3.0.7)"] -proxy = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -quicksight = ["jsonschema"] -resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)"] -s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.6.1)"] -s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.6.1)"] -server = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] +iotdata = ["jsondiff (>=1.1.2)"] +proxy = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.5.0)"] +s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.5.0)"] +server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] ssm = ["PyYAML (>=5.1)"] -stepfunctions = ["antlr4-python3-runtime", "jsonpath_ng"] xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"] [[package]] @@ -768,4 +767,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "~3.10" -content-hash = "6dcc58b41268bee85d7fc1d788554e74fc9cefc10d1f686a81fb63fefaa55150" +content-hash = "2f61b5f408dbc36f7297e05d3d907e0cd4d70133b8f23b7a74a62b7fc15047b8" diff --git a/ack_backend/pyproject.toml b/ack_backend/pyproject.toml index cc9183ad82..98a158b1c2 100644 --- a/ack_backend/pyproject.toml +++ b/ack_backend/pyproject.toml @@ -10,7 +10,7 @@ python = "~3.10" boto3 = "~1.38.17" mypy-boto3-dynamodb = "^1.38.4" freezegun = "^1.5.1" -moto = "~5.1.4" +moto = "^4" coverage = "^7.8.0" diff --git a/filenameprocessor/poetry.lock b/filenameprocessor/poetry.lock index 6c9b04ffb8..2cc0831179 100644 --- a/filenameprocessor/poetry.lock +++ b/filenameprocessor/poetry.lock @@ -995,47 +995,46 @@ files = [ [[package]] name = "moto" -version = "5.1.4" -description = "A library that allows you to easily mock out tests based on AWS infrastructure" +version = "4.2.14" +description = "" optional = false -python-versions = ">=3.9" +python-versions = ">=3.7" files = [ - {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, - {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, + {file = "moto-4.2.14-py2.py3-none-any.whl", hash = "sha256:6d242dbbabe925bb385ddb6958449e5c827670b13b8e153ed63f91dbdb50372c"}, + {file = "moto-4.2.14.tar.gz", hash = "sha256:8f9263ca70b646f091edcc93e97cda864a542e6d16ed04066b1370ed217bd190"}, ] [package.dependencies] boto3 = ">=1.9.201" -botocore = ">=1.20.88,<1.35.45 || >1.35.45,<1.35.46 || >1.35.46" -cryptography = ">=35.0.0" +botocore = ">=1.12.201" +cryptography = ">=3.3.1" Jinja2 = ">=2.10.1" python-dateutil = ">=2.1,<3.0.0" requests = ">=2.5" -responses = ">=0.15.0,<0.25.5 || >0.25.5" +responses = ">=0.13.0" werkzeug = ">=0.5,<2.2.0 || >2.2.0,<2.2.1 || >2.2.1" xmltodict = "*" [package.extras] -all = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "jsonschema", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -apigateway = ["PyYAML (>=5.1)", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)"] -apigatewayv2 = ["PyYAML (>=5.1)", "openapi-spec-validator (>=0.5.0)"] +all = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +apigateway = ["PyYAML (>=5.1)", "ecdsa (!=0.15)", "openapi-spec-validator (>=0.5.0)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +apigatewayv2 = ["PyYAML (>=5.1)"] appsync = ["graphql-core"] awslambda = ["docker (>=3.0.0)"] batch = ["docker (>=3.0.0)"] -cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -cognitoidp = ["joserfc (>=0.9.0)"] -dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.6.1)"] -dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.6.1)"] -events = ["jsonpath_ng"] +cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] +dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] +ec2 = ["sshpubkeys (>=3.1.0)"] glue = ["pyparsing (>=3.0.7)"] -proxy = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -quicksight = ["jsonschema"] -resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)"] -s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.6.1)"] -s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.6.1)"] -server = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] +iotdata = ["jsondiff (>=1.1.2)"] +proxy = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.5.0)"] +s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.5.0)"] +server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] ssm = ["PyYAML (>=5.1)"] -stepfunctions = ["antlr4-python3-runtime", "jsonpath_ng"] xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"] [[package]] @@ -1544,4 +1543,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "~3.10" -content-hash = "ea582438fa201fbbc4bed73427c932c6c716e3e57fd300371b5d4c9bfb77606a" +content-hash = "99f463bd2b7d6ba6a7603e534c703b6ec7fb55fae67d9633a2bf8e95f1363edd" diff --git a/filenameprocessor/pyproject.toml b/filenameprocessor/pyproject.toml index 38210f0610..116fc4463c 100644 --- a/filenameprocessor/pyproject.toml +++ b/filenameprocessor/pyproject.toml @@ -12,7 +12,7 @@ python = "~3.10" boto3 = "~1.38.17" boto3-stubs-lite = { extras = ["dynamodb"], version = "~1.26.90" } aws-lambda-typing = "~2.18.0" -moto = "~5.1.4" +moto = "^4" requests = "~2.31.0" responses = "~0.24.1" pydantic = "~1.10.13" diff --git a/recordprocessor/poetry.lock b/recordprocessor/poetry.lock index a4014c35d0..516feab552 100644 --- a/recordprocessor/poetry.lock +++ b/recordprocessor/poetry.lock @@ -974,47 +974,46 @@ files = [ [[package]] name = "moto" -version = "5.1.4" -description = "A library that allows you to easily mock out tests based on AWS infrastructure" +version = "4.2.14" +description = "" optional = false -python-versions = ">=3.9" +python-versions = ">=3.7" files = [ - {file = "moto-5.1.4-py3-none-any.whl", hash = "sha256:9a19d7a64c3f03824389cfbd478b64c82bd4d8da21b242a34259360d66cd108b"}, - {file = "moto-5.1.4.tar.gz", hash = "sha256:b339c3514f2986ebefa465671b688bdbf51796705702214b1bad46490b68507a"}, + {file = "moto-4.2.14-py2.py3-none-any.whl", hash = "sha256:6d242dbbabe925bb385ddb6958449e5c827670b13b8e153ed63f91dbdb50372c"}, + {file = "moto-4.2.14.tar.gz", hash = "sha256:8f9263ca70b646f091edcc93e97cda864a542e6d16ed04066b1370ed217bd190"}, ] [package.dependencies] boto3 = ">=1.9.201" -botocore = ">=1.20.88,<1.35.45 || >1.35.45,<1.35.46 || >1.35.46" -cryptography = ">=35.0.0" +botocore = ">=1.12.201" +cryptography = ">=3.3.1" Jinja2 = ">=2.10.1" python-dateutil = ">=2.1,<3.0.0" requests = ">=2.5" -responses = ">=0.15.0,<0.25.5 || >0.25.5" +responses = ">=0.13.0" werkzeug = ">=0.5,<2.2.0 || >2.2.0,<2.2.1 || >2.2.1" xmltodict = "*" [package.extras] -all = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "jsonschema", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -apigateway = ["PyYAML (>=5.1)", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)"] -apigatewayv2 = ["PyYAML (>=5.1)", "openapi-spec-validator (>=0.5.0)"] +all = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +apigateway = ["PyYAML (>=5.1)", "ecdsa (!=0.15)", "openapi-spec-validator (>=0.5.0)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +apigatewayv2 = ["PyYAML (>=5.1)"] appsync = ["graphql-core"] awslambda = ["docker (>=3.0.0)"] batch = ["docker (>=3.0.0)"] -cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -cognitoidp = ["joserfc (>=0.9.0)"] -dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.6.1)"] -dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.6.1)"] -events = ["jsonpath_ng"] +cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] +dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] +ec2 = ["sshpubkeys (>=3.1.0)"] glue = ["pyparsing (>=3.0.7)"] -proxy = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] -quicksight = ["jsonschema"] -resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "graphql-core", "joserfc (>=0.9.0)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)"] -s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.6.1)"] -s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.6.1)"] -server = ["PyYAML (>=5.1)", "antlr4-python3-runtime", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "joserfc (>=0.9.0)", "jsonpath_ng", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.6.1)", "pyparsing (>=3.0.7)", "setuptools"] +iotdata = ["jsondiff (>=1.1.2)"] +proxy = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] +resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] +s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.5.0)"] +s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.5.0)"] +server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] ssm = ["PyYAML (>=5.1)"] -stepfunctions = ["antlr4-python3-runtime", "jsonpath_ng"] xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"] [[package]] @@ -1655,4 +1654,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "~3.10" -content-hash = "fdb658b3f3c37de7b412c795c82f2b5a84818f403dc81dbc1c9b3dd82017ddd4" +content-hash = "e8ebf5a333ca363ea7d78a4dc8009ab688ed4354a8bb1b476aa71121bf6d50fa" diff --git a/recordprocessor/pyproject.toml b/recordprocessor/pyproject.toml index c7a802d397..9bb3e2561a 100644 --- a/recordprocessor/pyproject.toml +++ b/recordprocessor/pyproject.toml @@ -12,7 +12,7 @@ python = "~3.10" boto3 = "~1.38.17" boto3-stubs-lite = {extras = ["dynamodb"], version = "~1.26.90"} aws-lambda-typing = "~2.18.0" -moto = "~5.1.4" +moto = "^4" requests = "~2.31.0" responses = "~0.24.1" pydantic = "~1.10.13" From bd2c65b868098570278d3f9403d3c8710b08f8f1 Mon Sep 17 00:00:00 2001 From: Matt Jarvis Date: Fri, 30 May 2025 12:07:16 +0100 Subject: [PATCH 12/24] VED-305: Only search tests directory for tests. --- .github/workflows/sonarcloud.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index d6bad3a83b..603033d709 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -55,6 +55,7 @@ jobs: poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml + # This step is redundant - all of these tests will be run in the backend step below - name: Run unittest with recordforwarder-coverage working-directory: backend id: recordforwarder @@ -62,7 +63,7 @@ jobs: run: | poetry env use 3.11 poetry install - poetry run coverage run -m unittest discover -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt + poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda From 5d5f2e234d107d075104624cefc2657b9c9b83d1 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Fri, 30 May 2025 14:47:10 +0100 Subject: [PATCH 13/24] May 30 --- .github/scripts/run_test.sh | 20 ++++++++++ .github/workflows/sonarcloud.yml | 67 ++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 29 deletions(-) create mode 100755 .github/scripts/run_test.sh diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh new file mode 100755 index 0000000000..3fc83d0607 --- /dev/null +++ b/.github/scripts/run_test.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -e + +PYTHON_VERSION="$1" +DESCRIPTION="$2" +COVERAGE_XML="sonarcloud-coverage-$3.xml" + +echo "Using Python $PYTHON_VERSION" +poetry env use "$PYTHON_VERSION" +poetry config virtualenvs.in-project true +poetry install + +if poetry run coverage run -m unittest discover; then + echo "$DESCRIPTION tests passed" +else + echo "$DESCRIPTION tests failed" >> ../failed_tests.txt +fi + +poetry run coverage xml -o "../$COVERAGE_XML" +# poetry env list --full-path | awk '{print $1}' | xargs -n 1 poetry env remove || true diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 603033d709..d6ecf6d893 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -6,6 +6,9 @@ on: - master pull_request: types: [labeled, opened, synchronize, reopened, unlabeled] +env: + SCRIPT_FOLDER: ./.github/scripts + TEST_SCRIPT: ../.github/scripts/run_test.sh jobs: sonarcloud: @@ -20,6 +23,16 @@ jobs: - name: Install poetry run: pip install poetry==1.8.4 + - uses: actions/setup-python@v5 + with: + python-version: | + 3.10 + 3.11 + cache: 'poetry' + + - name: Install poetry + run: pip install poetry==1.8.4 + - uses: actions/setup-python@v5 with: python-version: | @@ -35,46 +48,45 @@ jobs: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY + - name: Chmod .github directory + run: | + chmod +x $SCRIPT_FOLDER/*.sh + - name: Run unittest with filenameprocessor-coverage working-directory: filenameprocessor id: filenameprocessor continue-on-error: true run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml + $TEST_SCRIPT 3.10 \ + "filenameprocessor" \ + "filenameprocessor-coverage.xml" - name: Run unittest with recordprocessor-coverage working-directory: recordprocessor id: recordprocessor continue-on-error: true run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml + $TEST_SCRIPT 3.10 \ + "recordprocessor" \ + "recordprocessor-coverage.xml" - # This step is redundant - all of these tests will be run in the backend step below - name: Run unittest with recordforwarder-coverage working-directory: backend id: recordforwarder continue-on-error: true run: | - poetry env use 3.11 - poetry install - poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml + $TEST_SCRIPT 3.11 \ + "recordforwarder" \ + "recordforwarder-coverage.xml" - name: Run unittest with coverage-ack-lambda working-directory: ack_backend id: acklambda continue-on-error: true run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml + $TEST_SCRIPT 3.10 \ + "ack-lambda" \ + "ack-lambda.xml" - name: Run unittest with coverage-delta working-directory: delta_backend @@ -83,30 +95,27 @@ jobs: PYTHONPATH: delta_backend/src:delta_backend/tests continue-on-error: true run: | - poetry env use 3.11 - poetry install - poetry run coverage run -m unittest discover || echo "delta tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-delta.xml + $TEST_SCRIPT 3.11 \ + "delta" \ + "delta.xml" - name: Run unittest with coverage-fhir-api working-directory: backend id: fhirapi continue-on-error: true run: | - poetry env use 3.11 - poetry install - poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage.xml + $TEST_SCRIPT 3.11 \ + "fhir-api" \ + "fhir-api.xml" - name: Run unittest with coverage-mesh-processor working-directory: mesh_processor id: meshprocessor continue-on-error: true run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml + $TEST_SCRIPT 3.10 \ + "mesh_processor" \ + "mesh_processor-coverage.xml" - name: Run Test Failure Summary id: check_failure From dba9351a1e323cc88c269ce89e7f4153d2bd58ba Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Sat, 31 May 2025 15:21:18 +0100 Subject: [PATCH 14/24] May 31 --- .github/scripts/run_test.sh | 19 +++++-- .github/workflows/sonarcloud.yml | 97 +++++++++++++++++++++----------- 2 files changed, 79 insertions(+), 37 deletions(-) diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index 3fc83d0607..56d2029da0 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -5,10 +5,20 @@ PYTHON_VERSION="$1" DESCRIPTION="$2" COVERAGE_XML="sonarcloud-coverage-$3.xml" -echo "Using Python $PYTHON_VERSION" -poetry env use "$PYTHON_VERSION" +echo "Using Python $PYTHON_VERSION again" poetry config virtualenvs.in-project true -poetry install + +# Only create/use the env and install if .venv does not exist +echo "Checking for Poetry virtual environment (.venv)" +poetry env list +if [ ! -d ".venv" ]; then + echo "Creating virtual environment (.venv) with Poetry" + poetry env use "$PYTHON_VERSION" + poetry install + poetry env list +else + echo "Using cached virtual environment (.venv)" +fi if poetry run coverage run -m unittest discover; then echo "$DESCRIPTION tests passed" @@ -16,5 +26,4 @@ else echo "$DESCRIPTION tests failed" >> ../failed_tests.txt fi -poetry run coverage xml -o "../$COVERAGE_XML" -# poetry env list --full-path | awk '{print $1}' | xargs -n 1 poetry env remove || true +poetry run coverage xml -o "../$COVERAGE_XML" \ No newline at end of file diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index d6ecf6d893..01187b4b29 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -8,7 +8,7 @@ on: types: [labeled, opened, synchronize, reopened, unlabeled] env: SCRIPT_FOLDER: ./.github/scripts - TEST_SCRIPT: ../.github/scripts/run_test.sh + TEST_SCRIPT: source ../.github/scripts/run_test.sh jobs: sonarcloud: @@ -23,16 +23,6 @@ jobs: - name: Install poetry run: pip install poetry==1.8.4 - - uses: actions/setup-python@v5 - with: - python-version: | - 3.10 - 3.11 - cache: 'poetry' - - - name: Install poetry - run: pip install poetry==1.8.4 - - uses: actions/setup-python@v5 with: python-version: | @@ -51,8 +41,51 @@ jobs: - name: Chmod .github directory run: | chmod +x $SCRIPT_FOLDER/*.sh - - - name: Run unittest with filenameprocessor-coverage + + - name: Set Poetry to use in-project venvs + run: poetry config virtualenvs.in-project true + + - name: Cache Poetry virtualenv (filenameprocessor) + uses: actions/cache@v4 + with: + path: ./filenameprocessor/.venv + key: ${{ runner.os }}-venv-filenameprocessor-${{ hashFiles('filenameprocessor/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-venv-filenameprocessor- + + - name: Cache Poetry virtualenv (recordprocessor) + uses: actions/cache@v4 + with: + path: ./recordprocessor/.venv + key: ${{ runner.os }}-venv-recordprocessor-${{ hashFiles('recordprocessor/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-venv-recordprocessor- + + - name: Cache Poetry virtualenv (recordforwarder) + uses: actions/cache@v4 + with: + path: ./backend/.venv + key: ${{ runner.os }}-venv-backend-${{ hashFiles('backend/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-venv-backend- + + - name: Cache Poetry virtualenv (ack_backend) + uses: actions/cache@v4 + with: + path: ./ack_backend/.venv + key: ${{ runner.os }}-venv-ack_backend-${{ hashFiles('ack_backend/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-venv-ack_backend- + + - name: Cache Poetry virtualenv (delta_backend) + uses: actions/cache@v4 + with: + path: ./delta_backend/.venv + key: ${{ runner.os }}-venv-delta_backend-${{ hashFiles('delta_backend/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-venv-delta_backend- + + - name: Run unittest with filenameprocessor-coverage (S) working-directory: filenameprocessor id: filenameprocessor continue-on-error: true @@ -61,7 +94,7 @@ jobs: "filenameprocessor" \ "filenameprocessor-coverage.xml" - - name: Run unittest with recordprocessor-coverage + - name: Run unittest with recordprocessor-coverage (s) working-directory: recordprocessor id: recordprocessor continue-on-error: true @@ -96,26 +129,26 @@ jobs: continue-on-error: true run: | $TEST_SCRIPT 3.11 \ - "delta" \ + "delta_backend" \ "delta.xml" - - name: Run unittest with coverage-fhir-api - working-directory: backend - id: fhirapi - continue-on-error: true - run: | - $TEST_SCRIPT 3.11 \ - "fhir-api" \ - "fhir-api.xml" - - - name: Run unittest with coverage-mesh-processor - working-directory: mesh_processor - id: meshprocessor - continue-on-error: true - run: | - $TEST_SCRIPT 3.10 \ - "mesh_processor" \ - "mesh_processor-coverage.xml" + # - name: Run unittest with coverage-fhir-api + # working-directory: backend + # id: fhirapi + # continue-on-error: true + # run: | + # $TEST_SCRIPT 3.11 \ + # "fhir-api" \ + # "fhir-api.xml" + + # - name: Run unittest with coverage-mesh-processor + # working-directory: mesh_processor + # id: meshprocessor + # continue-on-error: true + # run: | + # $TEST_SCRIPT 3.10 \ + # "mesh_processor" \ + # "mesh_processor-coverage.xml" - name: Run Test Failure Summary id: check_failure From 2819041d850dc91f0fe733f2b53bd2769bcfb483 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Sun, 1 Jun 2025 17:51:18 +0100 Subject: [PATCH 15/24] 1 Jun --- .github/scripts/run_test.sh | 9 +- .github/workflows/sonarcloud.yml | 83 ++++++------- .github/workflows/sonarcloud.yml.Junk | 160 ++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/sonarcloud.yml.Junk diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index 56d2029da0..d5bddd46c4 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -5,7 +5,14 @@ PYTHON_VERSION="$1" DESCRIPTION="$2" COVERAGE_XML="sonarcloud-coverage-$3.xml" -echo "Using Python $PYTHON_VERSION again" +# show cwd +echo "Current working directory: $(pwd)" +# list contents of venv + +ls -la . + + +echo "Using Python Version $PYTHON_VERSION" poetry config virtualenvs.in-project true # Only create/use the env and install if .venv does not exist diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 01187b4b29..fbfa4f4705 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -8,13 +8,17 @@ on: types: [labeled, opened, synchronize, reopened, unlabeled] env: SCRIPT_FOLDER: ./.github/scripts - TEST_SCRIPT: source ../.github/scripts/run_test.sh + RUN_TEST: source ../.github/scripts/run_test.sh jobs: sonarcloud: name: SonarCloud runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10', '3.11'] + steps: - uses: actions/checkout@v4 with: @@ -25,9 +29,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: | - 3.10 - 3.11 + python-version: ${{ matrix.python-version }} cache: 'poetry' - name: Set up AWS credentials @@ -46,109 +48,88 @@ jobs: run: poetry config virtualenvs.in-project true - name: Cache Poetry virtualenv (filenameprocessor) + if: matrix.python-version == '3.10' uses: actions/cache@v4 with: path: ./filenameprocessor/.venv - key: ${{ runner.os }}-venv-filenameprocessor-${{ hashFiles('filenameprocessor/poetry.lock') }} + key: ${{ runner.os }}-venv-fp-py3.10-${{ hashFiles('filenameprocessor/poetry.lock') }} restore-keys: | - ${{ runner.os }}-venv-filenameprocessor- + ${{ runner.os }}-venv-fp-py3.10- - name: Cache Poetry virtualenv (recordprocessor) + if: matrix.python-version == '3.10' uses: actions/cache@v4 with: path: ./recordprocessor/.venv - key: ${{ runner.os }}-venv-recordprocessor-${{ hashFiles('recordprocessor/poetry.lock') }} + key: ${{ runner.os }}-venv-rp-py3.10-${{ hashFiles('recordprocessor/poetry.lock') }} restore-keys: | - ${{ runner.os }}-venv-recordprocessor- + ${{ runner.os }}-venv-rp-py3.10- - name: Cache Poetry virtualenv (recordforwarder) + if: matrix.python-version == '3.11' uses: actions/cache@v4 with: path: ./backend/.venv - key: ${{ runner.os }}-venv-backend-${{ hashFiles('backend/poetry.lock') }} + key: ${{ runner.os }}-venv-be-py3.11-${{ hashFiles('backend/poetry.lock') }} restore-keys: | - ${{ runner.os }}-venv-backend- + ${{ runner.os }}-venv-be-py3.11- - name: Cache Poetry virtualenv (ack_backend) + if: matrix.python-version == '3.10' uses: actions/cache@v4 with: path: ./ack_backend/.venv - key: ${{ runner.os }}-venv-ack_backend-${{ hashFiles('ack_backend/poetry.lock') }} + key: ${{ runner.os }}-venv-ack-py3.10-${{ hashFiles('ack_backend/poetry.lock') }} restore-keys: | - ${{ runner.os }}-venv-ack_backend- + ${{ runner.os }}-venv-ack-py3.10- - name: Cache Poetry virtualenv (delta_backend) + if: matrix.python-version == '3.11' uses: actions/cache@v4 with: path: ./delta_backend/.venv - key: ${{ runner.os }}-venv-delta_backend-${{ hashFiles('delta_backend/poetry.lock') }} + key: ${{ runner.os }}-venv-delta-py3.11-${{ hashFiles('delta_backend/poetry.lock') }} restore-keys: | - ${{ runner.os }}-venv-delta_backend- + ${{ runner.os }}-venv-delta-py3.11- - name: Run unittest with filenameprocessor-coverage (S) + if: matrix.python-version == '3.10' working-directory: filenameprocessor id: filenameprocessor continue-on-error: true - run: | - $TEST_SCRIPT 3.10 \ - "filenameprocessor" \ - "filenameprocessor-coverage.xml" + run: $RUN_TEST 3.10 filenameprocessor filenameprocessor-coverage.xml - name: Run unittest with recordprocessor-coverage (s) + if: matrix.python-version == '3.10' working-directory: recordprocessor id: recordprocessor continue-on-error: true - run: | - $TEST_SCRIPT 3.10 \ - "recordprocessor" \ - "recordprocessor-coverage.xml" + run: $RUN_TEST 3.10 recordprocessor recordprocessor-coverage.xml - name: Run unittest with recordforwarder-coverage + if: matrix.python-version == '3.11' working-directory: backend id: recordforwarder continue-on-error: true run: | - $TEST_SCRIPT 3.11 \ - "recordforwarder" \ - "recordforwarder-coverage.xml" + poetry config virtualenvs.in-project true + $RUN_TEST 3.11 recordforwarder recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda + if: matrix.python-version == '3.10' working-directory: ack_backend id: acklambda continue-on-error: true - run: | - $TEST_SCRIPT 3.10 \ - "ack-lambda" \ - "ack-lambda.xml" + run: $RUN_TEST 3.10 ack-lambda ack-lambda.xml - name: Run unittest with coverage-delta + if: matrix.python-version == '3.11' working-directory: delta_backend id: delta env: PYTHONPATH: delta_backend/src:delta_backend/tests continue-on-error: true - run: | - $TEST_SCRIPT 3.11 \ - "delta_backend" \ - "delta.xml" - - # - name: Run unittest with coverage-fhir-api - # working-directory: backend - # id: fhirapi - # continue-on-error: true - # run: | - # $TEST_SCRIPT 3.11 \ - # "fhir-api" \ - # "fhir-api.xml" - - # - name: Run unittest with coverage-mesh-processor - # working-directory: mesh_processor - # id: meshprocessor - # continue-on-error: true - # run: | - # $TEST_SCRIPT 3.10 \ - # "mesh_processor" \ - # "mesh_processor-coverage.xml" + run: $RUN_TEST 3.11 delta_backend delta.xml - name: Run Test Failure Summary id: check_failure diff --git a/.github/workflows/sonarcloud.yml.Junk b/.github/workflows/sonarcloud.yml.Junk new file mode 100644 index 0000000000..58f72de626 --- /dev/null +++ b/.github/workflows/sonarcloud.yml.Junk @@ -0,0 +1,160 @@ +name: SonarCloud + +on: + push: + branches: + - master + pull_request: + types: [labeled, opened, synchronize, reopened, unlabeled] +env: + SCRIPT_FOLDER: ./.github/scripts + TEST_SCRIPT: source ../.github/scripts/run_test.sh + +jobs: + sonarcloud: + name: SonarCloud + runs-on: ubuntu-latest + strategy: + matrix: + include: + - project: filenameprocessor + python-version: "3.10" + - project: recordprocessor + python-version: "3.10" + - project: backend + python-version: "3.11" + test-name: recordforwarder + coverage-file: recordforwarder-coverage.xml + - project: ack_backend + python-version: "3.10" + test-name: ack-lambda + coverage-file: ack-lambda.xml + - project: delta_backend + python-version: "3.11" + test-name: delta_backend + coverage-file: delta.xml + # Add more projects as needed + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install poetry + run: pip install poetry==1.8.4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + + + - name: Set up AWS credentials + env: + AWS_ACCESS_KEY_ID: "FOOBARKEY" + AWS_SECRET_ACCESS_KEY: "FOOBARSECRET" + run: | + aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID + aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY + + - name: Chmod .github directory + run: | + chmod +x $SCRIPT_FOLDER/*.sh + + - name: Set Poetry to use in-project venvs + run: poetry config virtualenvs.in-project true + + - name: Cache Poetry virtualenv + uses: actions/cache@v4 + with: + path: ./${{ matrix.project }}/.venv + key: ${{ runner.os }}-venv-${{ matrix.project }}-py${{ matrix.python-version }}-${{ hashFiles(format('{0}/poetry.lock', matrix.project)) }} + restore-keys: | + ${{ runner.os }}-venv-${{ matrix.project }}-py${{ matrix.python-version }}- + + - name: Run unittest with filenameprocessor-coverage (S) + working-directory: filenameprocessor + id: filenameprocessor + continue-on-error: true + run: | + $TEST_SCRIPT 3.10 \ + "filenameprocessor" \ + "filenameprocessor-coverage.xml" + + - name: Run unittest with recordprocessor-coverage (s) + working-directory: recordprocessor + id: recordprocessor + continue-on-error: true + run: | + $TEST_SCRIPT 3.10 \ + "recordprocessor" \ + "recordprocessor-coverage.xml" + + - name: Run unittest with recordforwarder-coverage + working-directory: backend + id: recordforwarder + continue-on-error: true + run: | + $TEST_SCRIPT 3.11 \ + "recordforwarder" \ + "recordforwarder-coverage.xml" + + - name: Run unittest with coverage-ack-lambda + working-directory: ack_backend + id: acklambda + continue-on-error: true + run: | + $TEST_SCRIPT 3.10 \ + "ack-lambda" \ + "ack-lambda.xml" + + - name: Run unittest with coverage-delta + working-directory: delta_backend + id: delta + env: + PYTHONPATH: delta_backend/src:delta_backend/tests + continue-on-error: true + run: | + $TEST_SCRIPT 3.11 \ + "delta_backend" \ + "delta.xml" + + # - name: Run unittest with coverage-fhir-api + # working-directory: backend + # id: fhirapi + # continue-on-error: true + # run: | + # $TEST_SCRIPT 3.11 \ + # "fhir-api" \ + # "fhir-api.xml" + + # - name: Run unittest with coverage-mesh-processor + # working-directory: mesh_processor + # id: meshprocessor + # continue-on-error: true + # run: | + # $TEST_SCRIPT 3.10 \ + # "mesh_processor" \ + # "mesh_processor-coverage.xml" + + - name: Run Test Failure Summary + id: check_failure + run: | + if [ -s failed_tests.txt ]; then + echo "The following tests failed:" + cat failed_tests.txt + + while IFS= read -r line; do + echo "##[error]Test Failures: $line" + done < failed_tests.txt + + exit 1 + else + echo "All tests passed." + fi + + - name: SonarCloud Scan + uses: SonarSource/sonarqube-scan-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} From 69df356b8559a8da2d530b828e0cb9517ec023df Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 08:41:22 +0100 Subject: [PATCH 16/24] 2 Jun --- .github/scripts/run_test copy.sh.save | 49 ++++++++ .github/scripts/run_test.sh | 13 ++- .github/workflows/sonarcloud.yml | 155 +++++++++++++------------- .github/workflows/sonarcloud.yml.test | 78 +++++++++++++ 4 files changed, 215 insertions(+), 80 deletions(-) create mode 100755 .github/scripts/run_test copy.sh.save create mode 100644 .github/workflows/sonarcloud.yml.test diff --git a/.github/scripts/run_test copy.sh.save b/.github/scripts/run_test copy.sh.save new file mode 100755 index 0000000000..a9118958f2 --- /dev/null +++ b/.github/scripts/run_test copy.sh.save @@ -0,0 +1,49 @@ +#!/bin/bash +set -e + +PYTHON_VERSION="$1" +DESCRIPTION="$2" +COVERAGE_XML="sonarcloud-coverage-$3.xml" + +# show cwd +echo "Current working directory: $(pwd)" +# list contents of venv + +ls -la . + +########### debug +echo "Which Python:" +which python$PYTHON_VERSION || echo "python$PYTHON_VERSION not found in PATH" + +echo "Available interpreters:" +pyenv versions || true + +echo "Using Python Version $PYTHON_VERSION" +poetry config virtualenvs.in-project true +############## + +# Only create/use the env and install if .venv does not exist +echo "Checking for Poetry virtual environment (.venv)" +poetry env list +if [ ! -d ".venv" ]; then + echo "Creating virtual environment (.venv) with Poetry" + poetry env use "$PYTHON_VERSION" + + ########### debug + echo "Poetry environment info:" + poetry env info || true + ########### + + poetry install + poetry env list +else + echo "Using cached virtual environment (.venv)" +fi + +if poetry run coverage run -m unittest discover; then + echo "$DESCRIPTION tests passed" +else + echo "$DESCRIPTION tests failed" >> ../failed_tests.txt +fi + +poetry run coverage xml -o "../$COVERAGE_XML" \ No newline at end of file diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index d5bddd46c4..4794223e61 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -11,9 +11,14 @@ echo "Current working directory: $(pwd)" ls -la . +########### debug +echo "Which Python:" +which python$PYTHON_VERSION || echo "python$PYTHON_VERSION not found in PATH" + echo "Using Python Version $PYTHON_VERSION" -poetry config virtualenvs.in-project true +############## + # Only create/use the env and install if .venv does not exist echo "Checking for Poetry virtual environment (.venv)" @@ -21,6 +26,12 @@ poetry env list if [ ! -d ".venv" ]; then echo "Creating virtual environment (.venv) with Poetry" poetry env use "$PYTHON_VERSION" + + ########### debug + echo "Poetry environment info:" + poetry env info || true + ########### + poetry install poetry env list else diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index fbfa4f4705..b3d9397c83 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -16,9 +16,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10', '3.11'] + python-version: ['3.11', '3.10'] - steps: - uses: actions/checkout@v4 with: @@ -29,98 +28,75 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: | + 3.10 + 3.11 cache: 'poetry' - - name: Set up AWS credentials - env: - AWS_ACCESS_KEY_ID: "FOOBARKEY" - AWS_SECRET_ACCESS_KEY: "FOOBARSECRET" - run: | - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - - - name: Chmod .github directory - run: | - chmod +x $SCRIPT_FOLDER/*.sh + - name: Cache global Poetry virtualenvs - - name: Set Poetry to use in-project venvs - run: poetry config virtualenvs.in-project true + # uses: actions/cache@v4 + # with: + # path: ~/.cache/pypoetry/virtualenvs + # key: ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version || 'all' }}-${{ hashFiles('**/poetry.lock') }} + # restore-keys: | + # ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version || 'all' }}- - - name: Cache Poetry virtualenv (filenameprocessor) - if: matrix.python-version == '3.10' uses: actions/cache@v4 with: - path: ./filenameprocessor/.venv - key: ${{ runner.os }}-venv-fp-py3.10-${{ hashFiles('filenameprocessor/poetry.lock') }} + path: ~/.cache/pypoetry/virtualenvs + key: ${{ runner.os }}-poetry-venv-${{ matrix.python-version }}-${{ hashFiles('/poetry.lock') }} restore-keys: | - ${{ runner.os }}-venv-fp-py3.10- + ${{ runner.os }}-poetry-venv-${{ matrix.python-version }}- - - name: Cache Poetry virtualenv (recordprocessor) - if: matrix.python-version == '3.10' - uses: actions/cache@v4 - with: - path: ./recordprocessor/.venv - key: ${{ runner.os }}-venv-rp-py3.10-${{ hashFiles('recordprocessor/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-venv-rp-py3.10- - - name: Cache Poetry virtualenv (recordforwarder) - if: matrix.python-version == '3.11' - uses: actions/cache@v4 - with: - path: ./backend/.venv - key: ${{ runner.os }}-venv-be-py3.11-${{ hashFiles('backend/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-venv-be-py3.11- - - - name: Cache Poetry virtualenv (ack_backend) - if: matrix.python-version == '3.10' - uses: actions/cache@v4 - with: - path: ./ack_backend/.venv - key: ${{ runner.os }}-venv-ack-py3.10-${{ hashFiles('ack_backend/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-venv-ack-py3.10- - - name: Cache Poetry virtualenv (delta_backend) - if: matrix.python-version == '3.11' - uses: actions/cache@v4 - with: - path: ./delta_backend/.venv - key: ${{ runner.os }}-venv-delta-py3.11-${{ hashFiles('delta_backend/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-venv-delta-py3.11- - - - name: Run unittest with filenameprocessor-coverage (S) - if: matrix.python-version == '3.10' - working-directory: filenameprocessor - id: filenameprocessor - continue-on-error: true - run: $RUN_TEST 3.10 filenameprocessor filenameprocessor-coverage.xml - - - name: Run unittest with recordprocessor-coverage (s) - if: matrix.python-version == '3.10' - working-directory: recordprocessor - id: recordprocessor - continue-on-error: true - run: $RUN_TEST 3.10 recordprocessor recordprocessor-coverage.xml - - - name: Run unittest with recordforwarder-coverage - if: matrix.python-version == '3.11' - working-directory: backend - id: recordforwarder - continue-on-error: true + - name: Set up AWS credentials + env: + AWS_ACCESS_KEY_ID: "FOOBARKEY" + AWS_SECRET_ACCESS_KEY: "FOOBARSECRET" run: | - poetry config virtualenvs.in-project true - $RUN_TEST 3.11 recordforwarder recordforwarder-coverage.xml + aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID + aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY + + # - name: Run unittest with filenameprocessor-coverage + # working-directory: filenameprocessor + # id: filenameprocessor + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml + + # - name: Run unittest with recordprocessor-coverage + # working-directory: recordprocessor + # id: recordprocessor + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml + + # # This step is redundant - all of these tests will be run in the backend step below + # - name: Run unittest with recordforwarder-coverage + # working-directory: backend + # id: recordforwarder + # continue-on-error: true + # run: | + # poetry env use 3.11 + # poetry install + # poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda if: matrix.python-version == '3.10' working-directory: ack_backend id: acklambda continue-on-error: true - run: $RUN_TEST 3.10 ack-lambda ack-lambda.xml + run: | + $RUN_TEST 3.10 "ack-lambda" "ack-lambda.xml" - name: Run unittest with coverage-delta if: matrix.python-version == '3.11' @@ -129,7 +105,28 @@ jobs: env: PYTHONPATH: delta_backend/src:delta_backend/tests continue-on-error: true - run: $RUN_TEST 3.11 delta_backend delta.xml + run: | + $RUN_TEST 3.11 delta_backend delta.xml + + # - name: Run unittest with coverage-fhir-api + # working-directory: backend + # id: fhirapi + # continue-on-error: true + # run: | + # poetry env use 3.11 + # poetry install + # poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage.xml + + # - name: Run unittest with coverage-mesh-processor + # working-directory: mesh_processor + # id: meshprocessor + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml - name: Run Test Failure Summary id: check_failure @@ -151,4 +148,4 @@ jobs: uses: SonarSource/sonarqube-scan-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/sonarcloud.yml.test b/.github/workflows/sonarcloud.yml.test new file mode 100644 index 0000000000..0a2c75af23 --- /dev/null +++ b/.github/workflows/sonarcloud.yml.test @@ -0,0 +1,78 @@ +name: SonarCloud + +on: + push: + branches: + - master + pull_request: + types: [labeled, opened, synchronize, reopened, unlabeled] +env: + SCRIPT_FOLDER: ./.github/scripts + RUN_TEST: source ../.github/scripts/run_test.sh + +jobs: + sonarcloud: + name: SonarCloud + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.11'] + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install poetry + run: pip install poetry==1.8.4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + + - name: Set up AWS credentials + env: + AWS_ACCESS_KEY_ID: "FOOBARKEY" + AWS_SECRET_ACCESS_KEY: "FOOBARSECRET" + run: | + aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID + aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY + + - name: Chmod .github directory + run: | + chmod +x $SCRIPT_FOLDER/*.sh + + - name: Cache global Poetry virtualenvs + uses: actions/cache@v4 + with: + path: ~/.cache/pypoetry/virtualenvs + key: ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version }}- + + - name: Run unittest with coverage-delta + if: matrix.python-version == '3.11' + working-directory: delta_backend + id: delta + env: + PYTHONPATH: delta_backend/src:delta_backend/tests + continue-on-error: true + run: | + $RUN_TEST 3.11 delta_backend delta.xml + + - name: Run Test Failure Summary + id: check_failure + run: | + if [ -s failed_tests.txt ]; then + echo "The following tests failed:" + cat failed_tests.txt + + while IFS= read -r line; do + echo "##[error]Test Failures: $line" + done < failed_tests.txt + + exit 1 + else + echo "All tests passed." + fi From 81877df6b570f99b1f693148f0a0df89bcf06325 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 11:42:38 +0100 Subject: [PATCH 17/24] tidy --- .github/scripts/run_test.sh | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index 4794223e61..0d491f0a71 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -5,24 +5,6 @@ PYTHON_VERSION="$1" DESCRIPTION="$2" COVERAGE_XML="sonarcloud-coverage-$3.xml" -# show cwd -echo "Current working directory: $(pwd)" -# list contents of venv - -ls -la . - -########### debug -echo "Which Python:" -which python$PYTHON_VERSION || echo "python$PYTHON_VERSION not found in PATH" - - -echo "Using Python Version $PYTHON_VERSION" -############## - - -# Only create/use the env and install if .venv does not exist -echo "Checking for Poetry virtual environment (.venv)" -poetry env list if [ ! -d ".venv" ]; then echo "Creating virtual environment (.venv) with Poetry" poetry env use "$PYTHON_VERSION" From 725cf5eb4637f0df2063c817c13e8a5ec797f125 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 11:57:27 +0100 Subject: [PATCH 18/24] inline --- .github/workflows/sonarcloud.yml | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index b3d9397c83..78eb273dcc 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -59,15 +59,15 @@ jobs: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - # - name: Run unittest with filenameprocessor-coverage - # working-directory: filenameprocessor - # id: filenameprocessor - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml + - name: Run unittest with filenameprocessor-coverage + working-directory: filenameprocessor + id: filenameprocessor + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml # - name: Run unittest with recordprocessor-coverage # working-directory: recordprocessor @@ -108,15 +108,15 @@ jobs: run: | $RUN_TEST 3.11 delta_backend delta.xml - # - name: Run unittest with coverage-fhir-api - # working-directory: backend - # id: fhirapi - # continue-on-error: true - # run: | - # poetry env use 3.11 - # poetry install - # poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage.xml + - name: Run unittest with coverage-fhir-api + working-directory: backend + id: fhirapi + continue-on-error: true + run: | + poetry env use 3.11 + poetry install + poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage.xml # - name: Run unittest with coverage-mesh-processor # working-directory: mesh_processor From e12387f0bf1d66a69666f5b3779cb6d2bebc9ef8 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 12:04:30 +0100 Subject: [PATCH 19/24] imline --- .github/workflows/sonarcloud.yml | 95 +++++++++++++------------------- 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 78eb273dcc..ad1571a80e 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -6,9 +6,6 @@ on: - master pull_request: types: [labeled, opened, synchronize, reopened, unlabeled] -env: - SCRIPT_FOLDER: ./.github/scripts - RUN_TEST: source ../.github/scripts/run_test.sh jobs: sonarcloud: @@ -28,29 +25,9 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: | - 3.10 - 3.11 + python-version: ${{ matrix.python-version }} cache: 'poetry' - - name: Cache global Poetry virtualenvs - - # uses: actions/cache@v4 - # with: - # path: ~/.cache/pypoetry/virtualenvs - # key: ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version || 'all' }}-${{ hashFiles('**/poetry.lock') }} - # restore-keys: | - # ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version || 'all' }}- - - uses: actions/cache@v4 - with: - path: ~/.cache/pypoetry/virtualenvs - key: ${{ runner.os }}-poetry-venv-${{ matrix.python-version }}-${{ hashFiles('/poetry.lock') }} - restore-keys: | - ${{ runner.os }}-poetry-venv-${{ matrix.python-version }}- - - - - name: Set up AWS credentials env: AWS_ACCESS_KEY_ID: "FOOBARKEY" @@ -69,44 +46,48 @@ jobs: poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml - # - name: Run unittest with recordprocessor-coverage - # working-directory: recordprocessor - # id: recordprocessor - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml - - # # This step is redundant - all of these tests will be run in the backend step below - # - name: Run unittest with recordforwarder-coverage - # working-directory: backend - # id: recordforwarder - # continue-on-error: true - # run: | - # poetry env use 3.11 - # poetry install - # poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml + - name: Run unittest with recordprocessor-coverage + working-directory: recordprocessor + id: recordprocessor + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml + + # This step is redundant - all of these tests will be run in the backend step below + - name: Run unittest with recordforwarder-coverage + working-directory: backend + id: recordforwarder + continue-on-error: true + run: | + poetry env use 3.11 + poetry install + poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda - if: matrix.python-version == '3.10' working-directory: ack_backend id: acklambda continue-on-error: true run: | - $RUN_TEST 3.10 "ack-lambda" "ack-lambda.xml" + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml - name: Run unittest with coverage-delta - if: matrix.python-version == '3.11' working-directory: delta_backend id: delta env: PYTHONPATH: delta_backend/src:delta_backend/tests continue-on-error: true run: | - $RUN_TEST 3.11 delta_backend delta.xml + poetry env use 3.11 + poetry install + poetry run coverage run -m unittest discover || echo "delta tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-delta.xml - name: Run unittest with coverage-fhir-api working-directory: backend @@ -118,15 +99,15 @@ jobs: poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt poetry run coverage xml -o ../sonarcloud-coverage.xml - # - name: Run unittest with coverage-mesh-processor - # working-directory: mesh_processor - # id: meshprocessor - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml + - name: Run unittest with coverage-mesh-processor + working-directory: mesh_processor + id: meshprocessor + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml - name: Run Test Failure Summary id: check_failure From 8717a60aa2770e482de5ace9b4f8de5cc77b3af5 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 12:09:26 +0100 Subject: [PATCH 20/24] conditional --- .github/workflows/sonarcloud.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index ad1571a80e..2567ab6f64 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -37,6 +37,7 @@ jobs: aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - name: Run unittest with filenameprocessor-coverage + if: matrix.python-version == '3.11' working-directory: filenameprocessor id: filenameprocessor continue-on-error: true @@ -47,6 +48,7 @@ jobs: poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml - name: Run unittest with recordprocessor-coverage + if: matrix.python-version == '3.10' working-directory: recordprocessor id: recordprocessor continue-on-error: true @@ -58,6 +60,7 @@ jobs: # This step is redundant - all of these tests will be run in the backend step below - name: Run unittest with recordforwarder-coverage + if: matrix.python-version == '3.11' working-directory: backend id: recordforwarder continue-on-error: true @@ -68,6 +71,7 @@ jobs: poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - name: Run unittest with coverage-ack-lambda + if: matrix.python-version == '3.10' working-directory: ack_backend id: acklambda continue-on-error: true @@ -78,6 +82,7 @@ jobs: poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml - name: Run unittest with coverage-delta + if: matrix.python-version == '3.11' working-directory: delta_backend id: delta env: @@ -90,6 +95,7 @@ jobs: poetry run coverage xml -o ../sonarcloud-coverage-delta.xml - name: Run unittest with coverage-fhir-api + if: matrix.python-version == '3.11' working-directory: backend id: fhirapi continue-on-error: true @@ -100,6 +106,7 @@ jobs: poetry run coverage xml -o ../sonarcloud-coverage.xml - name: Run unittest with coverage-mesh-processor + if: matrix.python-version == '3.10' working-directory: mesh_processor id: meshprocessor continue-on-error: true From 283e04c4fb003d403f4dba04b33a209a733074d3 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 12:26:07 +0100 Subject: [PATCH 21/24] Cache global Poetry virtualenvs --- .github/scripts/run_test.sh | 2 +- .github/workflows/sonarcloud.yml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index 0d491f0a71..7e152c9d32 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -4,7 +4,7 @@ set -e PYTHON_VERSION="$1" DESCRIPTION="$2" COVERAGE_XML="sonarcloud-coverage-$3.xml" - +# poetry config virtualenvs.in-project true if [ ! -d ".venv" ]; then echo "Creating virtual environment (.venv) with Poetry" poetry env use "$PYTHON_VERSION" diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 2567ab6f64..48e04d2bb4 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -28,6 +28,14 @@ jobs: python-version: ${{ matrix.python-version }} cache: 'poetry' + - name: Cache global Poetry virtualenvs + uses: actions/cache@v4 + with: + path: ~/.cache/pypoetry/virtualenvs + key: ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }} + restore-keys: | + ${{ runner.os }}-poetry-global-venv-py${{ matrix.python-version }}- + - name: Set up AWS credentials env: AWS_ACCESS_KEY_ID: "FOOBARKEY" From 0447f178ce94f0695afcd06a886e39f0c451ed0b Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Mon, 2 Jun 2025 12:35:01 +0100 Subject: [PATCH 22/24] sonarcloud_scan --- .github/workflows/sonarcloud.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 48e04d2bb4..ceb2eeb29f 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -45,7 +45,7 @@ jobs: aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - name: Run unittest with filenameprocessor-coverage - if: matrix.python-version == '3.11' + if: matrix.python-version == '3.10' working-directory: filenameprocessor id: filenameprocessor continue-on-error: true @@ -128,7 +128,7 @@ jobs: id: check_failure run: | if [ -s failed_tests.txt ]; then - echo "The following tests failed:" + echo "The following ${{ matrix.python-version }} tests failed:" cat failed_tests.txt while IFS= read -r line; do @@ -137,9 +137,17 @@ jobs: exit 1 else - echo "All tests passed." + echo "All ${{ matrix.python-version }} tests passed." fi + sonarcloud_scan: + name: SonarCloud Scan + runs-on: ubuntu-latest + needs: sonarcloud + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: SonarCloud Scan uses: SonarSource/sonarqube-scan-action@master env: From 3d5b5af55f8653f4239f1ea4d025963456edba4d Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Tue, 3 Jun 2025 11:23:39 +0100 Subject: [PATCH 23/24] test break --- .github/scripts/run_test.sh | 26 +- .github/workflows/sonarcloud.yml | 130 +-- delta_backend/tests/test_convert.py | 400 +++---- delta_backend/tests/test_delta.py | 1348 +++++++++++----------- delta_backend/tests/test_log_firehose.py | 112 +- delta_backend/tests/test_utils.py | 18 +- 6 files changed, 1012 insertions(+), 1022 deletions(-) diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index 7e152c9d32..218ed46012 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -4,26 +4,16 @@ set -e PYTHON_VERSION="$1" DESCRIPTION="$2" COVERAGE_XML="sonarcloud-coverage-$3.xml" -# poetry config virtualenvs.in-project true -if [ ! -d ".venv" ]; then - echo "Creating virtual environment (.venv) with Poetry" - poetry env use "$PYTHON_VERSION" - ########### debug - echo "Poetry environment info:" - poetry env info || true - ########### - poetry install - poetry env list -else - echo "Using cached virtual environment (.venv)" -fi + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml + -if poetry run coverage run -m unittest discover; then - echo "$DESCRIPTION tests passed" -else - echo "$DESCRIPTION tests failed" >> ../failed_tests.txt -fi + poetry env use "$PYTHON_VERSION" + poetry install + poetry run coverage run -m unittest discover || echo "$DESCRIPTION tests failed" >> ../failed_tests.txt poetry run coverage xml -o "../$COVERAGE_XML" \ No newline at end of file diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index ceb2eeb29f..7f437a9686 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -44,50 +44,50 @@ jobs: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - - name: Run unittest with filenameprocessor-coverage - if: matrix.python-version == '3.10' - working-directory: filenameprocessor - id: filenameprocessor - continue-on-error: true - run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml - - - name: Run unittest with recordprocessor-coverage - if: matrix.python-version == '3.10' - working-directory: recordprocessor - id: recordprocessor - continue-on-error: true - run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml - - # This step is redundant - all of these tests will be run in the backend step below - - name: Run unittest with recordforwarder-coverage - if: matrix.python-version == '3.11' - working-directory: backend - id: recordforwarder - continue-on-error: true - run: | - poetry env use 3.11 - poetry install - poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - - - name: Run unittest with coverage-ack-lambda - if: matrix.python-version == '3.10' - working-directory: ack_backend - id: acklambda - continue-on-error: true - run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml + # - name: Run unittest with filenameprocessor-coverage + # if: matrix.python-version == '3.10' + # working-directory: filenameprocessor + # id: filenameprocessor + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml + + # - name: Run unittest with recordprocessor-coverage + # if: matrix.python-version == '3.10' + # working-directory: recordprocessor + # id: recordprocessor + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml + + # # This step is redundant - all of these tests will be run in the backend step below + # - name: Run unittest with recordforwarder-coverage + # if: matrix.python-version == '3.11' + # working-directory: backend + # id: recordforwarder + # continue-on-error: true + # run: | + # poetry env use 3.11 + # poetry install + # poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml + + # - name: Run unittest with coverage-ack-lambda + # if: matrix.python-version == '3.10' + # working-directory: ack_backend + # id: acklambda + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml - name: Run unittest with coverage-delta if: matrix.python-version == '3.11' @@ -102,27 +102,27 @@ jobs: poetry run coverage run -m unittest discover || echo "delta tests failed" >> ../failed_tests.txt poetry run coverage xml -o ../sonarcloud-coverage-delta.xml - - name: Run unittest with coverage-fhir-api - if: matrix.python-version == '3.11' - working-directory: backend - id: fhirapi - continue-on-error: true - run: | - poetry env use 3.11 - poetry install - poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-coverage.xml - - - name: Run unittest with coverage-mesh-processor - if: matrix.python-version == '3.10' - working-directory: mesh_processor - id: meshprocessor - continue-on-error: true - run: | - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml + # - name: Run unittest with coverage-fhir-api + # if: matrix.python-version == '3.11' + # working-directory: backend + # id: fhirapi + # continue-on-error: true + # run: | + # poetry env use 3.11 + # poetry install + # poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-coverage.xml + + # - name: Run unittest with coverage-mesh-processor + # if: matrix.python-version == '3.10' + # working-directory: mesh_processor + # id: meshprocessor + # continue-on-error: true + # run: | + # poetry env use 3.10 + # poetry install + # poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt + # poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml - name: Run Test Failure Summary id: check_failure diff --git a/delta_backend/tests/test_convert.py b/delta_backend/tests/test_convert.py index 6e270e33d9..b13c96b8da 100644 --- a/delta_backend/tests/test_convert.py +++ b/delta_backend/tests/test_convert.py @@ -1,233 +1,233 @@ -import json -import unittest -from copy import deepcopy -from unittest.mock import patch, Mock -from moto import mock_aws -from boto3 import resource as boto3_resource -from utils_for_converter_tests import ValuesForTests, ErrorValuesForTests -from converter import Converter -from common.mappings import ActionFlag, Operation, EventName - -MOCK_ENV_VARS = { - "AWS_SQS_QUEUE_URL": "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue", - "DELTA_TABLE_NAME": "immunisation-batch-internal-dev-audit-test-table", - "SOURCE": "test-source", -} -request_json_data = ValuesForTests.json_data -with patch.dict("os.environ", MOCK_ENV_VARS): - from delta import handler, Converter - - -@patch.dict("os.environ", MOCK_ENV_VARS, clear=True) -class TestConvertToFlatJson(unittest.TestCase): - maxDiff = None - def setUp(self): - # Start moto AWS mocks - self.mock = mock_aws() - self.mock.start() +# import json +# import unittest +# from copy import deepcopy +# from unittest.mock import patch, Mock +# from moto import mock_aws +# from boto3 import resource as boto3_resource +# from utils_for_converter_tests import ValuesForTests, ErrorValuesForTests +# from converter import Converter +# from common.mappings import ActionFlag, Operation, EventName + +# MOCK_ENV_VARS = { +# "AWS_SQS_QUEUE_URL": "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue", +# "DELTA_TABLE_NAME": "immunisation-batch-internal-dev-audit-test-table", +# "SOURCE": "test-source", +# } +# request_json_data = ValuesForTests.json_data +# with patch.dict("os.environ", MOCK_ENV_VARS): +# from delta import handler, Converter + + +# @patch.dict("os.environ", MOCK_ENV_VARS, clear=True) +# class TestConvertToFlatJson(unittest.TestCase): +# maxDiff = None +# def setUp(self): +# # Start moto AWS mocks +# self.mock = mock_aws() +# self.mock.start() - """Set up mock DynamoDB table.""" - self.dynamodb_resource = boto3_resource("dynamodb", "eu-west-2") - self.table = self.dynamodb_resource.create_table( - TableName="immunisation-batch-internal-dev-audit-test-table", - KeySchema=[ - {"AttributeName": "PK", "KeyType": "HASH"}, - ], - AttributeDefinitions=[ - {"AttributeName": "PK", "AttributeType": "S"}, - {"AttributeName": "Operation", "AttributeType": "S"}, - {"AttributeName": "IdentifierPK", "AttributeType": "S"}, - {"AttributeName": "SupplierSystem", "AttributeType": "S"}, - ], - ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, - GlobalSecondaryIndexes=[ - { - "IndexName": "IdentifierGSI", - "KeySchema": [{"AttributeName": "IdentifierPK", "KeyType": "HASH"}], - "Projection": {"ProjectionType": "ALL"}, - "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, - }, - { - "IndexName": "PatientGSI", - "KeySchema": [ - {"AttributeName": "Operation", "KeyType": "HASH"}, - {"AttributeName": "SupplierSystem", "KeyType": "RANGE"}, - ], - "Projection": {"ProjectionType": "ALL"}, - "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, - }, - ], - ) - self.logger_info_patcher = patch("logging.Logger.info") - self.mock_logger_info = self.logger_info_patcher.start() - - self.logger_exception_patcher = patch("logging.Logger.exception") - self.mock_logger_exception = self.logger_exception_patcher.start() - - self.firehose_logger_patcher = patch("delta.firehose_logger") - self.mock_firehose_logger = self.firehose_logger_patcher.start() - - def tearDown(self): - self.logger_exception_patcher.stop() - self.logger_info_patcher.stop() - self.mock_firehose_logger.stop() +# """Set up mock DynamoDB table.""" +# self.dynamodb_resource = boto3_resource("dynamodb", "eu-west-2") +# self.table = self.dynamodb_resource.create_table( +# TableName="immunisation-batch-internal-dev-audit-test-table", +# KeySchema=[ +# {"AttributeName": "PK", "KeyType": "HASH"}, +# ], +# AttributeDefinitions=[ +# {"AttributeName": "PK", "AttributeType": "S"}, +# {"AttributeName": "Operation", "AttributeType": "S"}, +# {"AttributeName": "IdentifierPK", "AttributeType": "S"}, +# {"AttributeName": "SupplierSystem", "AttributeType": "S"}, +# ], +# ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, +# GlobalSecondaryIndexes=[ +# { +# "IndexName": "IdentifierGSI", +# "KeySchema": [{"AttributeName": "IdentifierPK", "KeyType": "HASH"}], +# "Projection": {"ProjectionType": "ALL"}, +# "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, +# }, +# { +# "IndexName": "PatientGSI", +# "KeySchema": [ +# {"AttributeName": "Operation", "KeyType": "HASH"}, +# {"AttributeName": "SupplierSystem", "KeyType": "RANGE"}, +# ], +# "Projection": {"ProjectionType": "ALL"}, +# "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, +# }, +# ], +# ) +# self.logger_info_patcher = patch("logging.Logger.info") +# self.mock_logger_info = self.logger_info_patcher.start() + +# self.logger_exception_patcher = patch("logging.Logger.exception") +# self.mock_logger_exception = self.logger_exception_patcher.start() + +# self.firehose_logger_patcher = patch("delta.firehose_logger") +# self.mock_firehose_logger = self.firehose_logger_patcher.start() + +# def tearDown(self): +# self.logger_exception_patcher.stop() +# self.logger_info_patcher.stop() +# self.mock_firehose_logger.stop() - self.mock.stop() +# self.mock.stop() - @staticmethod - def get_event(event_name=EventName.CREATE, operation="operation", supplier="EMIS"): - """Returns test event data.""" - return ValuesForTests.get_event(event_name, operation, supplier) +# @staticmethod +# def get_event(event_name=EventName.CREATE, operation="operation", supplier="EMIS"): +# """Returns test event data.""" +# return ValuesForTests.get_event(event_name, operation, supplier) - def assert_dynamodb_record(self, operation_flag, action_flag, items, expected_values, expected_imms, response): - """ - Asserts that a record with the expected structure exists in DynamoDB. - Ignores dynamically generated fields like PK, DateTimeStamp, and ExpiresAt. - Ensures that the 'Imms' field matches exactly. - """ - self.assertTrue(response) +# def assert_dynamodb_record(self, operation_flag, action_flag, items, expected_values, expected_imms, response): +# """ +# Asserts that a record with the expected structure exists in DynamoDB. +# Ignores dynamically generated fields like PK, DateTimeStamp, and ExpiresAt. +# Ensures that the 'Imms' field matches exactly. +# """ +# self.assertTrue(response) - filtered_items = [ - {k: v for k, v in item.items() if k not in ["PK", "DateTimeStamp", "ExpiresAt"]} - for item in items - if item.get("Operation") == operation_flag - and item.get("Imms", {}).get("ACTION_FLAG") == action_flag - ] +# filtered_items = [ +# {k: v for k, v in item.items() if k not in ["PK", "DateTimeStamp", "ExpiresAt"]} +# for item in items +# if item.get("Operation") == operation_flag +# and item.get("Imms", {}).get("ACTION_FLAG") == action_flag +# ] - self.assertGreater(len(filtered_items), 0, f"No matching item found for {operation_flag}") +# self.assertGreater(len(filtered_items), 0, f"No matching item found for {operation_flag}") - imms_data = filtered_items[0]["Imms"] - self.assertIsInstance(imms_data, dict) - self.assertGreater(len(imms_data), 0) +# imms_data = filtered_items[0]["Imms"] +# self.assertIsInstance(imms_data, dict) +# self.assertGreater(len(imms_data), 0) - # Check Imms JSON structure matches exactly - self.assertEqual(imms_data, expected_imms, "Imms data does not match expected JSON structure") +# # Check Imms JSON structure matches exactly +# self.assertEqual(imms_data, expected_imms, "Imms data does not match expected JSON structure") - for key, expected_value in expected_values.items(): - self.assertIn(key, filtered_items[0], f"{key} is missing") - self.assertEqual(filtered_items[0][key], expected_value, f"{key} mismatch") +# for key, expected_value in expected_values.items(): +# self.assertIn(key, filtered_items[0], f"{key} is missing") +# self.assertEqual(filtered_items[0][key], expected_value, f"{key} mismatch") - def test_fhir_converter_json_direct_data(self): - """it should convert fhir json data to flat json""" - json_data = json.dumps(ValuesForTests.json_data) +# def test_fhir_converter_json_direct_data(self): +# """it should convert fhir json data to flat json""" +# json_data = json.dumps(ValuesForTests.json_data) - fhir_converter = Converter(json_data) - FlatFile = fhir_converter.run_conversion() +# fhir_converter = Converter(json_data) +# FlatFile = fhir_converter.run_conversion() - flatJSON = json.dumps(FlatFile) - expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag - expected_imms = json.dumps(expected_imms_value) - self.assertEqual(flatJSON, expected_imms) +# flatJSON = json.dumps(FlatFile) +# expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag +# expected_imms = json.dumps(expected_imms_value) +# self.assertEqual(flatJSON, expected_imms) - errorRecords = fhir_converter.get_error_records() +# errorRecords = fhir_converter.get_error_records() - self.assertEqual(len(errorRecords), 0) +# self.assertEqual(len(errorRecords), 0) - def test_fhir_converter_json_direct_data(self): - """it should convert fhir json data to flat json""" - json_data = json.dumps(ValuesForTests.json_data) +# def test_fhir_converter_json_direct_data(self): +# """it should convert fhir json data to flat json""" +# json_data = json.dumps(ValuesForTests.json_data) - fhir_converter = Converter(json_data) - FlatFile = fhir_converter.run_conversion() +# fhir_converter = Converter(json_data) +# FlatFile = fhir_converter.run_conversion() - flatJSON = json.dumps(FlatFile) - expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag - expected_imms = json.dumps(expected_imms_value) - self.assertEqual(flatJSON, expected_imms) +# flatJSON = json.dumps(FlatFile) +# expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag +# expected_imms = json.dumps(expected_imms_value) +# self.assertEqual(flatJSON, expected_imms) - errorRecords = fhir_converter.get_error_records() +# errorRecords = fhir_converter.get_error_records() - self.assertEqual(len(errorRecords), 0) +# self.assertEqual(len(errorRecords), 0) - def test_fhir_converter_json_error_scenario_reporting_on(self): - """it should convert fhir json data to flat json - error scenarios""" - error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] +# def test_fhir_converter_json_error_scenario_reporting_on(self): +# """it should convert fhir json data to flat json - error scenarios""" +# error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] - for test_case in error_test_cases: - json_data = json.dumps(test_case) +# for test_case in error_test_cases: +# json_data = json.dumps(test_case) - fhir_converter = Converter(json_data) - fhir_converter.run_conversion() +# fhir_converter = Converter(json_data) +# fhir_converter.run_conversion() - errorRecords = fhir_converter.get_error_records() +# errorRecords = fhir_converter.get_error_records() - # Check if bad data creates error records - self.assertTrue(len(errorRecords) > 0) +# # Check if bad data creates error records +# self.assertTrue(len(errorRecords) > 0) - def test_fhir_converter_json_error_scenario_reporting_off(self): - """it should convert fhir json data to flat json - error scenarios""" - error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] +# def test_fhir_converter_json_error_scenario_reporting_off(self): +# """it should convert fhir json data to flat json - error scenarios""" +# error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] - for test_case in error_test_cases: - json_data = json.dumps(test_case) +# for test_case in error_test_cases: +# json_data = json.dumps(test_case) - fhir_converter = Converter(json_data, report_unexpected_exception=False) - fhir_converter.run_conversion() +# fhir_converter = Converter(json_data, report_unexpected_exception=False) +# fhir_converter.run_conversion() - errorRecords = fhir_converter.get_error_records() +# errorRecords = fhir_converter.get_error_records() - # Check if bad data creates error records - self.assertTrue(len(errorRecords) == 0) +# # Check if bad data creates error records +# self.assertTrue(len(errorRecords) == 0) - def test_fhir_converter_json_incorrect_data_scenario_reporting_on(self): - """it should convert fhir json data to flat json - error scenarios""" +# def test_fhir_converter_json_incorrect_data_scenario_reporting_on(self): +# """it should convert fhir json data to flat json - error scenarios""" - with self.assertRaises(ValueError): - fhir_converter = Converter(None) - errorRecords = fhir_converter.get_error_records() - self.assertTrue(len(errorRecords) > 0) +# with self.assertRaises(ValueError): +# fhir_converter = Converter(None) +# errorRecords = fhir_converter.get_error_records() +# self.assertTrue(len(errorRecords) > 0) - def test_fhir_converter_json_incorrect_data_scenario_reporting_off(self): - """it should convert fhir json data to flat json - error scenarios""" - - with self.assertRaises(ValueError): - fhir_converter = Converter(None, report_unexpected_exception=False) - errorRecords = fhir_converter.get_error_records() - self.assertTrue(len(errorRecords) == 0) - - def test_handler_imms_convert_to_flat_json(self): - """Test that the Imms field contains the correct flat JSON data for CREATE, UPDATE, and DELETE operations.""" - expected_action_flags = [ - {"Operation": Operation.CREATE, "EXPECTED_ACTION_FLAG": ActionFlag.CREATE}, - {"Operation": Operation.UPDATE, "EXPECTED_ACTION_FLAG": ActionFlag.UPDATE}, - {"Operation": Operation.DELETE_LOGICAL, "EXPECTED_ACTION_FLAG": ActionFlag.DELETE_LOGICAL}, - ] - - 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) - - # Retrieve items from DynamoDB - result = self.table.scan() - items = result.get("Items", []) - - expected_values = ValuesForTests.expected_static_values - expected_imms = ValuesForTests.get_expected_imms(test_case["EXPECTED_ACTION_FLAG"]) - - self.assert_dynamodb_record( - test_case["Operation"], - test_case["EXPECTED_ACTION_FLAG"], - items, - expected_values, - expected_imms, - response - ) - - result = self.table.scan() - items = result.get("Items", []) - self.clear_table() - - def clear_table(self): - scan = self.table.scan() - with self.table.batch_writer() as batch: - for item in scan.get("Items", []): - batch.delete_item(Key={"PK": item["PK"]}) - result = self.table.scan() - items = result.get("Items", []) - - if __name__ == "__main__": - unittest.main() +# def test_fhir_converter_json_incorrect_data_scenario_reporting_off(self): +# """it should convert fhir json data to flat json - error scenarios""" + +# with self.assertRaises(ValueError): +# fhir_converter = Converter(None, report_unexpected_exception=False) +# errorRecords = fhir_converter.get_error_records() +# self.assertTrue(len(errorRecords) == 0) + +# def test_handler_imms_convert_to_flat_json(self): +# """Test that the Imms field contains the correct flat JSON data for CREATE, UPDATE, and DELETE operations.""" +# expected_action_flags = [ +# {"Operation": Operation.CREATE, "EXPECTED_ACTION_FLAG": ActionFlag.CREATE}, +# {"Operation": Operation.UPDATE, "EXPECTED_ACTION_FLAG": ActionFlag.UPDATE}, +# {"Operation": Operation.DELETE_LOGICAL, "EXPECTED_ACTION_FLAG": ActionFlag.DELETE_LOGICAL}, +# ] + +# 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) + +# # Retrieve items from DynamoDB +# result = self.table.scan() +# items = result.get("Items", []) + +# expected_values = ValuesForTests.expected_static_values +# expected_imms = ValuesForTests.get_expected_imms(test_case["EXPECTED_ACTION_FLAG"]) + +# self.assert_dynamodb_record( +# test_case["Operation"], +# test_case["EXPECTED_ACTION_FLAG"], +# items, +# expected_values, +# expected_imms, +# response +# ) + +# result = self.table.scan() +# items = result.get("Items", []) +# self.clear_table() + +# def clear_table(self): +# scan = self.table.scan() +# with self.table.batch_writer() as batch: +# for item in scan.get("Items", []): +# batch.delete_item(Key={"PK": item["PK"]}) +# result = self.table.scan() +# items = result.get("Items", []) + +# if __name__ == "__main__": +# unittest.main() diff --git a/delta_backend/tests/test_delta.py b/delta_backend/tests/test_delta.py index 08c64c7e0d..3ce3796fc0 100644 --- a/delta_backend/tests/test_delta.py +++ b/delta_backend/tests/test_delta.py @@ -1,674 +1,674 @@ -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 - -# Set environment variables before importing the module -## @TODO: # Note: Environment variables shared across tests, thus aligned -os.environ["AWS_SQS_QUEUE_URL"] = "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue" -os.environ["DELTA_TABLE_NAME"] = "my_delta_table" -os.environ["SOURCE"] = "my_source" - -from delta import send_message, handler, process_record # Import after setting environment variables - -SUCCESS_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 200}} -EXCEPTION_RESPONSE = ClientError({"Error": {"Code": "ConditionalCheckFailedException"}}, "PutItem") -FAIL_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 500}} - -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") - self.mock_logger_info = self.logger_info_patcher.start() - - self.logger_exception_patcher = patch("logging.Logger.exception") - self.mock_logger_exception = self.logger_exception_patcher.start() - - self.logger_warning_patcher = patch("logging.Logger.warning") - self.mock_logger_warning = self.logger_warning_patcher.start() - - self.logger_error_patcher = patch("logging.Logger.error") - self.mock_logger_error = self.logger_error_patcher.start() - - self.firehose_logger_patcher = patch("delta.firehose_logger") - self.mock_firehose_logger = self.firehose_logger_patcher.start() - - self.sqs_client_patcher = patch("delta.sqs_client") - self.mock_sqs_client = self.sqs_client_patcher.start() - - self.delta_table_patcher=patch("delta.delta_table") - self.mock_delta_table = self.delta_table_patcher.start() - - def tearDown(self): - self.logger_exception_patcher.stop() - self.logger_warning_patcher.stop() - self.logger_error_patcher.stop() - self.logger_info_patcher.stop() - self.mock_firehose_logger.stop() - self.sqs_client_patcher.stop() - self.delta_table_patcher.stop() - - def test_send_message_success(self): - # Arrange - self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} - record = {"key": "value"} - sqs_queue_url = "test-queue-url" - - # Act - send_message(record, sqs_queue_url) - - # Assert - self.mock_sqs_client.send_message.assert_called_once_with( - QueueUrl=sqs_queue_url, MessageBody=json.dumps(record) - ) - - def test_send_message_client_error(self): - # Arrange - record = {"key": "value"} - - # Simulate ClientError - error_response = {"Error": {"Code": "500", "Message": "Internal Server Error"}} - self.mock_sqs_client.send_message.side_effect = ClientError(error_response, "SendMessage") - - # Act - send_message(record, "test-queue-url") - - # Assert - self.mock_logger_error.assert_called_once_with( - f"Error sending record to DLQ: An error occurred (500) when calling the SendMessage operation: Internal Server Error" - ) - - def test_handler_success_insert(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - suppliers = ["DPS", "EMIS"] - for supplier in suppliers: - imms_id = f"test-insert-imms-{supplier}-id" - event = ValuesForTests.get_event(event_name=EventName.CREATE, operation=Operation.CREATE, imms_id=imms_id, supplier=supplier) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.mock_delta_table.put_item.assert_called() - self.mock_firehose_logger.send_log.assert_called() # check logged - put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB - put_item_data = put_item_call_args.kwargs["Item"] - self.assertIn("Imms", put_item_data) - self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.CREATE) - self.assertEqual(put_item_data["Operation"], Operation.CREATE) - self.assertEqual(put_item_data["SupplierSystem"], supplier) - - def test_handler_failure(self): - # Arrange - self.mock_delta_table.put_item.return_value = FAIL_RESPONSE - event = ValuesForTests.get_event() - - # Act - result = handler(event, None) - - # Assert - self.assertFalse(result) - - def test_handler_success_update(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - imms_id = "test-update-imms-id" - event = ValuesForTests.get_event(event_name=EventName.UPDATE, operation=Operation.UPDATE, imms_id=imms_id) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.mock_delta_table.put_item.assert_called() - self.mock_firehose_logger.send_log.assert_called() # check logged - put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB - put_item_data = put_item_call_args.kwargs["Item"] - self.assertIn("Imms", put_item_data) - self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.UPDATE) - self.assertEqual(put_item_data["Operation"], Operation.UPDATE) - self.assertEqual(put_item_data["ImmsID"], imms_id) - - def test_handler_success_delete_physical(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - imms_id = "test-update-imms-id" - event = ValuesForTests.get_event(event_name=EventName.DELETE_PHYSICAL, operation=Operation.DELETE_PHYSICAL, imms_id=imms_id) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.mock_delta_table.put_item.assert_called() - self.mock_firehose_logger.send_log.assert_called() # check logged - put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB - put_item_data = put_item_call_args.kwargs["Item"] - self.assertIn("Imms", put_item_data) - self.assertEqual(put_item_data["Operation"], Operation.DELETE_PHYSICAL) - self.assertEqual(put_item_data["ImmsID"], imms_id) - self.assertEqual(put_item_data["Imms"], "") # check imms has been blanked out - - def test_handler_success_delete_logical(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - imms_id = "test-update-imms-id" - event = ValuesForTests.get_event(event_name=EventName.UPDATE, - operation=Operation.DELETE_LOGICAL, - imms_id=imms_id) - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.mock_delta_table.put_item.assert_called() - self.mock_firehose_logger.send_log.assert_called() # check logged - put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB - put_item_data = put_item_call_args.kwargs["Item"] - self.assertIn("Imms", put_item_data) - self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.DELETE_LOGICAL) - self.assertEqual(put_item_data["Operation"], Operation.DELETE_LOGICAL) - self.assertEqual(put_item_data["ImmsID"], imms_id) - - @patch("delta.logger.info") - def test_dps_record_skipped(self, mock_logger_info): - event = ValuesForTests.get_event(supplier="DPSFULL") - - response = handler(event, None) - - self.assertTrue(response) - - # Check logging and Firehose were called - mock_logger_info.assert_called_with("Record from DPS skipped for 12345") - - @patch("delta.Converter") - def test_partial_success_with_errors(self, mock_converter): - mock_converter_instance = MagicMock() - mock_converter_instance.run_conversion.return_value = {"ABC":"DEF"} - mock_converter_instance.get_error_records.return_value = [{"error": "Invalid field"}] - mock_converter.return_value = mock_converter_instance - - # Mock DynamoDB put_item success - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - - event = ValuesForTests.get_event() - - response = handler(event, None) - - self.assertTrue(response) - # Check logging and Firehose were called - self.mock_logger_info.assert_called() - self.assertEqual(self.mock_firehose_logger.send_log.call_count, 1) - self.mock_firehose_logger.send_log.assert_called_once() - - # Get the actual argument passed to send_log - args, kwargs = self.mock_firehose_logger.send_log.call_args - sent_payload = args[0] # First positional arg - - # Navigate to the specific message - status_desc = sent_payload["event"]["operation_outcome"]["statusDesc"] - - # Assert the expected message is present - self.assertIn( - "Partial success: successfully synced into delta, but issues found within record", - status_desc - ) - - def test_send_message_multi_records_diverse(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - records_config = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), - RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "id3", ActionFlag.DELETE_LOGICAL), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) - - def test_send_message_skipped_records_diverse(self): - '''Check skipped records sent to firehose but not to DynamoDB''' - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - records_config = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), - RecordConfig(EventName.CREATE, Operation.CREATE, "id-skip", ActionFlag.CREATE, "DPSFULL"), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, 3) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) - - def test_send_message_multi_create(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - records_config = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "create-id1", ActionFlag.CREATE), - RecordConfig(EventName.CREATE, Operation.CREATE, "create-id2", ActionFlag.CREATE), - RecordConfig(EventName.CREATE, Operation.CREATE, "create-id3", ActionFlag.CREATE) - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, 3) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - - - def test_send_message_multi_update(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - records_config = [ - RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id1", ActionFlag.UPDATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id2", ActionFlag.UPDATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id3", ActionFlag.UPDATE) - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, 3) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - - def test_send_message_multi_logical_delete(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - - records_config = [ - RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id1", ActionFlag.DELETE_LOGICAL), - RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id2", ActionFlag.DELETE_LOGICAL), - RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id3", ActionFlag.DELETE_LOGICAL) - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, 3) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - - def test_send_message_multi_physical_delete(self): - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - records_config = [ - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id1"), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id2"), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id3") - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertTrue(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, 3) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - - def test_single_error_in_multi(self): - # Arrange - self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] - - records_config = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id1", ActionFlag.CREATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id1.2", ActionFlag.UPDATE), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id1.3"), - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertFalse(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, 3) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - self.assertEqual(self.mock_logger_warning.call_count, 1) - - def test_single_exception_in_multi(self): - # Arrange - # 2nd record fails - self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, EXCEPTION_RESPONSE, SUCCESS_RESPONSE] - - records_config = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id2.1", ActionFlag.CREATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "exception-id2.2", ActionFlag.UPDATE), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id2.3"), - ] - event = ValuesForTests.get_multi_record_event(records_config) - - # Act - result = handler(event, None) - - # Assert - self.assertFalse(result) - self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) - self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) - - @patch("delta.process_record") - @patch("delta.send_firehose") - def test_handler_calls_process_record_for_each_event(self, mock_send_firehose, mock_process_record): - # Arrange - event = { - "Records": [ - { "a": "record1" }, - { "a": "record2" }, - { "a": "record3" } - ] - } - # Mock process_record to always return True - mock_process_record.return_value = True, {} - mock_send_firehose.return_value = None - - # Act - result = handler(event, {}) - - # Assert - self.assertTrue(result) - self.assertEqual(mock_process_record.call_count, len(event["Records"])) - - # TODO depedency injection needed here - @patch("delta.process_record") - @patch("delta.send_firehose") - def test_handler_sends_all_to_firehose(self, mock_send_firehose, mock_process_record): - # Arrange - - # event with 3 records - event = { - "Records": [ - { "a": "record1" }, - { "a": "record2" }, - { "a": "record3" } - ] - } - return_ok = (True, {}) - return_fail = (False, {}) - mock_send_firehose.return_value = None - mock_process_record.side_effect = [return_ok, return_fail, return_ok] - - # Act - result = handler(event, {}) - - # Assert - self.assertFalse(result) - self.assertEqual(mock_process_record.call_count, len(event["Records"])) - # check that all records were sent to firehose - self.assertEqual(mock_send_firehose.call_count, len(event["Records"])) - -class DeltaRecordProcessorTestCase(unittest.TestCase): - - def setUp(self): - self.logger_info_patcher = patch("logging.Logger.info") - self.mock_logger_info = self.logger_info_patcher.start() - - self.logger_exception_patcher = patch("logging.Logger.exception") - self.mock_logger_exception = self.logger_exception_patcher.start() - - self.logger_warning_patcher = patch("logging.Logger.warning") - self.mock_logger_warning = self.logger_warning_patcher.start() - - self.delta_table_patcher=patch("delta.delta_table") - self.mock_delta_table = self.delta_table_patcher.start() - - def tearDown(self): - self.logger_exception_patcher.stop() - self.logger_warning_patcher.stop() - self.logger_info_patcher.stop() - self.delta_table_patcher.stop() - - def test_multi_record_success(self): - - # Arrange - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - test_configs = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "ok-id.2", ActionFlag.UPDATE), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), - ] - test_index = 0 - for config in test_configs: - test_index += 1 - record = ValuesForTests.get_event_record( - imms_id=config.imms_id, - event_name=config.event_name, - operation=config.operation, - supplier=config.supplier, - ) - # Act - result, log_data = process_record(record, {}) - - # Assert - self.assertEqual(result, True) - operation_outcome = log_data["operation_outcome"] - self.assertEqual(operation_outcome["record"], config.imms_id) - self.assertEqual(operation_outcome["operation_type"], config.operation) - self.assertEqual(operation_outcome["statusCode"], "200") - self.assertEqual(operation_outcome["statusDesc"], "Successfully synched into delta") - self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) - - self.assertEqual(self.mock_logger_exception.call_count, 0) - 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 = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] - test_configs = [ - RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), - RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id.2", ActionFlag.UPDATE), - RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), - ] - test_index = 0 - for config in test_configs: - test_index += 1 - record = ValuesForTests.get_event_record( - imms_id=config.imms_id, - event_name=config.event_name, - operation=config.operation, - supplier=config.supplier, - ) - log_data = {} - # Act - result, log_data = process_record(record, log_data) - - # Assert - self.assertEqual(result, expected_returns[test_index-1]) - self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) - - self.assertEqual(self.mock_logger_exception.call_count, 0) - self.assertEqual(self.mock_logger_warning.call_count, 1) - - - def test_single_record_table_exception(self): - - # Arrange - imms_id = "exception-id" - record = ValuesForTests.get_event_record( - imms_id, - event_name=EventName.UPDATE, - operation=Operation.UPDATE, - supplier="EMIS", - ) - self.mock_delta_table.put_item.return_value = EXCEPTION_RESPONSE - # Act - result, log_data = process_record(record, {}) - - # Assert - self.assertEqual(result, False) - operation_outcome = log_data["operation_outcome"] - self.assertEqual(operation_outcome["record"], imms_id) - self.assertEqual(operation_outcome["operation_type"], Operation.UPDATE) - self.assertEqual(operation_outcome["statusCode"], "500") - self.assertEqual(operation_outcome["statusDesc"], "Exception") - self.assertEqual(self.mock_delta_table.put_item.call_count, 1) - self.assertEqual(self.mock_logger_exception.call_count, 1) - - @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 - ) - - self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - # Act - process_record(record, {}) - - # Assert - mock_json_loads.assert_any_call(ValuesForTests.json_value_for_test, parse_float=decimal.Decimal) - - -import delta - -class TestGetDeltaTable(unittest.TestCase): - def setUp(self): - self.delta_table_patcher=patch("delta.delta_table") - self.mock_delta_table = self.delta_table_patcher.start() - self.logger_info_patcher = patch("logging.Logger.info") - self.mock_logger_info = self.logger_info_patcher.start() - self.logger_error_patcher = patch("logging.Logger.error") - self.mock_logger_error = self.logger_error_patcher.start() - - def tearDown(self): - self.delta_table_patcher.stop() - self.logger_info_patcher.stop() - 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 - self.assertIs(delta.delta_table, self.mock_delta_table) - - @patch("boto3.resource") - def test_returns_cached_table(self, mock_boto3_resource): - delta.delta_table = self.mock_delta_table - - table = delta.get_delta_table() - self.assertIs(table, self.mock_delta_table) - # Should not call boto3 again - mock_boto3_resource.assert_not_called() - - # mock boto3.resource to raise an exception - @patch("boto3.resource") - def test_returns_none_on_exception(self, mock_boto3_resource): - delta.delta_table = None - mock_boto3_resource.side_effect = Exception("fail") - table = delta.get_delta_table() - self.assertIsNone(table) - self.mock_logger_error.assert_called() - -import delta - -class TestGetSqsClient(unittest.TestCase): - def setUp(self): - # Patch logger.info and logger.error - self.logger_info_patcher = patch("logging.Logger.info") - self.mock_logger_info = self.logger_info_patcher.start() - self.logger_error_patcher = patch("logging.Logger.error") - self.mock_logger_error = self.logger_error_patcher.start() - self.sqs_client_patcher = patch("delta.boto3.client") - self.mock_sqs_client = self.sqs_client_patcher.start() - # Reset the global sqs_client before each test - delta.sqs_client = None - - def tearDown(self): - self.logger_info_patcher.stop() - self.logger_error_patcher.stop() - self.sqs_client_patcher.stop() - - def test_returns_client_on_success(self): - mock_client = MagicMock() - self.mock_sqs_client.return_value = mock_client - - client = delta.get_sqs_client() - self.assertIs(client, mock_client) - # Should cache the client - self.assertIs(delta.sqs_client, mock_client) - - def test_returns_cached_client(self): - mock_client = MagicMock() - delta.sqs_client = mock_client - - client = delta.get_sqs_client() - self.assertIs(client, mock_client) - # Should not re-initialize - self.mock_sqs_client.assert_not_called() - - def test_returns_none_on_exception(self): - self.mock_sqs_client.side_effect = Exception("fail") - client = delta.get_sqs_client() - self.assertIsNone(client) - self.mock_logger_error.assert_called() - - -import delta - -class TestSendMessage(unittest.TestCase): - def setUp(self): - self.get_sqs_client_patcher = patch("delta.get_sqs_client") - self.mock_get_sqs_client = self.get_sqs_client_patcher.start() - self.mock_sqs_client = MagicMock() - self.mock_get_sqs_client.return_value = self.mock_sqs_client - - self.logger_info_patcher = patch("logging.Logger.info") - self.mock_logger_info = self.logger_info_patcher.start() - self.logger_error_patcher = patch("logging.Logger.error") - self.mock_logger_error = self.logger_error_patcher.start() - - def tearDown(self): - self.get_sqs_client_patcher.stop() - self.logger_info_patcher.stop() - self.logger_error_patcher.stop() - - def test_send_message_success(self): - record = {"a": "bbb"} - self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} - - delta.send_message(record) - - self.mock_sqs_client.send_message.assert_called_once() - self.mock_logger_info.assert_any_call("Record saved successfully to the DLQ") - self.mock_logger_error.assert_not_called() - - def test_send_message_client_error(self): - record = {"a": "bbb"} - self.mock_sqs_client.send_message.side_effect = Exception("SQS error") - - delta.send_message(record, "test-queue-url") - - self.mock_logger_error.assert_called() +# 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 + +# # Set environment variables before importing the module +# ## @TODO: # Note: Environment variables shared across tests, thus aligned +# os.environ["AWS_SQS_QUEUE_URL"] = "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue" +# os.environ["DELTA_TABLE_NAME"] = "my_delta_table" +# os.environ["SOURCE"] = "my_source" + +# from delta import send_message, handler, process_record # Import after setting environment variables + +# SUCCESS_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 200}} +# EXCEPTION_RESPONSE = ClientError({"Error": {"Code": "ConditionalCheckFailedException"}}, "PutItem") +# FAIL_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 500}} + +# 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") +# self.mock_logger_info = self.logger_info_patcher.start() + +# self.logger_exception_patcher = patch("logging.Logger.exception") +# self.mock_logger_exception = self.logger_exception_patcher.start() + +# self.logger_warning_patcher = patch("logging.Logger.warning") +# self.mock_logger_warning = self.logger_warning_patcher.start() + +# self.logger_error_patcher = patch("logging.Logger.error") +# self.mock_logger_error = self.logger_error_patcher.start() + +# self.firehose_logger_patcher = patch("delta.firehose_logger") +# self.mock_firehose_logger = self.firehose_logger_patcher.start() + +# self.sqs_client_patcher = patch("delta.sqs_client") +# self.mock_sqs_client = self.sqs_client_patcher.start() + +# self.delta_table_patcher=patch("delta.delta_table") +# self.mock_delta_table = self.delta_table_patcher.start() + +# def tearDown(self): +# self.logger_exception_patcher.stop() +# self.logger_warning_patcher.stop() +# self.logger_error_patcher.stop() +# self.logger_info_patcher.stop() +# self.mock_firehose_logger.stop() +# self.sqs_client_patcher.stop() +# self.delta_table_patcher.stop() + +# def test_send_message_success(self): +# # Arrange +# self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} +# record = {"key": "value"} +# sqs_queue_url = "test-queue-url" + +# # Act +# send_message(record, sqs_queue_url) + +# # Assert +# self.mock_sqs_client.send_message.assert_called_once_with( +# QueueUrl=sqs_queue_url, MessageBody=json.dumps(record) +# ) + +# def test_send_message_client_error(self): +# # Arrange +# record = {"key": "value"} + +# # Simulate ClientError +# error_response = {"Error": {"Code": "500", "Message": "Internal Server Error"}} +# self.mock_sqs_client.send_message.side_effect = ClientError(error_response, "SendMessage") + +# # Act +# send_message(record, "test-queue-url") + +# # Assert +# self.mock_logger_error.assert_called_once_with( +# f"Error sending record to DLQ: An error occurred (500) when calling the SendMessage operation: Internal Server Error" +# ) + +# def test_handler_success_insert(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# suppliers = ["DPS", "EMIS"] +# for supplier in suppliers: +# imms_id = f"test-insert-imms-{supplier}-id" +# event = ValuesForTests.get_event(event_name=EventName.CREATE, operation=Operation.CREATE, imms_id=imms_id, supplier=supplier) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.mock_delta_table.put_item.assert_called() +# self.mock_firehose_logger.send_log.assert_called() # check logged +# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB +# put_item_data = put_item_call_args.kwargs["Item"] +# self.assertIn("Imms", put_item_data) +# self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.CREATE) +# self.assertEqual(put_item_data["Operation"], Operation.CREATE) +# self.assertEqual(put_item_data["SupplierSystem"], supplier) + +# def test_handler_failure(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = FAIL_RESPONSE +# event = ValuesForTests.get_event() + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertFalse(result) + +# def test_handler_success_update(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# imms_id = "test-update-imms-id" +# event = ValuesForTests.get_event(event_name=EventName.UPDATE, operation=Operation.UPDATE, imms_id=imms_id) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.mock_delta_table.put_item.assert_called() +# self.mock_firehose_logger.send_log.assert_called() # check logged +# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB +# put_item_data = put_item_call_args.kwargs["Item"] +# self.assertIn("Imms", put_item_data) +# self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.UPDATE) +# self.assertEqual(put_item_data["Operation"], Operation.UPDATE) +# self.assertEqual(put_item_data["ImmsID"], imms_id) + +# def test_handler_success_delete_physical(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# imms_id = "test-update-imms-id" +# event = ValuesForTests.get_event(event_name=EventName.DELETE_PHYSICAL, operation=Operation.DELETE_PHYSICAL, imms_id=imms_id) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.mock_delta_table.put_item.assert_called() +# self.mock_firehose_logger.send_log.assert_called() # check logged +# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB +# put_item_data = put_item_call_args.kwargs["Item"] +# self.assertIn("Imms", put_item_data) +# self.assertEqual(put_item_data["Operation"], Operation.DELETE_PHYSICAL) +# self.assertEqual(put_item_data["ImmsID"], imms_id) +# self.assertEqual(put_item_data["Imms"], "") # check imms has been blanked out + +# def test_handler_success_delete_logical(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# imms_id = "test-update-imms-id" +# event = ValuesForTests.get_event(event_name=EventName.UPDATE, +# operation=Operation.DELETE_LOGICAL, +# imms_id=imms_id) +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.mock_delta_table.put_item.assert_called() +# self.mock_firehose_logger.send_log.assert_called() # check logged +# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB +# put_item_data = put_item_call_args.kwargs["Item"] +# self.assertIn("Imms", put_item_data) +# self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.DELETE_LOGICAL) +# self.assertEqual(put_item_data["Operation"], Operation.DELETE_LOGICAL) +# self.assertEqual(put_item_data["ImmsID"], imms_id) + +# @patch("delta.logger.info") +# def test_dps_record_skipped(self, mock_logger_info): +# event = ValuesForTests.get_event(supplier="DPSFULL") + +# response = handler(event, None) + +# self.assertTrue(response) + +# # Check logging and Firehose were called +# mock_logger_info.assert_called_with("Record from DPS skipped for 12345") + +# @patch("delta.Converter") +# def test_partial_success_with_errors(self, mock_converter): +# mock_converter_instance = MagicMock() +# mock_converter_instance.run_conversion.return_value = {"ABC":"DEF"} +# mock_converter_instance.get_error_records.return_value = [{"error": "Invalid field"}] +# mock_converter.return_value = mock_converter_instance + +# # Mock DynamoDB put_item success +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + +# event = ValuesForTests.get_event() + +# response = handler(event, None) + +# self.assertTrue(response) +# # Check logging and Firehose were called +# self.mock_logger_info.assert_called() +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 1) +# self.mock_firehose_logger.send_log.assert_called_once() + +# # Get the actual argument passed to send_log +# args, kwargs = self.mock_firehose_logger.send_log.call_args +# sent_payload = args[0] # First positional arg + +# # Navigate to the specific message +# status_desc = sent_payload["event"]["operation_outcome"]["statusDesc"] + +# # Assert the expected message is present +# self.assertIn( +# "Partial success: successfully synced into delta, but issues found within record", +# status_desc +# ) + +# def test_send_message_multi_records_diverse(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# records_config = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), +# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "id3", ActionFlag.DELETE_LOGICAL), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) + +# def test_send_message_skipped_records_diverse(self): +# '''Check skipped records sent to firehose but not to DynamoDB''' +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# records_config = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), +# RecordConfig(EventName.CREATE, Operation.CREATE, "id-skip", ActionFlag.CREATE, "DPSFULL"), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) + +# def test_send_message_multi_create(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# records_config = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "create-id1", ActionFlag.CREATE), +# RecordConfig(EventName.CREATE, Operation.CREATE, "create-id2", ActionFlag.CREATE), +# RecordConfig(EventName.CREATE, Operation.CREATE, "create-id3", ActionFlag.CREATE) +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + + +# def test_send_message_multi_update(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# records_config = [ +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id1", ActionFlag.UPDATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id2", ActionFlag.UPDATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id3", ActionFlag.UPDATE) +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + +# def test_send_message_multi_logical_delete(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + +# records_config = [ +# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id1", ActionFlag.DELETE_LOGICAL), +# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id2", ActionFlag.DELETE_LOGICAL), +# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id3", ActionFlag.DELETE_LOGICAL) +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + +# def test_send_message_multi_physical_delete(self): +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# records_config = [ +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id1"), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id2"), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id3") +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + +# def test_single_error_in_multi(self): +# # Arrange +# self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] + +# records_config = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id1", ActionFlag.CREATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id1.2", ActionFlag.UPDATE), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id1.3"), +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertFalse(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) +# self.assertEqual(self.mock_logger_warning.call_count, 1) + +# def test_single_exception_in_multi(self): +# # Arrange +# # 2nd record fails +# self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, EXCEPTION_RESPONSE, SUCCESS_RESPONSE] + +# records_config = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id2.1", ActionFlag.CREATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "exception-id2.2", ActionFlag.UPDATE), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id2.3"), +# ] +# event = ValuesForTests.get_multi_record_event(records_config) + +# # Act +# result = handler(event, None) + +# # Assert +# self.assertFalse(result) +# self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) +# self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) + +# @patch("delta.process_record") +# @patch("delta.send_firehose") +# def test_handler_calls_process_record_for_each_event(self, mock_send_firehose, mock_process_record): +# # Arrange +# event = { +# "Records": [ +# { "a": "record1" }, +# { "a": "record2" }, +# { "a": "record3" } +# ] +# } +# # Mock process_record to always return True +# mock_process_record.return_value = True, {} +# mock_send_firehose.return_value = None + +# # Act +# result = handler(event, {}) + +# # Assert +# self.assertTrue(result) +# self.assertEqual(mock_process_record.call_count, len(event["Records"])) + +# # TODO depedency injection needed here +# @patch("delta.process_record") +# @patch("delta.send_firehose") +# def test_handler_sends_all_to_firehose(self, mock_send_firehose, mock_process_record): +# # Arrange + +# # event with 3 records +# event = { +# "Records": [ +# { "a": "record1" }, +# { "a": "record2" }, +# { "a": "record3" } +# ] +# } +# return_ok = (True, {}) +# return_fail = (False, {}) +# mock_send_firehose.return_value = None +# mock_process_record.side_effect = [return_ok, return_fail, return_ok] + +# # Act +# result = handler(event, {}) + +# # Assert +# self.assertFalse(result) +# self.assertEqual(mock_process_record.call_count, len(event["Records"])) +# # check that all records were sent to firehose +# self.assertEqual(mock_send_firehose.call_count, len(event["Records"])) + +# class DeltaRecordProcessorTestCase(unittest.TestCase): + +# def setUp(self): +# self.logger_info_patcher = patch("logging.Logger.info") +# self.mock_logger_info = self.logger_info_patcher.start() + +# self.logger_exception_patcher = patch("logging.Logger.exception") +# self.mock_logger_exception = self.logger_exception_patcher.start() + +# self.logger_warning_patcher = patch("logging.Logger.warning") +# self.mock_logger_warning = self.logger_warning_patcher.start() + +# self.delta_table_patcher=patch("delta.delta_table") +# self.mock_delta_table = self.delta_table_patcher.start() + +# def tearDown(self): +# self.logger_exception_patcher.stop() +# self.logger_warning_patcher.stop() +# self.logger_info_patcher.stop() +# self.delta_table_patcher.stop() + +# def test_multi_record_success(self): + +# # Arrange +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# test_configs = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "ok-id.2", ActionFlag.UPDATE), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), +# ] +# test_index = 0 +# for config in test_configs: +# test_index += 1 +# record = ValuesForTests.get_event_record( +# imms_id=config.imms_id, +# event_name=config.event_name, +# operation=config.operation, +# supplier=config.supplier, +# ) +# # Act +# result, log_data = process_record(record, {}) + +# # Assert +# self.assertEqual(result, True) +# operation_outcome = log_data["operation_outcome"] +# self.assertEqual(operation_outcome["record"], config.imms_id) +# self.assertEqual(operation_outcome["operation_type"], config.operation) +# self.assertEqual(operation_outcome["statusCode"], "200") +# self.assertEqual(operation_outcome["statusDesc"], "Successfully synched into delta") +# self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) + +# self.assertEqual(self.mock_logger_exception.call_count, 0) +# 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 = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] +# test_configs = [ +# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), +# RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id.2", ActionFlag.UPDATE), +# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), +# ] +# test_index = 0 +# for config in test_configs: +# test_index += 1 +# record = ValuesForTests.get_event_record( +# imms_id=config.imms_id, +# event_name=config.event_name, +# operation=config.operation, +# supplier=config.supplier, +# ) +# log_data = {} +# # Act +# result, log_data = process_record(record, log_data) + +# # Assert +# self.assertEqual(result, expected_returns[test_index-1]) +# self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) + +# self.assertEqual(self.mock_logger_exception.call_count, 0) +# self.assertEqual(self.mock_logger_warning.call_count, 1) + + +# def test_single_record_table_exception(self): + +# # Arrange +# imms_id = "exception-id" +# record = ValuesForTests.get_event_record( +# imms_id, +# event_name=EventName.UPDATE, +# operation=Operation.UPDATE, +# supplier="EMIS", +# ) +# self.mock_delta_table.put_item.return_value = EXCEPTION_RESPONSE +# # Act +# result, log_data = process_record(record, {}) + +# # Assert +# self.assertEqual(result, False) +# operation_outcome = log_data["operation_outcome"] +# self.assertEqual(operation_outcome["record"], imms_id) +# self.assertEqual(operation_outcome["operation_type"], Operation.UPDATE) +# self.assertEqual(operation_outcome["statusCode"], "500") +# self.assertEqual(operation_outcome["statusDesc"], "Exception") +# self.assertEqual(self.mock_delta_table.put_item.call_count, 1) +# self.assertEqual(self.mock_logger_exception.call_count, 1) + +# @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 +# ) + +# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE +# # Act +# process_record(record, {}) + +# # Assert +# mock_json_loads.assert_any_call(ValuesForTests.json_value_for_test, parse_float=decimal.Decimal) + + +# import delta + +# class TestGetDeltaTable(unittest.TestCase): +# def setUp(self): +# self.delta_table_patcher=patch("delta.delta_table") +# self.mock_delta_table = self.delta_table_patcher.start() +# self.logger_info_patcher = patch("logging.Logger.info") +# self.mock_logger_info = self.logger_info_patcher.start() +# self.logger_error_patcher = patch("logging.Logger.error") +# self.mock_logger_error = self.logger_error_patcher.start() + +# def tearDown(self): +# self.delta_table_patcher.stop() +# self.logger_info_patcher.stop() +# 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 +# self.assertIs(delta.delta_table, self.mock_delta_table) + +# @patch("boto3.resource") +# def test_returns_cached_table(self, mock_boto3_resource): +# delta.delta_table = self.mock_delta_table + +# table = delta.get_delta_table() +# self.assertIs(table, self.mock_delta_table) +# # Should not call boto3 again +# mock_boto3_resource.assert_not_called() + +# # mock boto3.resource to raise an exception +# @patch("boto3.resource") +# def test_returns_none_on_exception(self, mock_boto3_resource): +# delta.delta_table = None +# mock_boto3_resource.side_effect = Exception("fail") +# table = delta.get_delta_table() +# self.assertIsNone(table) +# self.mock_logger_error.assert_called() + +# import delta + +# class TestGetSqsClient(unittest.TestCase): +# def setUp(self): +# # Patch logger.info and logger.error +# self.logger_info_patcher = patch("logging.Logger.info") +# self.mock_logger_info = self.logger_info_patcher.start() +# self.logger_error_patcher = patch("logging.Logger.error") +# self.mock_logger_error = self.logger_error_patcher.start() +# self.sqs_client_patcher = patch("delta.boto3.client") +# self.mock_sqs_client = self.sqs_client_patcher.start() +# # Reset the global sqs_client before each test +# delta.sqs_client = None + +# def tearDown(self): +# self.logger_info_patcher.stop() +# self.logger_error_patcher.stop() +# self.sqs_client_patcher.stop() + +# def test_returns_client_on_success(self): +# mock_client = MagicMock() +# self.mock_sqs_client.return_value = mock_client + +# client = delta.get_sqs_client() +# self.assertIs(client, mock_client) +# # Should cache the client +# self.assertIs(delta.sqs_client, mock_client) + +# def test_returns_cached_client(self): +# mock_client = MagicMock() +# delta.sqs_client = mock_client + +# client = delta.get_sqs_client() +# self.assertIs(client, mock_client) +# # Should not re-initialize +# self.mock_sqs_client.assert_not_called() + +# def test_returns_none_on_exception(self): +# self.mock_sqs_client.side_effect = Exception("fail") +# client = delta.get_sqs_client() +# self.assertIsNone(client) +# self.mock_logger_error.assert_called() + + +# import delta + +# class TestSendMessage(unittest.TestCase): +# def setUp(self): +# self.get_sqs_client_patcher = patch("delta.get_sqs_client") +# self.mock_get_sqs_client = self.get_sqs_client_patcher.start() +# self.mock_sqs_client = MagicMock() +# self.mock_get_sqs_client.return_value = self.mock_sqs_client + +# self.logger_info_patcher = patch("logging.Logger.info") +# self.mock_logger_info = self.logger_info_patcher.start() +# self.logger_error_patcher = patch("logging.Logger.error") +# self.mock_logger_error = self.logger_error_patcher.start() + +# def tearDown(self): +# self.get_sqs_client_patcher.stop() +# self.logger_info_patcher.stop() +# self.logger_error_patcher.stop() + +# def test_send_message_success(self): +# record = {"a": "bbb"} +# self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} + +# delta.send_message(record) + +# self.mock_sqs_client.send_message.assert_called_once() +# self.mock_logger_info.assert_any_call("Record saved successfully to the DLQ") +# self.mock_logger_error.assert_not_called() + +# def test_send_message_client_error(self): +# record = {"a": "bbb"} +# self.mock_sqs_client.send_message.side_effect = Exception("SQS error") + +# delta.send_message(record, "test-queue-url") + +# self.mock_logger_error.assert_called() diff --git a/delta_backend/tests/test_log_firehose.py b/delta_backend/tests/test_log_firehose.py index 9ac716e073..c3351d7b04 100644 --- a/delta_backend/tests/test_log_firehose.py +++ b/delta_backend/tests/test_log_firehose.py @@ -1,71 +1,71 @@ -import unittest -from unittest.mock import patch, MagicMock -import json -from log_firehose import FirehoseLogger +# import unittest +# from unittest.mock import patch, MagicMock +# import json +# from log_firehose import FirehoseLogger -class TestFirehoseLogger(unittest.TestCase): +# class TestFirehoseLogger(unittest.TestCase): - def setUp(self): - # Common setup if needed - self.context = {} - self.logger_info_patcher = patch("logging.Logger.info") - self.mock_logger_info = self.logger_info_patcher.start() +# def setUp(self): +# # Common setup if needed +# self.context = {} +# self.logger_info_patcher = patch("logging.Logger.info") +# self.mock_logger_info = self.logger_info_patcher.start() - def tearDown(self): - self.logger_info_patcher.stop() +# def tearDown(self): +# self.logger_info_patcher.stop() - @patch("boto3.client") - def test_send_log(self, mock_boto_client): - """it should send log message to Firehose""" +# @patch("boto3.client") +# def test_send_log(self, mock_boto_client): +# """it should send log message to Firehose""" - # Arrange - mock_response = { - "RecordId": "shardId-000000000000000000000001", - "ResponseMetadata": { - "RequestId": "12345abcde67890fghijk", - "HTTPStatusCode": 200, - "RetryAttempts": 0 - } - } - mock_firehose_client = MagicMock() - mock_boto_client.return_value = mock_firehose_client - mock_firehose_client.put_record.return_value = mock_response +# # Arrange +# mock_response = { +# "RecordId": "shardId-000000000000000000000001", +# "ResponseMetadata": { +# "RequestId": "12345abcde67890fghijk", +# "HTTPStatusCode": 200, +# "RetryAttempts": 0 +# } +# } +# mock_firehose_client = MagicMock() +# mock_boto_client.return_value = mock_firehose_client +# mock_firehose_client.put_record.return_value = mock_response - stream_name = "stream_name" - firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) - log_message = {"text": "Test log message"} +# stream_name = "stream_name" +# firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) +# log_message = {"text": "Test log message"} - # Act - firehose_logger.send_log(log_message) +# # Act +# firehose_logger.send_log(log_message) - # Assert - mock_firehose_client.put_record.assert_called_once() - self.assertEqual(mock_firehose_client.put_record.return_value, mock_response) +# # Assert +# mock_firehose_client.put_record.assert_called_once() +# self.assertEqual(mock_firehose_client.put_record.return_value, mock_response) - @patch("boto3.client") - def test_send_log_failure(self, mock_boto_client): - """Test that send_log logs an exception when put_record fails.""" +# @patch("boto3.client") +# def test_send_log_failure(self, mock_boto_client): +# """Test that send_log logs an exception when put_record fails.""" - # Arrange - mock_firehose_client = MagicMock() - mock_boto_client.return_value = mock_firehose_client - mock_firehose_client.put_record.side_effect = Exception("Test exception") +# # Arrange +# mock_firehose_client = MagicMock() +# mock_boto_client.return_value = mock_firehose_client +# mock_firehose_client.put_record.side_effect = Exception("Test exception") - stream_name = "test-stream" - firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) - log_message = {"key": "value"} +# stream_name = "test-stream" +# firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) +# log_message = {"key": "value"} - with patch("log_firehose.logger.exception") as mock_logger_exception: - # Act - firehose_logger.send_log(log_message) +# with patch("log_firehose.logger.exception") as mock_logger_exception: +# # Act +# firehose_logger.send_log(log_message) - # Assert - mock_firehose_client.put_record.assert_called_once_with( - DeliveryStreamName="test-stream", - Record={"Data": json.dumps(log_message).encode("utf-8")}, - ) - mock_logger_exception.assert_called_once_with("Error sending log to Firehose: Test exception") +# # Assert +# mock_firehose_client.put_record.assert_called_once_with( +# DeliveryStreamName="test-stream", +# Record={"Data": json.dumps(log_message).encode("utf-8")}, +# ) +# mock_logger_exception.assert_called_once_with("Error sending log to Firehose: Test exception") -if __name__ == "__main__": - unittest.main() \ No newline at end of file +# if __name__ == "__main__": +# unittest.main() \ No newline at end of file diff --git a/delta_backend/tests/test_utils.py b/delta_backend/tests/test_utils.py index 134317d2b9..0bb1249a02 100644 --- a/delta_backend/tests/test_utils.py +++ b/delta_backend/tests/test_utils.py @@ -1,12 +1,12 @@ -import unittest -from utils import is_valid_simple_snomed +# import unittest +# from utils import is_valid_simple_snomed -class TestIsValidSimpleSnomed(unittest.TestCase): +# class TestIsValidSimpleSnomed(unittest.TestCase): - def test_valid_snomed(self): - valid_snomed = "956951000000104" - self.assertTrue(is_valid_simple_snomed(valid_snomed)) +# def test_valid_snomed(self): +# valid_snomed = "956951000000104" +# self.assertTrue(is_valid_simple_snomed(valid_snomed)) - def test_invalid_snomed(self): - invalid_snomed = "956951000000105" - self.assertFalse(is_valid_simple_snomed(invalid_snomed)) +# def test_invalid_snomed(self): +# invalid_snomed = "956951000000105" +# self.assertFalse(is_valid_simple_snomed(invalid_snomed)) From c7180c753cb7ece5a053ba61638f2759abb69aa2 Mon Sep 17 00:00:00 2001 From: nhsdevws Date: Tue, 3 Jun 2025 11:43:11 +0100 Subject: [PATCH 24/24] Script --- .github/scripts/run_test.sh | 14 +- .github/workflows/sonarcloud.yml | 148 +-- delta_backend/tests/test_convert.py | 400 +++---- delta_backend/tests/test_delta.py | 1348 +++++++++++----------- delta_backend/tests/test_log_firehose.py | 112 +- delta_backend/tests/test_utils.py | 18 +- 6 files changed, 1025 insertions(+), 1015 deletions(-) diff --git a/.github/scripts/run_test.sh b/.github/scripts/run_test.sh index 218ed46012..9b7a9ff12b 100755 --- a/.github/scripts/run_test.sh +++ b/.github/scripts/run_test.sh @@ -5,15 +5,7 @@ PYTHON_VERSION="$1" DESCRIPTION="$2" COVERAGE_XML="sonarcloud-coverage-$3.xml" - - poetry env use 3.10 - poetry install - poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt - poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml - - - poetry env use "$PYTHON_VERSION" - poetry install - poetry run coverage run -m unittest discover || echo "$DESCRIPTION tests failed" >> ../failed_tests.txt - +poetry env use "$PYTHON_VERSION" +poetry install +poetry run coverage run -m unittest discover || echo "$DESCRIPTION tests failed" >> ../failed_tests.txt poetry run coverage xml -o "../$COVERAGE_XML" \ No newline at end of file diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 7f437a9686..de212b179d 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -6,6 +6,9 @@ on: - master pull_request: types: [labeled, opened, synchronize, reopened, unlabeled] +env: + SCRIPT_FOLDER: ./.github/scripts + RUN_TEST: source ../.github/scripts/run_test.sh jobs: sonarcloud: @@ -20,6 +23,10 @@ jobs: with: fetch-depth: 0 + - name: Chmod .github directory + run: | + chmod +x $SCRIPT_FOLDER/*.sh + - name: Install poetry run: pip install poetry==1.8.4 @@ -44,50 +51,50 @@ jobs: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY - # - name: Run unittest with filenameprocessor-coverage - # if: matrix.python-version == '3.10' - # working-directory: filenameprocessor - # id: filenameprocessor - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml - - # - name: Run unittest with recordprocessor-coverage - # if: matrix.python-version == '3.10' - # working-directory: recordprocessor - # id: recordprocessor - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml - - # # This step is redundant - all of these tests will be run in the backend step below - # - name: Run unittest with recordforwarder-coverage - # if: matrix.python-version == '3.11' - # working-directory: backend - # id: recordforwarder - # continue-on-error: true - # run: | - # poetry env use 3.11 - # poetry install - # poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml - - # - name: Run unittest with coverage-ack-lambda - # if: matrix.python-version == '3.10' - # working-directory: ack_backend - # id: acklambda - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml + - name: Run unittest with filenameprocessor-coverage + if: matrix.python-version == '3.10' + working-directory: filenameprocessor + id: filenameprocessor + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "filenameprocessor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-filenameprocessor-coverage.xml + + - name: Run unittest with recordprocessor-coverage + if: matrix.python-version == '3.10' + working-directory: recordprocessor + id: recordprocessor + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "recordprocessor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-recordprocessor-coverage.xml + + # This step is redundant - all of these tests will be run in the backend step below + - name: Run unittest with recordforwarder-coverage + if: matrix.python-version == '3.11' + working-directory: backend + id: recordforwarder + continue-on-error: true + run: | + poetry env use 3.11 + poetry install + poetry run coverage run -m unittest discover -s "./tests" -p "*batch*.py" || echo "recordforwarder tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-recordforwarder-coverage.xml + + - name: Run unittest with coverage-ack-lambda + if: matrix.python-version == '3.10' + working-directory: ack_backend + id: acklambda + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "ack-lambda tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage-ack-lambda.xml - name: Run unittest with coverage-delta if: matrix.python-version == '3.11' @@ -102,27 +109,38 @@ jobs: poetry run coverage run -m unittest discover || echo "delta tests failed" >> ../failed_tests.txt poetry run coverage xml -o ../sonarcloud-coverage-delta.xml - # - name: Run unittest with coverage-fhir-api - # if: matrix.python-version == '3.11' - # working-directory: backend - # id: fhirapi - # continue-on-error: true - # run: | - # poetry env use 3.11 - # poetry install - # poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-coverage.xml - - # - name: Run unittest with coverage-mesh-processor - # if: matrix.python-version == '3.10' - # working-directory: mesh_processor - # id: meshprocessor - # continue-on-error: true - # run: | - # poetry env use 3.10 - # poetry install - # poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt - # poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml + + - name: Run unittest with coverage-delta2 + if: matrix.python-version == '3.11' + working-directory: delta_backend + id: delta2 + env: + PYTHONPATH: delta_backend/src:delta_backend/tests + continue-on-error: true + run: | + $RUN_TEST 3.11 delta_backend delta_backend + + - name: Run unittest with coverage-fhir-api + if: matrix.python-version == '3.11' + working-directory: backend + id: fhirapi + continue-on-error: true + run: | + poetry env use 3.11 + poetry install + poetry run coverage run -m unittest discover || echo "fhir-api tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-coverage.xml + + - name: Run unittest with coverage-mesh-processor + if: matrix.python-version == '3.10' + working-directory: mesh_processor + id: meshprocessor + continue-on-error: true + run: | + poetry env use 3.10 + poetry install + poetry run coverage run -m unittest discover || echo "mesh_processor tests failed" >> ../failed_tests.txt + poetry run coverage xml -o ../sonarcloud-mesh_processor-coverage.xml - name: Run Test Failure Summary id: check_failure diff --git a/delta_backend/tests/test_convert.py b/delta_backend/tests/test_convert.py index b13c96b8da..6e270e33d9 100644 --- a/delta_backend/tests/test_convert.py +++ b/delta_backend/tests/test_convert.py @@ -1,233 +1,233 @@ -# import json -# import unittest -# from copy import deepcopy -# from unittest.mock import patch, Mock -# from moto import mock_aws -# from boto3 import resource as boto3_resource -# from utils_for_converter_tests import ValuesForTests, ErrorValuesForTests -# from converter import Converter -# from common.mappings import ActionFlag, Operation, EventName - -# MOCK_ENV_VARS = { -# "AWS_SQS_QUEUE_URL": "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue", -# "DELTA_TABLE_NAME": "immunisation-batch-internal-dev-audit-test-table", -# "SOURCE": "test-source", -# } -# request_json_data = ValuesForTests.json_data -# with patch.dict("os.environ", MOCK_ENV_VARS): -# from delta import handler, Converter - - -# @patch.dict("os.environ", MOCK_ENV_VARS, clear=True) -# class TestConvertToFlatJson(unittest.TestCase): -# maxDiff = None -# def setUp(self): -# # Start moto AWS mocks -# self.mock = mock_aws() -# self.mock.start() +import json +import unittest +from copy import deepcopy +from unittest.mock import patch, Mock +from moto import mock_aws +from boto3 import resource as boto3_resource +from utils_for_converter_tests import ValuesForTests, ErrorValuesForTests +from converter import Converter +from common.mappings import ActionFlag, Operation, EventName + +MOCK_ENV_VARS = { + "AWS_SQS_QUEUE_URL": "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue", + "DELTA_TABLE_NAME": "immunisation-batch-internal-dev-audit-test-table", + "SOURCE": "test-source", +} +request_json_data = ValuesForTests.json_data +with patch.dict("os.environ", MOCK_ENV_VARS): + from delta import handler, Converter + + +@patch.dict("os.environ", MOCK_ENV_VARS, clear=True) +class TestConvertToFlatJson(unittest.TestCase): + maxDiff = None + def setUp(self): + # Start moto AWS mocks + self.mock = mock_aws() + self.mock.start() -# """Set up mock DynamoDB table.""" -# self.dynamodb_resource = boto3_resource("dynamodb", "eu-west-2") -# self.table = self.dynamodb_resource.create_table( -# TableName="immunisation-batch-internal-dev-audit-test-table", -# KeySchema=[ -# {"AttributeName": "PK", "KeyType": "HASH"}, -# ], -# AttributeDefinitions=[ -# {"AttributeName": "PK", "AttributeType": "S"}, -# {"AttributeName": "Operation", "AttributeType": "S"}, -# {"AttributeName": "IdentifierPK", "AttributeType": "S"}, -# {"AttributeName": "SupplierSystem", "AttributeType": "S"}, -# ], -# ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, -# GlobalSecondaryIndexes=[ -# { -# "IndexName": "IdentifierGSI", -# "KeySchema": [{"AttributeName": "IdentifierPK", "KeyType": "HASH"}], -# "Projection": {"ProjectionType": "ALL"}, -# "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, -# }, -# { -# "IndexName": "PatientGSI", -# "KeySchema": [ -# {"AttributeName": "Operation", "KeyType": "HASH"}, -# {"AttributeName": "SupplierSystem", "KeyType": "RANGE"}, -# ], -# "Projection": {"ProjectionType": "ALL"}, -# "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, -# }, -# ], -# ) -# self.logger_info_patcher = patch("logging.Logger.info") -# self.mock_logger_info = self.logger_info_patcher.start() - -# self.logger_exception_patcher = patch("logging.Logger.exception") -# self.mock_logger_exception = self.logger_exception_patcher.start() - -# self.firehose_logger_patcher = patch("delta.firehose_logger") -# self.mock_firehose_logger = self.firehose_logger_patcher.start() - -# def tearDown(self): -# self.logger_exception_patcher.stop() -# self.logger_info_patcher.stop() -# self.mock_firehose_logger.stop() + """Set up mock DynamoDB table.""" + self.dynamodb_resource = boto3_resource("dynamodb", "eu-west-2") + self.table = self.dynamodb_resource.create_table( + TableName="immunisation-batch-internal-dev-audit-test-table", + KeySchema=[ + {"AttributeName": "PK", "KeyType": "HASH"}, + ], + AttributeDefinitions=[ + {"AttributeName": "PK", "AttributeType": "S"}, + {"AttributeName": "Operation", "AttributeType": "S"}, + {"AttributeName": "IdentifierPK", "AttributeType": "S"}, + {"AttributeName": "SupplierSystem", "AttributeType": "S"}, + ], + ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, + GlobalSecondaryIndexes=[ + { + "IndexName": "IdentifierGSI", + "KeySchema": [{"AttributeName": "IdentifierPK", "KeyType": "HASH"}], + "Projection": {"ProjectionType": "ALL"}, + "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, + }, + { + "IndexName": "PatientGSI", + "KeySchema": [ + {"AttributeName": "Operation", "KeyType": "HASH"}, + {"AttributeName": "SupplierSystem", "KeyType": "RANGE"}, + ], + "Projection": {"ProjectionType": "ALL"}, + "ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, + }, + ], + ) + self.logger_info_patcher = patch("logging.Logger.info") + self.mock_logger_info = self.logger_info_patcher.start() + + self.logger_exception_patcher = patch("logging.Logger.exception") + self.mock_logger_exception = self.logger_exception_patcher.start() + + self.firehose_logger_patcher = patch("delta.firehose_logger") + self.mock_firehose_logger = self.firehose_logger_patcher.start() + + def tearDown(self): + self.logger_exception_patcher.stop() + self.logger_info_patcher.stop() + self.mock_firehose_logger.stop() -# self.mock.stop() + self.mock.stop() -# @staticmethod -# def get_event(event_name=EventName.CREATE, operation="operation", supplier="EMIS"): -# """Returns test event data.""" -# return ValuesForTests.get_event(event_name, operation, supplier) + @staticmethod + def get_event(event_name=EventName.CREATE, operation="operation", supplier="EMIS"): + """Returns test event data.""" + return ValuesForTests.get_event(event_name, operation, supplier) -# def assert_dynamodb_record(self, operation_flag, action_flag, items, expected_values, expected_imms, response): -# """ -# Asserts that a record with the expected structure exists in DynamoDB. -# Ignores dynamically generated fields like PK, DateTimeStamp, and ExpiresAt. -# Ensures that the 'Imms' field matches exactly. -# """ -# self.assertTrue(response) + def assert_dynamodb_record(self, operation_flag, action_flag, items, expected_values, expected_imms, response): + """ + Asserts that a record with the expected structure exists in DynamoDB. + Ignores dynamically generated fields like PK, DateTimeStamp, and ExpiresAt. + Ensures that the 'Imms' field matches exactly. + """ + self.assertTrue(response) -# filtered_items = [ -# {k: v for k, v in item.items() if k not in ["PK", "DateTimeStamp", "ExpiresAt"]} -# for item in items -# if item.get("Operation") == operation_flag -# and item.get("Imms", {}).get("ACTION_FLAG") == action_flag -# ] + filtered_items = [ + {k: v for k, v in item.items() if k not in ["PK", "DateTimeStamp", "ExpiresAt"]} + for item in items + if item.get("Operation") == operation_flag + and item.get("Imms", {}).get("ACTION_FLAG") == action_flag + ] -# self.assertGreater(len(filtered_items), 0, f"No matching item found for {operation_flag}") + self.assertGreater(len(filtered_items), 0, f"No matching item found for {operation_flag}") -# imms_data = filtered_items[0]["Imms"] -# self.assertIsInstance(imms_data, dict) -# self.assertGreater(len(imms_data), 0) + imms_data = filtered_items[0]["Imms"] + self.assertIsInstance(imms_data, dict) + self.assertGreater(len(imms_data), 0) -# # Check Imms JSON structure matches exactly -# self.assertEqual(imms_data, expected_imms, "Imms data does not match expected JSON structure") + # Check Imms JSON structure matches exactly + self.assertEqual(imms_data, expected_imms, "Imms data does not match expected JSON structure") -# for key, expected_value in expected_values.items(): -# self.assertIn(key, filtered_items[0], f"{key} is missing") -# self.assertEqual(filtered_items[0][key], expected_value, f"{key} mismatch") + for key, expected_value in expected_values.items(): + self.assertIn(key, filtered_items[0], f"{key} is missing") + self.assertEqual(filtered_items[0][key], expected_value, f"{key} mismatch") -# def test_fhir_converter_json_direct_data(self): -# """it should convert fhir json data to flat json""" -# json_data = json.dumps(ValuesForTests.json_data) + def test_fhir_converter_json_direct_data(self): + """it should convert fhir json data to flat json""" + json_data = json.dumps(ValuesForTests.json_data) -# fhir_converter = Converter(json_data) -# FlatFile = fhir_converter.run_conversion() + fhir_converter = Converter(json_data) + FlatFile = fhir_converter.run_conversion() -# flatJSON = json.dumps(FlatFile) -# expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag -# expected_imms = json.dumps(expected_imms_value) -# self.assertEqual(flatJSON, expected_imms) + flatJSON = json.dumps(FlatFile) + expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag + expected_imms = json.dumps(expected_imms_value) + self.assertEqual(flatJSON, expected_imms) -# errorRecords = fhir_converter.get_error_records() + errorRecords = fhir_converter.get_error_records() -# self.assertEqual(len(errorRecords), 0) + self.assertEqual(len(errorRecords), 0) -# def test_fhir_converter_json_direct_data(self): -# """it should convert fhir json data to flat json""" -# json_data = json.dumps(ValuesForTests.json_data) + def test_fhir_converter_json_direct_data(self): + """it should convert fhir json data to flat json""" + json_data = json.dumps(ValuesForTests.json_data) -# fhir_converter = Converter(json_data) -# FlatFile = fhir_converter.run_conversion() + fhir_converter = Converter(json_data) + FlatFile = fhir_converter.run_conversion() -# flatJSON = json.dumps(FlatFile) -# expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag -# expected_imms = json.dumps(expected_imms_value) -# self.assertEqual(flatJSON, expected_imms) + flatJSON = json.dumps(FlatFile) + expected_imms_value = deepcopy(ValuesForTests.expected_imms2) # UPDATE is currently the default action-flag + expected_imms = json.dumps(expected_imms_value) + self.assertEqual(flatJSON, expected_imms) -# errorRecords = fhir_converter.get_error_records() + errorRecords = fhir_converter.get_error_records() -# self.assertEqual(len(errorRecords), 0) + self.assertEqual(len(errorRecords), 0) -# def test_fhir_converter_json_error_scenario_reporting_on(self): -# """it should convert fhir json data to flat json - error scenarios""" -# error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] + def test_fhir_converter_json_error_scenario_reporting_on(self): + """it should convert fhir json data to flat json - error scenarios""" + error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] -# for test_case in error_test_cases: -# json_data = json.dumps(test_case) + for test_case in error_test_cases: + json_data = json.dumps(test_case) -# fhir_converter = Converter(json_data) -# fhir_converter.run_conversion() + fhir_converter = Converter(json_data) + fhir_converter.run_conversion() -# errorRecords = fhir_converter.get_error_records() + errorRecords = fhir_converter.get_error_records() -# # Check if bad data creates error records -# self.assertTrue(len(errorRecords) > 0) + # Check if bad data creates error records + self.assertTrue(len(errorRecords) > 0) -# def test_fhir_converter_json_error_scenario_reporting_off(self): -# """it should convert fhir json data to flat json - error scenarios""" -# error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] + def test_fhir_converter_json_error_scenario_reporting_off(self): + """it should convert fhir json data to flat json - error scenarios""" + error_test_cases = [ErrorValuesForTests.missing_json, ErrorValuesForTests.json_dob_error] -# for test_case in error_test_cases: -# json_data = json.dumps(test_case) + for test_case in error_test_cases: + json_data = json.dumps(test_case) -# fhir_converter = Converter(json_data, report_unexpected_exception=False) -# fhir_converter.run_conversion() + fhir_converter = Converter(json_data, report_unexpected_exception=False) + fhir_converter.run_conversion() -# errorRecords = fhir_converter.get_error_records() + errorRecords = fhir_converter.get_error_records() -# # Check if bad data creates error records -# self.assertTrue(len(errorRecords) == 0) + # Check if bad data creates error records + self.assertTrue(len(errorRecords) == 0) -# def test_fhir_converter_json_incorrect_data_scenario_reporting_on(self): -# """it should convert fhir json data to flat json - error scenarios""" + def test_fhir_converter_json_incorrect_data_scenario_reporting_on(self): + """it should convert fhir json data to flat json - error scenarios""" -# with self.assertRaises(ValueError): -# fhir_converter = Converter(None) -# errorRecords = fhir_converter.get_error_records() -# self.assertTrue(len(errorRecords) > 0) + with self.assertRaises(ValueError): + fhir_converter = Converter(None) + errorRecords = fhir_converter.get_error_records() + self.assertTrue(len(errorRecords) > 0) -# def test_fhir_converter_json_incorrect_data_scenario_reporting_off(self): -# """it should convert fhir json data to flat json - error scenarios""" - -# with self.assertRaises(ValueError): -# fhir_converter = Converter(None, report_unexpected_exception=False) -# errorRecords = fhir_converter.get_error_records() -# self.assertTrue(len(errorRecords) == 0) - -# def test_handler_imms_convert_to_flat_json(self): -# """Test that the Imms field contains the correct flat JSON data for CREATE, UPDATE, and DELETE operations.""" -# expected_action_flags = [ -# {"Operation": Operation.CREATE, "EXPECTED_ACTION_FLAG": ActionFlag.CREATE}, -# {"Operation": Operation.UPDATE, "EXPECTED_ACTION_FLAG": ActionFlag.UPDATE}, -# {"Operation": Operation.DELETE_LOGICAL, "EXPECTED_ACTION_FLAG": ActionFlag.DELETE_LOGICAL}, -# ] - -# 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) - -# # Retrieve items from DynamoDB -# result = self.table.scan() -# items = result.get("Items", []) - -# expected_values = ValuesForTests.expected_static_values -# expected_imms = ValuesForTests.get_expected_imms(test_case["EXPECTED_ACTION_FLAG"]) - -# self.assert_dynamodb_record( -# test_case["Operation"], -# test_case["EXPECTED_ACTION_FLAG"], -# items, -# expected_values, -# expected_imms, -# response -# ) - -# result = self.table.scan() -# items = result.get("Items", []) -# self.clear_table() - -# def clear_table(self): -# scan = self.table.scan() -# with self.table.batch_writer() as batch: -# for item in scan.get("Items", []): -# batch.delete_item(Key={"PK": item["PK"]}) -# result = self.table.scan() -# items = result.get("Items", []) - -# if __name__ == "__main__": -# unittest.main() + def test_fhir_converter_json_incorrect_data_scenario_reporting_off(self): + """it should convert fhir json data to flat json - error scenarios""" + + with self.assertRaises(ValueError): + fhir_converter = Converter(None, report_unexpected_exception=False) + errorRecords = fhir_converter.get_error_records() + self.assertTrue(len(errorRecords) == 0) + + def test_handler_imms_convert_to_flat_json(self): + """Test that the Imms field contains the correct flat JSON data for CREATE, UPDATE, and DELETE operations.""" + expected_action_flags = [ + {"Operation": Operation.CREATE, "EXPECTED_ACTION_FLAG": ActionFlag.CREATE}, + {"Operation": Operation.UPDATE, "EXPECTED_ACTION_FLAG": ActionFlag.UPDATE}, + {"Operation": Operation.DELETE_LOGICAL, "EXPECTED_ACTION_FLAG": ActionFlag.DELETE_LOGICAL}, + ] + + 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) + + # Retrieve items from DynamoDB + result = self.table.scan() + items = result.get("Items", []) + + expected_values = ValuesForTests.expected_static_values + expected_imms = ValuesForTests.get_expected_imms(test_case["EXPECTED_ACTION_FLAG"]) + + self.assert_dynamodb_record( + test_case["Operation"], + test_case["EXPECTED_ACTION_FLAG"], + items, + expected_values, + expected_imms, + response + ) + + result = self.table.scan() + items = result.get("Items", []) + self.clear_table() + + def clear_table(self): + scan = self.table.scan() + with self.table.batch_writer() as batch: + for item in scan.get("Items", []): + batch.delete_item(Key={"PK": item["PK"]}) + result = self.table.scan() + items = result.get("Items", []) + + if __name__ == "__main__": + unittest.main() diff --git a/delta_backend/tests/test_delta.py b/delta_backend/tests/test_delta.py index 3ce3796fc0..08c64c7e0d 100644 --- a/delta_backend/tests/test_delta.py +++ b/delta_backend/tests/test_delta.py @@ -1,674 +1,674 @@ -# 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 - -# # Set environment variables before importing the module -# ## @TODO: # Note: Environment variables shared across tests, thus aligned -# os.environ["AWS_SQS_QUEUE_URL"] = "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue" -# os.environ["DELTA_TABLE_NAME"] = "my_delta_table" -# os.environ["SOURCE"] = "my_source" - -# from delta import send_message, handler, process_record # Import after setting environment variables - -# SUCCESS_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 200}} -# EXCEPTION_RESPONSE = ClientError({"Error": {"Code": "ConditionalCheckFailedException"}}, "PutItem") -# FAIL_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 500}} - -# 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") -# self.mock_logger_info = self.logger_info_patcher.start() - -# self.logger_exception_patcher = patch("logging.Logger.exception") -# self.mock_logger_exception = self.logger_exception_patcher.start() - -# self.logger_warning_patcher = patch("logging.Logger.warning") -# self.mock_logger_warning = self.logger_warning_patcher.start() - -# self.logger_error_patcher = patch("logging.Logger.error") -# self.mock_logger_error = self.logger_error_patcher.start() - -# self.firehose_logger_patcher = patch("delta.firehose_logger") -# self.mock_firehose_logger = self.firehose_logger_patcher.start() - -# self.sqs_client_patcher = patch("delta.sqs_client") -# self.mock_sqs_client = self.sqs_client_patcher.start() - -# self.delta_table_patcher=patch("delta.delta_table") -# self.mock_delta_table = self.delta_table_patcher.start() - -# def tearDown(self): -# self.logger_exception_patcher.stop() -# self.logger_warning_patcher.stop() -# self.logger_error_patcher.stop() -# self.logger_info_patcher.stop() -# self.mock_firehose_logger.stop() -# self.sqs_client_patcher.stop() -# self.delta_table_patcher.stop() - -# def test_send_message_success(self): -# # Arrange -# self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} -# record = {"key": "value"} -# sqs_queue_url = "test-queue-url" - -# # Act -# send_message(record, sqs_queue_url) - -# # Assert -# self.mock_sqs_client.send_message.assert_called_once_with( -# QueueUrl=sqs_queue_url, MessageBody=json.dumps(record) -# ) - -# def test_send_message_client_error(self): -# # Arrange -# record = {"key": "value"} - -# # Simulate ClientError -# error_response = {"Error": {"Code": "500", "Message": "Internal Server Error"}} -# self.mock_sqs_client.send_message.side_effect = ClientError(error_response, "SendMessage") - -# # Act -# send_message(record, "test-queue-url") - -# # Assert -# self.mock_logger_error.assert_called_once_with( -# f"Error sending record to DLQ: An error occurred (500) when calling the SendMessage operation: Internal Server Error" -# ) - -# def test_handler_success_insert(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# suppliers = ["DPS", "EMIS"] -# for supplier in suppliers: -# imms_id = f"test-insert-imms-{supplier}-id" -# event = ValuesForTests.get_event(event_name=EventName.CREATE, operation=Operation.CREATE, imms_id=imms_id, supplier=supplier) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.mock_delta_table.put_item.assert_called() -# self.mock_firehose_logger.send_log.assert_called() # check logged -# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB -# put_item_data = put_item_call_args.kwargs["Item"] -# self.assertIn("Imms", put_item_data) -# self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.CREATE) -# self.assertEqual(put_item_data["Operation"], Operation.CREATE) -# self.assertEqual(put_item_data["SupplierSystem"], supplier) - -# def test_handler_failure(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = FAIL_RESPONSE -# event = ValuesForTests.get_event() - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertFalse(result) - -# def test_handler_success_update(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# imms_id = "test-update-imms-id" -# event = ValuesForTests.get_event(event_name=EventName.UPDATE, operation=Operation.UPDATE, imms_id=imms_id) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.mock_delta_table.put_item.assert_called() -# self.mock_firehose_logger.send_log.assert_called() # check logged -# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB -# put_item_data = put_item_call_args.kwargs["Item"] -# self.assertIn("Imms", put_item_data) -# self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.UPDATE) -# self.assertEqual(put_item_data["Operation"], Operation.UPDATE) -# self.assertEqual(put_item_data["ImmsID"], imms_id) - -# def test_handler_success_delete_physical(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# imms_id = "test-update-imms-id" -# event = ValuesForTests.get_event(event_name=EventName.DELETE_PHYSICAL, operation=Operation.DELETE_PHYSICAL, imms_id=imms_id) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.mock_delta_table.put_item.assert_called() -# self.mock_firehose_logger.send_log.assert_called() # check logged -# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB -# put_item_data = put_item_call_args.kwargs["Item"] -# self.assertIn("Imms", put_item_data) -# self.assertEqual(put_item_data["Operation"], Operation.DELETE_PHYSICAL) -# self.assertEqual(put_item_data["ImmsID"], imms_id) -# self.assertEqual(put_item_data["Imms"], "") # check imms has been blanked out - -# def test_handler_success_delete_logical(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# imms_id = "test-update-imms-id" -# event = ValuesForTests.get_event(event_name=EventName.UPDATE, -# operation=Operation.DELETE_LOGICAL, -# imms_id=imms_id) -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.mock_delta_table.put_item.assert_called() -# self.mock_firehose_logger.send_log.assert_called() # check logged -# put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB -# put_item_data = put_item_call_args.kwargs["Item"] -# self.assertIn("Imms", put_item_data) -# self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.DELETE_LOGICAL) -# self.assertEqual(put_item_data["Operation"], Operation.DELETE_LOGICAL) -# self.assertEqual(put_item_data["ImmsID"], imms_id) - -# @patch("delta.logger.info") -# def test_dps_record_skipped(self, mock_logger_info): -# event = ValuesForTests.get_event(supplier="DPSFULL") - -# response = handler(event, None) - -# self.assertTrue(response) - -# # Check logging and Firehose were called -# mock_logger_info.assert_called_with("Record from DPS skipped for 12345") - -# @patch("delta.Converter") -# def test_partial_success_with_errors(self, mock_converter): -# mock_converter_instance = MagicMock() -# mock_converter_instance.run_conversion.return_value = {"ABC":"DEF"} -# mock_converter_instance.get_error_records.return_value = [{"error": "Invalid field"}] -# mock_converter.return_value = mock_converter_instance - -# # Mock DynamoDB put_item success -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - -# event = ValuesForTests.get_event() - -# response = handler(event, None) - -# self.assertTrue(response) -# # Check logging and Firehose were called -# self.mock_logger_info.assert_called() -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 1) -# self.mock_firehose_logger.send_log.assert_called_once() - -# # Get the actual argument passed to send_log -# args, kwargs = self.mock_firehose_logger.send_log.call_args -# sent_payload = args[0] # First positional arg - -# # Navigate to the specific message -# status_desc = sent_payload["event"]["operation_outcome"]["statusDesc"] - -# # Assert the expected message is present -# self.assertIn( -# "Partial success: successfully synced into delta, but issues found within record", -# status_desc -# ) - -# def test_send_message_multi_records_diverse(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# records_config = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), -# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "id3", ActionFlag.DELETE_LOGICAL), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) - -# def test_send_message_skipped_records_diverse(self): -# '''Check skipped records sent to firehose but not to DynamoDB''' -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# records_config = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), -# RecordConfig(EventName.CREATE, Operation.CREATE, "id-skip", ActionFlag.CREATE, "DPSFULL"), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) - -# def test_send_message_multi_create(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# records_config = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "create-id1", ActionFlag.CREATE), -# RecordConfig(EventName.CREATE, Operation.CREATE, "create-id2", ActionFlag.CREATE), -# RecordConfig(EventName.CREATE, Operation.CREATE, "create-id3", ActionFlag.CREATE) -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - - -# def test_send_message_multi_update(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# records_config = [ -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id1", ActionFlag.UPDATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id2", ActionFlag.UPDATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id3", ActionFlag.UPDATE) -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - -# def test_send_message_multi_logical_delete(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE - -# records_config = [ -# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id1", ActionFlag.DELETE_LOGICAL), -# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id2", ActionFlag.DELETE_LOGICAL), -# RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id3", ActionFlag.DELETE_LOGICAL) -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - -# def test_send_message_multi_physical_delete(self): -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# records_config = [ -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id1"), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id2"), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id3") -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) - -# def test_single_error_in_multi(self): -# # Arrange -# self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] - -# records_config = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id1", ActionFlag.CREATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id1.2", ActionFlag.UPDATE), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id1.3"), -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertFalse(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, 3) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) -# self.assertEqual(self.mock_logger_warning.call_count, 1) - -# def test_single_exception_in_multi(self): -# # Arrange -# # 2nd record fails -# self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, EXCEPTION_RESPONSE, SUCCESS_RESPONSE] - -# records_config = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id2.1", ActionFlag.CREATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "exception-id2.2", ActionFlag.UPDATE), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id2.3"), -# ] -# event = ValuesForTests.get_multi_record_event(records_config) - -# # Act -# result = handler(event, None) - -# # Assert -# self.assertFalse(result) -# self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) -# self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) - -# @patch("delta.process_record") -# @patch("delta.send_firehose") -# def test_handler_calls_process_record_for_each_event(self, mock_send_firehose, mock_process_record): -# # Arrange -# event = { -# "Records": [ -# { "a": "record1" }, -# { "a": "record2" }, -# { "a": "record3" } -# ] -# } -# # Mock process_record to always return True -# mock_process_record.return_value = True, {} -# mock_send_firehose.return_value = None - -# # Act -# result = handler(event, {}) - -# # Assert -# self.assertTrue(result) -# self.assertEqual(mock_process_record.call_count, len(event["Records"])) - -# # TODO depedency injection needed here -# @patch("delta.process_record") -# @patch("delta.send_firehose") -# def test_handler_sends_all_to_firehose(self, mock_send_firehose, mock_process_record): -# # Arrange - -# # event with 3 records -# event = { -# "Records": [ -# { "a": "record1" }, -# { "a": "record2" }, -# { "a": "record3" } -# ] -# } -# return_ok = (True, {}) -# return_fail = (False, {}) -# mock_send_firehose.return_value = None -# mock_process_record.side_effect = [return_ok, return_fail, return_ok] - -# # Act -# result = handler(event, {}) - -# # Assert -# self.assertFalse(result) -# self.assertEqual(mock_process_record.call_count, len(event["Records"])) -# # check that all records were sent to firehose -# self.assertEqual(mock_send_firehose.call_count, len(event["Records"])) - -# class DeltaRecordProcessorTestCase(unittest.TestCase): - -# def setUp(self): -# self.logger_info_patcher = patch("logging.Logger.info") -# self.mock_logger_info = self.logger_info_patcher.start() - -# self.logger_exception_patcher = patch("logging.Logger.exception") -# self.mock_logger_exception = self.logger_exception_patcher.start() - -# self.logger_warning_patcher = patch("logging.Logger.warning") -# self.mock_logger_warning = self.logger_warning_patcher.start() - -# self.delta_table_patcher=patch("delta.delta_table") -# self.mock_delta_table = self.delta_table_patcher.start() - -# def tearDown(self): -# self.logger_exception_patcher.stop() -# self.logger_warning_patcher.stop() -# self.logger_info_patcher.stop() -# self.delta_table_patcher.stop() - -# def test_multi_record_success(self): - -# # Arrange -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# test_configs = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "ok-id.2", ActionFlag.UPDATE), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), -# ] -# test_index = 0 -# for config in test_configs: -# test_index += 1 -# record = ValuesForTests.get_event_record( -# imms_id=config.imms_id, -# event_name=config.event_name, -# operation=config.operation, -# supplier=config.supplier, -# ) -# # Act -# result, log_data = process_record(record, {}) - -# # Assert -# self.assertEqual(result, True) -# operation_outcome = log_data["operation_outcome"] -# self.assertEqual(operation_outcome["record"], config.imms_id) -# self.assertEqual(operation_outcome["operation_type"], config.operation) -# self.assertEqual(operation_outcome["statusCode"], "200") -# self.assertEqual(operation_outcome["statusDesc"], "Successfully synched into delta") -# self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) - -# self.assertEqual(self.mock_logger_exception.call_count, 0) -# 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 = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] -# test_configs = [ -# RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), -# RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id.2", ActionFlag.UPDATE), -# RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), -# ] -# test_index = 0 -# for config in test_configs: -# test_index += 1 -# record = ValuesForTests.get_event_record( -# imms_id=config.imms_id, -# event_name=config.event_name, -# operation=config.operation, -# supplier=config.supplier, -# ) -# log_data = {} -# # Act -# result, log_data = process_record(record, log_data) - -# # Assert -# self.assertEqual(result, expected_returns[test_index-1]) -# self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) - -# self.assertEqual(self.mock_logger_exception.call_count, 0) -# self.assertEqual(self.mock_logger_warning.call_count, 1) - - -# def test_single_record_table_exception(self): - -# # Arrange -# imms_id = "exception-id" -# record = ValuesForTests.get_event_record( -# imms_id, -# event_name=EventName.UPDATE, -# operation=Operation.UPDATE, -# supplier="EMIS", -# ) -# self.mock_delta_table.put_item.return_value = EXCEPTION_RESPONSE -# # Act -# result, log_data = process_record(record, {}) - -# # Assert -# self.assertEqual(result, False) -# operation_outcome = log_data["operation_outcome"] -# self.assertEqual(operation_outcome["record"], imms_id) -# self.assertEqual(operation_outcome["operation_type"], Operation.UPDATE) -# self.assertEqual(operation_outcome["statusCode"], "500") -# self.assertEqual(operation_outcome["statusDesc"], "Exception") -# self.assertEqual(self.mock_delta_table.put_item.call_count, 1) -# self.assertEqual(self.mock_logger_exception.call_count, 1) - -# @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 -# ) - -# self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE -# # Act -# process_record(record, {}) - -# # Assert -# mock_json_loads.assert_any_call(ValuesForTests.json_value_for_test, parse_float=decimal.Decimal) - - -# import delta - -# class TestGetDeltaTable(unittest.TestCase): -# def setUp(self): -# self.delta_table_patcher=patch("delta.delta_table") -# self.mock_delta_table = self.delta_table_patcher.start() -# self.logger_info_patcher = patch("logging.Logger.info") -# self.mock_logger_info = self.logger_info_patcher.start() -# self.logger_error_patcher = patch("logging.Logger.error") -# self.mock_logger_error = self.logger_error_patcher.start() - -# def tearDown(self): -# self.delta_table_patcher.stop() -# self.logger_info_patcher.stop() -# 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 -# self.assertIs(delta.delta_table, self.mock_delta_table) - -# @patch("boto3.resource") -# def test_returns_cached_table(self, mock_boto3_resource): -# delta.delta_table = self.mock_delta_table - -# table = delta.get_delta_table() -# self.assertIs(table, self.mock_delta_table) -# # Should not call boto3 again -# mock_boto3_resource.assert_not_called() - -# # mock boto3.resource to raise an exception -# @patch("boto3.resource") -# def test_returns_none_on_exception(self, mock_boto3_resource): -# delta.delta_table = None -# mock_boto3_resource.side_effect = Exception("fail") -# table = delta.get_delta_table() -# self.assertIsNone(table) -# self.mock_logger_error.assert_called() - -# import delta - -# class TestGetSqsClient(unittest.TestCase): -# def setUp(self): -# # Patch logger.info and logger.error -# self.logger_info_patcher = patch("logging.Logger.info") -# self.mock_logger_info = self.logger_info_patcher.start() -# self.logger_error_patcher = patch("logging.Logger.error") -# self.mock_logger_error = self.logger_error_patcher.start() -# self.sqs_client_patcher = patch("delta.boto3.client") -# self.mock_sqs_client = self.sqs_client_patcher.start() -# # Reset the global sqs_client before each test -# delta.sqs_client = None - -# def tearDown(self): -# self.logger_info_patcher.stop() -# self.logger_error_patcher.stop() -# self.sqs_client_patcher.stop() - -# def test_returns_client_on_success(self): -# mock_client = MagicMock() -# self.mock_sqs_client.return_value = mock_client - -# client = delta.get_sqs_client() -# self.assertIs(client, mock_client) -# # Should cache the client -# self.assertIs(delta.sqs_client, mock_client) - -# def test_returns_cached_client(self): -# mock_client = MagicMock() -# delta.sqs_client = mock_client - -# client = delta.get_sqs_client() -# self.assertIs(client, mock_client) -# # Should not re-initialize -# self.mock_sqs_client.assert_not_called() - -# def test_returns_none_on_exception(self): -# self.mock_sqs_client.side_effect = Exception("fail") -# client = delta.get_sqs_client() -# self.assertIsNone(client) -# self.mock_logger_error.assert_called() - - -# import delta - -# class TestSendMessage(unittest.TestCase): -# def setUp(self): -# self.get_sqs_client_patcher = patch("delta.get_sqs_client") -# self.mock_get_sqs_client = self.get_sqs_client_patcher.start() -# self.mock_sqs_client = MagicMock() -# self.mock_get_sqs_client.return_value = self.mock_sqs_client - -# self.logger_info_patcher = patch("logging.Logger.info") -# self.mock_logger_info = self.logger_info_patcher.start() -# self.logger_error_patcher = patch("logging.Logger.error") -# self.mock_logger_error = self.logger_error_patcher.start() - -# def tearDown(self): -# self.get_sqs_client_patcher.stop() -# self.logger_info_patcher.stop() -# self.logger_error_patcher.stop() - -# def test_send_message_success(self): -# record = {"a": "bbb"} -# self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} - -# delta.send_message(record) - -# self.mock_sqs_client.send_message.assert_called_once() -# self.mock_logger_info.assert_any_call("Record saved successfully to the DLQ") -# self.mock_logger_error.assert_not_called() - -# def test_send_message_client_error(self): -# record = {"a": "bbb"} -# self.mock_sqs_client.send_message.side_effect = Exception("SQS error") - -# delta.send_message(record, "test-queue-url") - -# self.mock_logger_error.assert_called() +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 + +# Set environment variables before importing the module +## @TODO: # Note: Environment variables shared across tests, thus aligned +os.environ["AWS_SQS_QUEUE_URL"] = "https://sqs.eu-west-2.amazonaws.com/123456789012/test-queue" +os.environ["DELTA_TABLE_NAME"] = "my_delta_table" +os.environ["SOURCE"] = "my_source" + +from delta import send_message, handler, process_record # Import after setting environment variables + +SUCCESS_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 200}} +EXCEPTION_RESPONSE = ClientError({"Error": {"Code": "ConditionalCheckFailedException"}}, "PutItem") +FAIL_RESPONSE = {"ResponseMetadata": {"HTTPStatusCode": 500}} + +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") + self.mock_logger_info = self.logger_info_patcher.start() + + self.logger_exception_patcher = patch("logging.Logger.exception") + self.mock_logger_exception = self.logger_exception_patcher.start() + + self.logger_warning_patcher = patch("logging.Logger.warning") + self.mock_logger_warning = self.logger_warning_patcher.start() + + self.logger_error_patcher = patch("logging.Logger.error") + self.mock_logger_error = self.logger_error_patcher.start() + + self.firehose_logger_patcher = patch("delta.firehose_logger") + self.mock_firehose_logger = self.firehose_logger_patcher.start() + + self.sqs_client_patcher = patch("delta.sqs_client") + self.mock_sqs_client = self.sqs_client_patcher.start() + + self.delta_table_patcher=patch("delta.delta_table") + self.mock_delta_table = self.delta_table_patcher.start() + + def tearDown(self): + self.logger_exception_patcher.stop() + self.logger_warning_patcher.stop() + self.logger_error_patcher.stop() + self.logger_info_patcher.stop() + self.mock_firehose_logger.stop() + self.sqs_client_patcher.stop() + self.delta_table_patcher.stop() + + def test_send_message_success(self): + # Arrange + self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} + record = {"key": "value"} + sqs_queue_url = "test-queue-url" + + # Act + send_message(record, sqs_queue_url) + + # Assert + self.mock_sqs_client.send_message.assert_called_once_with( + QueueUrl=sqs_queue_url, MessageBody=json.dumps(record) + ) + + def test_send_message_client_error(self): + # Arrange + record = {"key": "value"} + + # Simulate ClientError + error_response = {"Error": {"Code": "500", "Message": "Internal Server Error"}} + self.mock_sqs_client.send_message.side_effect = ClientError(error_response, "SendMessage") + + # Act + send_message(record, "test-queue-url") + + # Assert + self.mock_logger_error.assert_called_once_with( + f"Error sending record to DLQ: An error occurred (500) when calling the SendMessage operation: Internal Server Error" + ) + + def test_handler_success_insert(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + suppliers = ["DPS", "EMIS"] + for supplier in suppliers: + imms_id = f"test-insert-imms-{supplier}-id" + event = ValuesForTests.get_event(event_name=EventName.CREATE, operation=Operation.CREATE, imms_id=imms_id, supplier=supplier) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.mock_delta_table.put_item.assert_called() + self.mock_firehose_logger.send_log.assert_called() # check logged + put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB + put_item_data = put_item_call_args.kwargs["Item"] + self.assertIn("Imms", put_item_data) + self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.CREATE) + self.assertEqual(put_item_data["Operation"], Operation.CREATE) + self.assertEqual(put_item_data["SupplierSystem"], supplier) + + def test_handler_failure(self): + # Arrange + self.mock_delta_table.put_item.return_value = FAIL_RESPONSE + event = ValuesForTests.get_event() + + # Act + result = handler(event, None) + + # Assert + self.assertFalse(result) + + def test_handler_success_update(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + imms_id = "test-update-imms-id" + event = ValuesForTests.get_event(event_name=EventName.UPDATE, operation=Operation.UPDATE, imms_id=imms_id) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.mock_delta_table.put_item.assert_called() + self.mock_firehose_logger.send_log.assert_called() # check logged + put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB + put_item_data = put_item_call_args.kwargs["Item"] + self.assertIn("Imms", put_item_data) + self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.UPDATE) + self.assertEqual(put_item_data["Operation"], Operation.UPDATE) + self.assertEqual(put_item_data["ImmsID"], imms_id) + + def test_handler_success_delete_physical(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + imms_id = "test-update-imms-id" + event = ValuesForTests.get_event(event_name=EventName.DELETE_PHYSICAL, operation=Operation.DELETE_PHYSICAL, imms_id=imms_id) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.mock_delta_table.put_item.assert_called() + self.mock_firehose_logger.send_log.assert_called() # check logged + put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB + put_item_data = put_item_call_args.kwargs["Item"] + self.assertIn("Imms", put_item_data) + self.assertEqual(put_item_data["Operation"], Operation.DELETE_PHYSICAL) + self.assertEqual(put_item_data["ImmsID"], imms_id) + self.assertEqual(put_item_data["Imms"], "") # check imms has been blanked out + + def test_handler_success_delete_logical(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + imms_id = "test-update-imms-id" + event = ValuesForTests.get_event(event_name=EventName.UPDATE, + operation=Operation.DELETE_LOGICAL, + imms_id=imms_id) + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.mock_delta_table.put_item.assert_called() + self.mock_firehose_logger.send_log.assert_called() # check logged + put_item_call_args = self.mock_delta_table.put_item.call_args # check data written to DynamoDB + put_item_data = put_item_call_args.kwargs["Item"] + self.assertIn("Imms", put_item_data) + self.assertEqual(put_item_data["Imms"]["ACTION_FLAG"], ActionFlag.DELETE_LOGICAL) + self.assertEqual(put_item_data["Operation"], Operation.DELETE_LOGICAL) + self.assertEqual(put_item_data["ImmsID"], imms_id) + + @patch("delta.logger.info") + def test_dps_record_skipped(self, mock_logger_info): + event = ValuesForTests.get_event(supplier="DPSFULL") + + response = handler(event, None) + + self.assertTrue(response) + + # Check logging and Firehose were called + mock_logger_info.assert_called_with("Record from DPS skipped for 12345") + + @patch("delta.Converter") + def test_partial_success_with_errors(self, mock_converter): + mock_converter_instance = MagicMock() + mock_converter_instance.run_conversion.return_value = {"ABC":"DEF"} + mock_converter_instance.get_error_records.return_value = [{"error": "Invalid field"}] + mock_converter.return_value = mock_converter_instance + + # Mock DynamoDB put_item success + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + + event = ValuesForTests.get_event() + + response = handler(event, None) + + self.assertTrue(response) + # Check logging and Firehose were called + self.mock_logger_info.assert_called() + self.assertEqual(self.mock_firehose_logger.send_log.call_count, 1) + self.mock_firehose_logger.send_log.assert_called_once() + + # Get the actual argument passed to send_log + args, kwargs = self.mock_firehose_logger.send_log.call_args + sent_payload = args[0] # First positional arg + + # Navigate to the specific message + status_desc = sent_payload["event"]["operation_outcome"]["statusDesc"] + + # Assert the expected message is present + self.assertIn( + "Partial success: successfully synced into delta, but issues found within record", + status_desc + ) + + def test_send_message_multi_records_diverse(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + records_config = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), + RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "id3", ActionFlag.DELETE_LOGICAL), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) + + def test_send_message_skipped_records_diverse(self): + '''Check skipped records sent to firehose but not to DynamoDB''' + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + records_config = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "id1", ActionFlag.CREATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "id2", ActionFlag.UPDATE), + RecordConfig(EventName.CREATE, Operation.CREATE, "id-skip", ActionFlag.CREATE, "DPSFULL"), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "id4"), + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, 3) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) + + def test_send_message_multi_create(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + records_config = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "create-id1", ActionFlag.CREATE), + RecordConfig(EventName.CREATE, Operation.CREATE, "create-id2", ActionFlag.CREATE), + RecordConfig(EventName.CREATE, Operation.CREATE, "create-id3", ActionFlag.CREATE) + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, 3) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + + + def test_send_message_multi_update(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + records_config = [ + RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id1", ActionFlag.UPDATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id2", ActionFlag.UPDATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "update-id3", ActionFlag.UPDATE) + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, 3) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + + def test_send_message_multi_logical_delete(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + + records_config = [ + RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id1", ActionFlag.DELETE_LOGICAL), + RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id2", ActionFlag.DELETE_LOGICAL), + RecordConfig(EventName.DELETE_LOGICAL, Operation.DELETE_LOGICAL, "delete-id3", ActionFlag.DELETE_LOGICAL) + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, 3) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + + def test_send_message_multi_physical_delete(self): + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + records_config = [ + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id1"), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id2"), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "remove-id3") + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertTrue(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, 3) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + + def test_single_error_in_multi(self): + # Arrange + self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] + + records_config = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id1", ActionFlag.CREATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id1.2", ActionFlag.UPDATE), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id1.3"), + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertFalse(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, 3) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, 3) + self.assertEqual(self.mock_logger_warning.call_count, 1) + + def test_single_exception_in_multi(self): + # Arrange + # 2nd record fails + self.mock_delta_table.put_item.side_effect = [SUCCESS_RESPONSE, EXCEPTION_RESPONSE, SUCCESS_RESPONSE] + + records_config = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id2.1", ActionFlag.CREATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "exception-id2.2", ActionFlag.UPDATE), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id2.3"), + ] + event = ValuesForTests.get_multi_record_event(records_config) + + # Act + result = handler(event, None) + + # Assert + self.assertFalse(result) + self.assertEqual(self.mock_delta_table.put_item.call_count, len(records_config)) + self.assertEqual(self.mock_firehose_logger.send_log.call_count, len(records_config)) + + @patch("delta.process_record") + @patch("delta.send_firehose") + def test_handler_calls_process_record_for_each_event(self, mock_send_firehose, mock_process_record): + # Arrange + event = { + "Records": [ + { "a": "record1" }, + { "a": "record2" }, + { "a": "record3" } + ] + } + # Mock process_record to always return True + mock_process_record.return_value = True, {} + mock_send_firehose.return_value = None + + # Act + result = handler(event, {}) + + # Assert + self.assertTrue(result) + self.assertEqual(mock_process_record.call_count, len(event["Records"])) + + # TODO depedency injection needed here + @patch("delta.process_record") + @patch("delta.send_firehose") + def test_handler_sends_all_to_firehose(self, mock_send_firehose, mock_process_record): + # Arrange + + # event with 3 records + event = { + "Records": [ + { "a": "record1" }, + { "a": "record2" }, + { "a": "record3" } + ] + } + return_ok = (True, {}) + return_fail = (False, {}) + mock_send_firehose.return_value = None + mock_process_record.side_effect = [return_ok, return_fail, return_ok] + + # Act + result = handler(event, {}) + + # Assert + self.assertFalse(result) + self.assertEqual(mock_process_record.call_count, len(event["Records"])) + # check that all records were sent to firehose + self.assertEqual(mock_send_firehose.call_count, len(event["Records"])) + +class DeltaRecordProcessorTestCase(unittest.TestCase): + + def setUp(self): + self.logger_info_patcher = patch("logging.Logger.info") + self.mock_logger_info = self.logger_info_patcher.start() + + self.logger_exception_patcher = patch("logging.Logger.exception") + self.mock_logger_exception = self.logger_exception_patcher.start() + + self.logger_warning_patcher = patch("logging.Logger.warning") + self.mock_logger_warning = self.logger_warning_patcher.start() + + self.delta_table_patcher=patch("delta.delta_table") + self.mock_delta_table = self.delta_table_patcher.start() + + def tearDown(self): + self.logger_exception_patcher.stop() + self.logger_warning_patcher.stop() + self.logger_info_patcher.stop() + self.delta_table_patcher.stop() + + def test_multi_record_success(self): + + # Arrange + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + test_configs = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "ok-id.2", ActionFlag.UPDATE), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), + ] + test_index = 0 + for config in test_configs: + test_index += 1 + record = ValuesForTests.get_event_record( + imms_id=config.imms_id, + event_name=config.event_name, + operation=config.operation, + supplier=config.supplier, + ) + # Act + result, log_data = process_record(record, {}) + + # Assert + self.assertEqual(result, True) + operation_outcome = log_data["operation_outcome"] + self.assertEqual(operation_outcome["record"], config.imms_id) + self.assertEqual(operation_outcome["operation_type"], config.operation) + self.assertEqual(operation_outcome["statusCode"], "200") + self.assertEqual(operation_outcome["statusDesc"], "Successfully synched into delta") + self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) + + self.assertEqual(self.mock_logger_exception.call_count, 0) + 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 = [SUCCESS_RESPONSE, FAIL_RESPONSE, SUCCESS_RESPONSE] + test_configs = [ + RecordConfig(EventName.CREATE, Operation.CREATE, "ok-id.1", ActionFlag.CREATE), + RecordConfig(EventName.UPDATE, Operation.UPDATE, "fail-id.2", ActionFlag.UPDATE), + RecordConfig(EventName.DELETE_PHYSICAL, Operation.DELETE_PHYSICAL, "ok-id.3"), + ] + test_index = 0 + for config in test_configs: + test_index += 1 + record = ValuesForTests.get_event_record( + imms_id=config.imms_id, + event_name=config.event_name, + operation=config.operation, + supplier=config.supplier, + ) + log_data = {} + # Act + result, log_data = process_record(record, log_data) + + # Assert + self.assertEqual(result, expected_returns[test_index-1]) + self.assertEqual(self.mock_delta_table.put_item.call_count, test_index) + + self.assertEqual(self.mock_logger_exception.call_count, 0) + self.assertEqual(self.mock_logger_warning.call_count, 1) + + + def test_single_record_table_exception(self): + + # Arrange + imms_id = "exception-id" + record = ValuesForTests.get_event_record( + imms_id, + event_name=EventName.UPDATE, + operation=Operation.UPDATE, + supplier="EMIS", + ) + self.mock_delta_table.put_item.return_value = EXCEPTION_RESPONSE + # Act + result, log_data = process_record(record, {}) + + # Assert + self.assertEqual(result, False) + operation_outcome = log_data["operation_outcome"] + self.assertEqual(operation_outcome["record"], imms_id) + self.assertEqual(operation_outcome["operation_type"], Operation.UPDATE) + self.assertEqual(operation_outcome["statusCode"], "500") + self.assertEqual(operation_outcome["statusDesc"], "Exception") + self.assertEqual(self.mock_delta_table.put_item.call_count, 1) + self.assertEqual(self.mock_logger_exception.call_count, 1) + + @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 + ) + + self.mock_delta_table.put_item.return_value = SUCCESS_RESPONSE + # Act + process_record(record, {}) + + # Assert + mock_json_loads.assert_any_call(ValuesForTests.json_value_for_test, parse_float=decimal.Decimal) + + +import delta + +class TestGetDeltaTable(unittest.TestCase): + def setUp(self): + self.delta_table_patcher=patch("delta.delta_table") + self.mock_delta_table = self.delta_table_patcher.start() + self.logger_info_patcher = patch("logging.Logger.info") + self.mock_logger_info = self.logger_info_patcher.start() + self.logger_error_patcher = patch("logging.Logger.error") + self.mock_logger_error = self.logger_error_patcher.start() + + def tearDown(self): + self.delta_table_patcher.stop() + self.logger_info_patcher.stop() + 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 + self.assertIs(delta.delta_table, self.mock_delta_table) + + @patch("boto3.resource") + def test_returns_cached_table(self, mock_boto3_resource): + delta.delta_table = self.mock_delta_table + + table = delta.get_delta_table() + self.assertIs(table, self.mock_delta_table) + # Should not call boto3 again + mock_boto3_resource.assert_not_called() + + # mock boto3.resource to raise an exception + @patch("boto3.resource") + def test_returns_none_on_exception(self, mock_boto3_resource): + delta.delta_table = None + mock_boto3_resource.side_effect = Exception("fail") + table = delta.get_delta_table() + self.assertIsNone(table) + self.mock_logger_error.assert_called() + +import delta + +class TestGetSqsClient(unittest.TestCase): + def setUp(self): + # Patch logger.info and logger.error + self.logger_info_patcher = patch("logging.Logger.info") + self.mock_logger_info = self.logger_info_patcher.start() + self.logger_error_patcher = patch("logging.Logger.error") + self.mock_logger_error = self.logger_error_patcher.start() + self.sqs_client_patcher = patch("delta.boto3.client") + self.mock_sqs_client = self.sqs_client_patcher.start() + # Reset the global sqs_client before each test + delta.sqs_client = None + + def tearDown(self): + self.logger_info_patcher.stop() + self.logger_error_patcher.stop() + self.sqs_client_patcher.stop() + + def test_returns_client_on_success(self): + mock_client = MagicMock() + self.mock_sqs_client.return_value = mock_client + + client = delta.get_sqs_client() + self.assertIs(client, mock_client) + # Should cache the client + self.assertIs(delta.sqs_client, mock_client) + + def test_returns_cached_client(self): + mock_client = MagicMock() + delta.sqs_client = mock_client + + client = delta.get_sqs_client() + self.assertIs(client, mock_client) + # Should not re-initialize + self.mock_sqs_client.assert_not_called() + + def test_returns_none_on_exception(self): + self.mock_sqs_client.side_effect = Exception("fail") + client = delta.get_sqs_client() + self.assertIsNone(client) + self.mock_logger_error.assert_called() + + +import delta + +class TestSendMessage(unittest.TestCase): + def setUp(self): + self.get_sqs_client_patcher = patch("delta.get_sqs_client") + self.mock_get_sqs_client = self.get_sqs_client_patcher.start() + self.mock_sqs_client = MagicMock() + self.mock_get_sqs_client.return_value = self.mock_sqs_client + + self.logger_info_patcher = patch("logging.Logger.info") + self.mock_logger_info = self.logger_info_patcher.start() + self.logger_error_patcher = patch("logging.Logger.error") + self.mock_logger_error = self.logger_error_patcher.start() + + def tearDown(self): + self.get_sqs_client_patcher.stop() + self.logger_info_patcher.stop() + self.logger_error_patcher.stop() + + def test_send_message_success(self): + record = {"a": "bbb"} + self.mock_sqs_client.send_message.return_value = {"MessageId": "123"} + + delta.send_message(record) + + self.mock_sqs_client.send_message.assert_called_once() + self.mock_logger_info.assert_any_call("Record saved successfully to the DLQ") + self.mock_logger_error.assert_not_called() + + def test_send_message_client_error(self): + record = {"a": "bbb"} + self.mock_sqs_client.send_message.side_effect = Exception("SQS error") + + delta.send_message(record, "test-queue-url") + + self.mock_logger_error.assert_called() diff --git a/delta_backend/tests/test_log_firehose.py b/delta_backend/tests/test_log_firehose.py index c3351d7b04..9ac716e073 100644 --- a/delta_backend/tests/test_log_firehose.py +++ b/delta_backend/tests/test_log_firehose.py @@ -1,71 +1,71 @@ -# import unittest -# from unittest.mock import patch, MagicMock -# import json -# from log_firehose import FirehoseLogger +import unittest +from unittest.mock import patch, MagicMock +import json +from log_firehose import FirehoseLogger -# class TestFirehoseLogger(unittest.TestCase): +class TestFirehoseLogger(unittest.TestCase): -# def setUp(self): -# # Common setup if needed -# self.context = {} -# self.logger_info_patcher = patch("logging.Logger.info") -# self.mock_logger_info = self.logger_info_patcher.start() + def setUp(self): + # Common setup if needed + self.context = {} + self.logger_info_patcher = patch("logging.Logger.info") + self.mock_logger_info = self.logger_info_patcher.start() -# def tearDown(self): -# self.logger_info_patcher.stop() + def tearDown(self): + self.logger_info_patcher.stop() -# @patch("boto3.client") -# def test_send_log(self, mock_boto_client): -# """it should send log message to Firehose""" + @patch("boto3.client") + def test_send_log(self, mock_boto_client): + """it should send log message to Firehose""" -# # Arrange -# mock_response = { -# "RecordId": "shardId-000000000000000000000001", -# "ResponseMetadata": { -# "RequestId": "12345abcde67890fghijk", -# "HTTPStatusCode": 200, -# "RetryAttempts": 0 -# } -# } -# mock_firehose_client = MagicMock() -# mock_boto_client.return_value = mock_firehose_client -# mock_firehose_client.put_record.return_value = mock_response + # Arrange + mock_response = { + "RecordId": "shardId-000000000000000000000001", + "ResponseMetadata": { + "RequestId": "12345abcde67890fghijk", + "HTTPStatusCode": 200, + "RetryAttempts": 0 + } + } + mock_firehose_client = MagicMock() + mock_boto_client.return_value = mock_firehose_client + mock_firehose_client.put_record.return_value = mock_response -# stream_name = "stream_name" -# firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) -# log_message = {"text": "Test log message"} + stream_name = "stream_name" + firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) + log_message = {"text": "Test log message"} -# # Act -# firehose_logger.send_log(log_message) + # Act + firehose_logger.send_log(log_message) -# # Assert -# mock_firehose_client.put_record.assert_called_once() -# self.assertEqual(mock_firehose_client.put_record.return_value, mock_response) + # Assert + mock_firehose_client.put_record.assert_called_once() + self.assertEqual(mock_firehose_client.put_record.return_value, mock_response) -# @patch("boto3.client") -# def test_send_log_failure(self, mock_boto_client): -# """Test that send_log logs an exception when put_record fails.""" + @patch("boto3.client") + def test_send_log_failure(self, mock_boto_client): + """Test that send_log logs an exception when put_record fails.""" -# # Arrange -# mock_firehose_client = MagicMock() -# mock_boto_client.return_value = mock_firehose_client -# mock_firehose_client.put_record.side_effect = Exception("Test exception") + # Arrange + mock_firehose_client = MagicMock() + mock_boto_client.return_value = mock_firehose_client + mock_firehose_client.put_record.side_effect = Exception("Test exception") -# stream_name = "test-stream" -# firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) -# log_message = {"key": "value"} + stream_name = "test-stream" + firehose_logger = FirehoseLogger(boto_client=mock_firehose_client, stream_name=stream_name) + log_message = {"key": "value"} -# with patch("log_firehose.logger.exception") as mock_logger_exception: -# # Act -# firehose_logger.send_log(log_message) + with patch("log_firehose.logger.exception") as mock_logger_exception: + # Act + firehose_logger.send_log(log_message) -# # Assert -# mock_firehose_client.put_record.assert_called_once_with( -# DeliveryStreamName="test-stream", -# Record={"Data": json.dumps(log_message).encode("utf-8")}, -# ) -# mock_logger_exception.assert_called_once_with("Error sending log to Firehose: Test exception") + # Assert + mock_firehose_client.put_record.assert_called_once_with( + DeliveryStreamName="test-stream", + Record={"Data": json.dumps(log_message).encode("utf-8")}, + ) + mock_logger_exception.assert_called_once_with("Error sending log to Firehose: Test exception") -# if __name__ == "__main__": -# unittest.main() \ No newline at end of file +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/delta_backend/tests/test_utils.py b/delta_backend/tests/test_utils.py index 0bb1249a02..134317d2b9 100644 --- a/delta_backend/tests/test_utils.py +++ b/delta_backend/tests/test_utils.py @@ -1,12 +1,12 @@ -# import unittest -# from utils import is_valid_simple_snomed +import unittest +from utils import is_valid_simple_snomed -# class TestIsValidSimpleSnomed(unittest.TestCase): +class TestIsValidSimpleSnomed(unittest.TestCase): -# def test_valid_snomed(self): -# valid_snomed = "956951000000104" -# self.assertTrue(is_valid_simple_snomed(valid_snomed)) + def test_valid_snomed(self): + valid_snomed = "956951000000104" + self.assertTrue(is_valid_simple_snomed(valid_snomed)) -# def test_invalid_snomed(self): -# invalid_snomed = "956951000000105" -# self.assertFalse(is_valid_simple_snomed(invalid_snomed)) + def test_invalid_snomed(self): + invalid_snomed = "956951000000105" + self.assertFalse(is_valid_simple_snomed(invalid_snomed))