From 340b5d2c3118b35d4c3027dac0a84e0963553aee Mon Sep 17 00:00:00 2001 From: Lucas Alvares Gomes Date: Fri, 6 Jun 2025 14:25:45 +0100 Subject: [PATCH] Simplify running checks locally This patch refactors some of the GH workflow checks that we are running in the gate to make it eaier to run locally. That way we can verify the code prior to pushing it as a PR. $ pdm verify Signed-off-by: Lucas Alvares Gomes --- .github/workflows/black.yaml | 2 +- .github/workflows/mypy.yaml | 12 ++-- .github/workflows/pydocstyle.yaml | 12 ++-- .github/workflows/pylint.yaml | 2 +- .github/workflows/pyright.yaml | 2 +- .github/workflows/ruff.yaml | 15 ++++- Makefile | 24 +++++++- pdm.lock | 95 ++++++++++++++++++++++++++++++- pyproject.toml | 5 ++ src/app/endpoints/query.py | 4 +- 10 files changed, 154 insertions(+), 19 deletions(-) diff --git a/.github/workflows/black.yaml b/.github/workflows/black.yaml index 8d823a98..054d0b4a 100644 --- a/.github/workflows/black.yaml +++ b/.github/workflows/black.yaml @@ -24,4 +24,4 @@ jobs: - name: Black version run: pdm run black --version - name: Black check - run: pdm run black . --check + run: make black diff --git a/.github/workflows/mypy.yaml b/.github/workflows/mypy.yaml index 13bb3db2..721bf1dc 100644 --- a/.github/workflows/mypy.yaml +++ b/.github/workflows/mypy.yaml @@ -17,7 +17,11 @@ jobs: python-version: '3.11' - name: Python version run: python --version - - name: Mypy installation - run: pip install --user mypy pydantic types-PyYAML - - name: Type checks - run: mypy --explicit-package-bases --disallow-untyped-calls --disallow-untyped-defs --disallow-incomplete-defs --ignore-missing-imports --disable-error-code attr-defined src/ + - name: PDM installation + run: pip install --user pdm + - name: Install dependencies + run: pdm install + - name: Install devel dependencies + run: pdm install --group default,dev + - name: Python linter + run: make check-types diff --git a/.github/workflows/pydocstyle.yaml b/.github/workflows/pydocstyle.yaml index 101fce9e..1b7fb472 100644 --- a/.github/workflows/pydocstyle.yaml +++ b/.github/workflows/pydocstyle.yaml @@ -17,7 +17,11 @@ jobs: python-version: '3.11' - name: Python version run: python --version - - name: Pydocstyle install - run: pip install --user pydocstyle - - name: Python docstring checks - run: pydocstyle -v . + - name: PDM installation + run: pip install --user pdm + - name: Install dependencies + run: pdm install + - name: Install devel dependencies + run: pdm install --group default,dev + - name: Python linter + run: make docstyle diff --git a/.github/workflows/pylint.yaml b/.github/workflows/pylint.yaml index 5ce45511..24d7b7d5 100644 --- a/.github/workflows/pylint.yaml +++ b/.github/workflows/pylint.yaml @@ -25,4 +25,4 @@ jobs: - name: Install devel dependencies run: pdm install --group default,dev - name: Python linter - run: pdm run pylint src + run: make pylint diff --git a/.github/workflows/pyright.yaml b/.github/workflows/pyright.yaml index 80c9ef2e..374ac170 100644 --- a/.github/workflows/pyright.yaml +++ b/.github/workflows/pyright.yaml @@ -25,4 +25,4 @@ jobs: - name: Install devel dependencies run: pdm install --group default,dev - name: Run Pyright tests - run: pdm run pyright src + run: make pyright diff --git a/.github/workflows/ruff.yaml b/.github/workflows/ruff.yaml index 735bfbe3..044b8214 100644 --- a/.github/workflows/ruff.yaml +++ b/.github/workflows/ruff.yaml @@ -12,7 +12,16 @@ jobs: pull-requests: read steps: - uses: actions/checkout@v4 - - uses: chartboost/ruff-action@v1 + - uses: actions/setup-python@v5 with: - args: 'check . --per-file-ignores=tests/*:S101 --per-file-ignores=scripts/*:S101' - + python-version: '3.11' + - name: Python version + run: python --version + - name: PDM installation + run: pip install --user pdm + - name: Install dependencies + run: pdm install + - name: Install devel dependencies + run: pdm install --group default,dev + - name: Python linter + run: make ruff diff --git a/Makefile b/Makefile index 84a7ebef..b2c3ce60 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ test-integration: ## Run integration tests tests COVERAGE_FILE="${ARTIFACT_DIR}/.coverage.integration" pdm run pytest tests/integration --cov=src --cov-report term-missing --cov-report "json:${ARTIFACT_DIR}/coverage_integration.json" --junit-xml="${ARTIFACT_DIR}/junit_integration.xml" --cov-fail-under=10 check-types: ## Checks type hints in sources - MYPYPATH=src pdm run mypy --namespace-packages --explicit-package-bases --strict --disallow-untyped-calls --disallow-untyped-defs --disallow-incomplete-defs src + pdm run mypy --explicit-package-bases --disallow-untyped-calls --disallow-untyped-defs --disallow-incomplete-defs --ignore-missing-imports --disable-error-code attr-defined src/ security-check: ## Check the project for security issues bandit -c pyproject.toml -r src tests @@ -43,3 +43,25 @@ shellcheck: ## Run shellcheck shellcheck --version shellcheck -- */*.sh +black: + pdm run black --check . + +pylint: + pdm run pylint src + +pyright: + pdm run pyright src + +docstyle: + pdm run pydocstyle -v . + +ruff: + pdm run ruff check . --per-file-ignores=tests/*:S101 --per-file-ignores=scripts/*:S101 + +verify: + $(MAKE) black + $(MAKE) pylint + $(MAKE) pyright + $(MAKE) ruff + $(MAKE) docstyle + $(MAKE) check-types diff --git a/pdm.lock b/pdm.lock index 57688a86..2b70c747 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:39ffd9411792359ce4c793606a92a8f2bcab6fe0781c4a843b789fca3b9de29c" +content_hash = "sha256:3dc065684ceb02081a1bd8843f12bd4a889883f71b3fac485eabaf0d3c890b6b" [[metadata.targets]] requires_python = ">=3.11.1,<=3.12.10" @@ -799,6 +799,35 @@ files = [ {file = "multidict-6.4.4.tar.gz", hash = "sha256:69ee9e6ba214b5245031b76233dd95408a0fd57fdb019ddcc1ead4790932a8e8"}, ] +[[package]] +name = "mypy" +version = "1.16.0" +requires_python = ">=3.9" +summary = "Optional static typing for Python" +groups = ["dev"] +dependencies = [ + "mypy-extensions>=1.0.0", + "pathspec>=0.9.0", + "tomli>=1.1.0; python_version < \"3.11\"", + "typing-extensions>=4.6.0", +] +files = [ + {file = "mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab"}, + {file = "mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2"}, + {file = "mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff"}, + {file = "mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666"}, + {file = "mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c"}, + {file = "mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b"}, + {file = "mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13"}, + {file = "mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090"}, + {file = "mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1"}, + {file = "mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8"}, + {file = "mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730"}, + {file = "mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec"}, + {file = "mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031"}, + {file = "mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab"}, +] + [[package]] name = "mypy-extensions" version = "1.1.0" @@ -1137,6 +1166,21 @@ files = [ {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, ] +[[package]] +name = "pydocstyle" +version = "6.3.0" +requires_python = ">=3.6" +summary = "Python docstring style checker" +groups = ["dev"] +dependencies = [ + "importlib-metadata<5.0.0,>=2.0.0; python_version < \"3.8\"", + "snowballstemmer>=2.2.0", +] +files = [ + {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, + {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, +] + [[package]] name = "pygments" version = "2.19.1" @@ -1481,6 +1525,33 @@ files = [ {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, ] +[[package]] +name = "ruff" +version = "0.11.13" +requires_python = ">=3.7" +summary = "An extremely fast Python linter and code formatter, written in Rust." +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"}, +] + [[package]] name = "setuptools" version = "80.8.0" @@ -1514,6 +1585,17 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "snowballstemmer" +version = "3.0.1" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*" +summary = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." +groups = ["dev"] +files = [ + {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, + {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, +] + [[package]] name = "starlette" version = "0.46.2" @@ -1591,6 +1673,17 @@ files = [ {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, ] +[[package]] +name = "types-pyyaml" +version = "6.0.12.20250516" +requires_python = ">=3.9" +summary = "Typing stubs for PyYAML" +groups = ["dev"] +files = [ + {file = "types_pyyaml-6.0.12.20250516-py3-none-any.whl", hash = "sha256:8478208feaeb53a34cb5d970c56a7cd76b72659442e733e268a94dc72b2d0530"}, + {file = "types_pyyaml-6.0.12.20250516.tar.gz", hash = "sha256:9f21a70216fc0fa1b216a8176db5f9e0af6eb35d2f2932acb87689d03a5bf6ba"}, +] + [[package]] name = "typing-extensions" version = "4.13.2" diff --git a/pyproject.toml b/pyproject.toml index 5cfe1757..6d07377d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,10 @@ dev = [ "pytest-asyncio>=1.0.0", "pyright>=1.1.401", "pylint>=3.3.7", + "pydocstyle>=6.3.0", + "mypy>=1.16.0", + "types-PyYAML>=6.0.2", + "ruff>=0.11.13", ] [tool.pytest.ini_options] @@ -47,4 +51,5 @@ distribution = true start = "pdm run make run" test-unit = "pdm run make test-unit" test-integration = "pdm run make test-integration" +verify = "pdm run make verify" diff --git a/src/app/endpoints/query.py b/src/app/endpoints/query.py index 8f7ccd1a..bb713415 100644 --- a/src/app/endpoints/query.py +++ b/src/app/endpoints/query.py @@ -127,9 +127,7 @@ def retrieve_response( stream=False, ) - return str( - response.output_message.content # pyright: ignore[reportAttributeAccessIssue] - ) + return str(response.output_message.content) # type: ignore[union-attr] def validate_attachments_metadata(attachments: list[Attachment]) -> None: