From f081f38e5bacee3796f07536450d2dc414dac4db Mon Sep 17 00:00:00 2001 From: Edd Almond <102675624+eddalmond1@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:35:14 +0000 Subject: [PATCH 1/4] eli-366 addressing ruff failures with updated version of ruff --- poetry.lock | 41 ++++++++++--------- pyproject.toml | 2 +- .../calculators/eligibility_calculator.py | 2 +- tests/integration/conftest.py | 2 +- .../test_eligibility_calculator.py | 2 +- .../services/processors/test_token_parser.py | 4 +- .../processors/test_token_processor.py | 2 +- 7 files changed, 28 insertions(+), 27 deletions(-) diff --git a/poetry.lock b/poetry.lock index bf875e8fa..3d933c687 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3121,30 +3121,31 @@ pyasn1 = ">=0.1.3" [[package]] name = "ruff" -version = "0.11.13" +version = "0.14.10" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46"}, - {file = "ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48"}, - {file = "ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71"}, - {file = "ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432"}, - {file = "ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492"}, - {file = "ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250"}, - {file = "ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3"}, - {file = "ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b"}, - {file = "ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514"}, + {file = "ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49"}, + {file = "ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f"}, + {file = "ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f"}, + {file = "ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f"}, + {file = "ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d"}, + {file = "ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405"}, + {file = "ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60"}, + {file = "ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830"}, + {file = "ruff-0.14.10-py3-none-win32.whl", hash = "sha256:104c49fc7ab73f3f3a758039adea978869a918f31b73280db175b43a2d9b51d6"}, + {file = "ruff-0.14.10-py3-none-win_amd64.whl", hash = "sha256:466297bd73638c6bdf06485683e812db1c00c7ac96d4ddd0294a338c62fdc154"}, + {file = "ruff-0.14.10-py3-none-win_arm64.whl", hash = "sha256:e51d046cf6dda98a4633b8a8a771451107413b0f07183b2bef03f075599e44e6"}, + {file = "ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4"}, ] [[package]] @@ -3674,4 +3675,4 @@ propcache = ">=0.2.1" [metadata] lock-version = "2.1" python-versions = "^3.13" -content-hash = "a227d46eea2dfc2deb9d365385b489929b86bcea6cc45fefd9500f2afb8599d9" +content-hash = "2c27814e1620b83cd0f59640693a5919bdec7160590e76879db011bf11c4ea5e" diff --git a/pyproject.toml b/pyproject.toml index 5613c25ed..5c60d3cd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ botocore = "^1.40.57" aws-xray-sdk = "2.15.0" [tool.poetry.group.dev.dependencies] -ruff = "^0.11.13" +ruff = "^0.14.10" docopt = "^0.6.2" jsonpath-rw = "^1.4.0" semver = "^3.0.4" diff --git a/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py b/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py index cd91c096d..b7314bdcc 100644 --- a/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py +++ b/src/eligibility_signposting_api/services/calculators/eligibility_calculator.py @@ -129,7 +129,7 @@ def get_best_iteration_result(self, campaign_group: list[CampaignConfig]) -> Bes if not iteration_results: return None - (best_iteration_name, best_iteration_result) = max( + (_best_iteration_name, best_iteration_result) = max( iteration_results.items(), key=lambda item: next(iter(item[1].cohort_results.values())).status.value # Below handles the case where there are no cohort results diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index eb76ff2ba..236acc85b 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -228,7 +228,7 @@ def iam_role(iam_client: BaseClient) -> Generator[str]: @pytest.fixture(scope="session") def lambda_zip() -> Path: - build_result = subprocess.run(["make", "build"], capture_output=True, text=True, check=False) # Noqa: S603, S607 + build_result = subprocess.run(["make", "build"], capture_output=True, text=True, check=False) # noqa: S603, S607 assert build_result.returncode == 0, f"'make build' failed: {build_result.stderr}" return Path("dist/lambda.zip") diff --git a/tests/unit/services/calculators/test_eligibility_calculator.py b/tests/unit/services/calculators/test_eligibility_calculator.py index c235aa480..31c30f782 100644 --- a/tests/unit/services/calculators/test_eligibility_calculator.py +++ b/tests/unit/services/calculators/test_eligibility_calculator.py @@ -1436,7 +1436,7 @@ def test_eligibility_status_with_invalid_tokens_raises_attribute_error(faker: Fa calculator = EligibilityCalculator(person_rows, campaign_configs) - with pytest.raises(ValueError, match="Invalid token."): + with pytest.raises(ValueError, match=r"Invalid token\."): calculator.get_eligibility_status("Y", ["ALL"], "ALL") diff --git a/tests/unit/services/processors/test_token_parser.py b/tests/unit/services/processors/test_token_parser.py index d81465b3f..f9814c2da 100644 --- a/tests/unit/services/processors/test_token_parser.py +++ b/tests/unit/services/processors/test_token_parser.py @@ -38,7 +38,7 @@ def test_parse_valid_tokens(self, token, expected_level, expected_name, expected ], ) def test_parse_invalid_tokens_raises_error(self, token): - with pytest.raises(ValueError, match="Invalid token."): + with pytest.raises(ValueError, match=r"Invalid token\."): TokenParser.parse(token) @pytest.mark.parametrize( @@ -53,5 +53,5 @@ def test_parse_invalid_tokens_raises_error(self, token): ], ) def test_parse_invalid_token_format_raises_error(self, token): - with pytest.raises(ValueError, match="Invalid token format."): + with pytest.raises(ValueError, match=r"Invalid token format\."): TokenParser.parse(token) diff --git a/tests/unit/services/processors/test_token_processor.py b/tests/unit/services/processors/test_token_processor.py index 1a6785bbc..7e1f348e2 100644 --- a/tests/unit/services/processors/test_token_processor.py +++ b/tests/unit/services/processors/test_token_processor.py @@ -351,7 +351,7 @@ def test_valid_token_invalid_format_should_raise_error(self, token_format: str): actions=[], ) - with pytest.raises(ValueError, match="Invalid token format."): + with pytest.raises(ValueError, match=r"Invalid token format\."): TokenProcessor.find_and_replace_tokens(person, condition) @pytest.mark.parametrize( From 16b68489ea89e266244d18eddcec196beacd34ca Mon Sep 17 00:00:00 2001 From: Edd Almond <102675624+eddalmond1@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:40:43 +0000 Subject: [PATCH 2/4] eli-366 fixing unit test --- tests/unit/services/calculators/test_eligibility_calculator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/services/calculators/test_eligibility_calculator.py b/tests/unit/services/calculators/test_eligibility_calculator.py index 31c30f782..90004f577 100644 --- a/tests/unit/services/calculators/test_eligibility_calculator.py +++ b/tests/unit/services/calculators/test_eligibility_calculator.py @@ -1436,7 +1436,7 @@ def test_eligibility_status_with_invalid_tokens_raises_attribute_error(faker: Fa calculator = EligibilityCalculator(person_rows, campaign_configs) - with pytest.raises(ValueError, match=r"Invalid token\."): + with pytest.raises(ValueError, match=r"Invalid token format\."): calculator.get_eligibility_status("Y", ["ALL"], "ALL") From 9057879dba63d23cfc8092d6a5d581894e0e703b Mon Sep 17 00:00:00 2001 From: Edd Almond <102675624+eddalmond1@users.noreply.github.com> Date: Tue, 30 Dec 2025 12:54:22 +0000 Subject: [PATCH 3/4] eli-366 further linting and fixing pre-commit --- scripts/config/pre-commit.yaml | 2 +- tests/integration/conftest.py | 2 +- tests/unit/logging/test_logs_helper.py | 4 ++-- tests/unit/middleware/test_security_headers.py | 4 +--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml index 7e99a6f7b..25a226877 100644 --- a/scripts/config/pre-commit.yaml +++ b/scripts/config/pre-commit.yaml @@ -51,7 +51,7 @@ repos: language: script pass_filenames: false - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.7 + rev: v0.14.10 hooks: - id: ruff args: [--fix] diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 236acc85b..4af1223a2 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -228,7 +228,7 @@ def iam_role(iam_client: BaseClient) -> Generator[str]: @pytest.fixture(scope="session") def lambda_zip() -> Path: - build_result = subprocess.run(["make", "build"], capture_output=True, text=True, check=False) # noqa: S603, S607 + build_result = subprocess.run(["make", "build"], capture_output=True, text=True, check=False) # noqa: S607 assert build_result.returncode == 0, f"'make build' failed: {build_result.stderr}" return Path("dist/lambda.zip") diff --git a/tests/unit/logging/test_logs_helper.py b/tests/unit/logging/test_logs_helper.py index d11885bc9..c29ffcba4 100644 --- a/tests/unit/logging/test_logs_helper.py +++ b/tests/unit/logging/test_logs_helper.py @@ -5,6 +5,8 @@ import pytest from mangum.types import LambdaContext +from eligibility_signposting_api.app import log_request_ids_from_headers + @pytest.fixture def lambda_context(): @@ -46,8 +48,6 @@ def lambda_context(): ], ) def test_log_request_ids_decorator_logs_metadata(headers, gateway_request_id, expected_extra, lambda_context, caplog): - from eligibility_signposting_api.app import log_request_ids_from_headers - event = {"headers": headers} if gateway_request_id is not None: event["requestContext"] = {"requestId": gateway_request_id} diff --git a/tests/unit/middleware/test_security_headers.py b/tests/unit/middleware/test_security_headers.py index b475bbbb7..8b3c8b2ab 100644 --- a/tests/unit/middleware/test_security_headers.py +++ b/tests/unit/middleware/test_security_headers.py @@ -3,7 +3,7 @@ from http import HTTPStatus import pytest -from flask import Flask +from flask import Flask, make_response from flask.testing import FlaskClient from hamcrest import assert_that, contains_string, equal_to, has_entries, is_ @@ -152,8 +152,6 @@ def test_existing_headers_are_not_overridden(self) -> None: @app.route("/test") def test_route(): - from flask import make_response - resp = make_response({"status": "ok"}, HTTPStatus.OK) resp.headers["Cache-Control"] = "public, max-age=3600" return resp From 74b9325becf81f1763ac3f83dcb0c40163ff5142 Mon Sep 17 00:00:00 2001 From: Edd Almond <102675624+eddalmond1@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:11:20 +0000 Subject: [PATCH 4/4] eli-366 more linting --- src/eligibility_signposting_api/model/campaign_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eligibility_signposting_api/model/campaign_config.py b/src/eligibility_signposting_api/model/campaign_config.py index 8c6e8c7c6..fd4d06b7e 100644 --- a/src/eligibility_signposting_api/model/campaign_config.py +++ b/src/eligibility_signposting_api/model/campaign_config.py @@ -158,7 +158,7 @@ class IterationRule(BaseModel): model_config = {"populate_by_name": True, "extra": "ignore"} @field_validator("rule_stop", mode="before") - def parse_yn_to_bool(cls, v: str | bool) -> bool: # noqa: N805 + def parse_yn_to_bool(cls, v: str | bool) -> bool: # noqa: N805, FBT001 if isinstance(v, str): return v.upper() == "Y" return v