From 4f59286f05ed73f1c344d616ebfd4c633d5bbd50 Mon Sep 17 00:00:00 2001 From: PredictiveManish Date: Wed, 25 Mar 2026 22:16:21 +0530 Subject: [PATCH 1/5] Enable comprehensive mypy type checking across landmarkdiff codebase --- .github/workflows/ci.yml | 11 +++++++++-- .pre-commit-config.yaml | 1 + benchmarks/__init__.py | 1 + pyproject.toml | 11 ++++++----- scripts/__init__.py | 1 + 5 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 benchmarks/__init__.py create mode 100644 scripts/__init__.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29d0b94..aae2e24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,13 @@ jobs: type-check: runs-on: ubuntu-latest needs: lint + strategy: + fail-fast: false + matrix: + target: + - landmarkdiff/ + - scripts/ + - benchmarks/ steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 @@ -37,8 +44,8 @@ jobs: cache: pip - name: Install dependencies run: pip install -e ".[dev]" - - name: Type check - run: mypy landmarkdiff/ --ignore-missing-imports + - name: Type check ${{ matrix.target }} + run: mypy ${{ matrix.target }} pre-commit: runs-on: ubuntu-latest needs: lint diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ec5e97b..89486e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,6 +28,7 @@ repos: additional_dependencies: [types-Pillow, types-PyYAML, types-requests] exclude: '\.ipynb$' args: [ + --explicit-package-bases, --ignore-missing-imports, --config-file=pyproject.toml, --exclude, 'scripts/benchmark_inference\.py', diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py new file mode 100644 index 0000000..46ae392 --- /dev/null +++ b/benchmarks/__init__.py @@ -0,0 +1 @@ +"""Benchmarks package for LandmarkDiff performance testing.""" diff --git a/pyproject.toml b/pyproject.toml index 9379a57..5e362eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -192,15 +192,16 @@ ignore = [ [tool.mypy] python_version = "3.10" -warn_return_any = false +warn_return_any = true warn_unused_configs = true -disallow_untyped_defs = false -check_untyped_defs = false +disallow_untyped_defs = true +check_untyped_defs = true explicit_package_bases = true ignore_missing_imports = true +strict_optional = true +warn_redundant_casts = true +warn_unused_ignores = true exclude = [ - "scripts/batch_inference.py", - "scripts/benchmark_inference.py", "examples/*.ipynb", ] diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..2bf8e08 --- /dev/null +++ b/scripts/__init__.py @@ -0,0 +1 @@ +"""Scripts package for LandmarkDiff utilities and experiments.""" From 14616b4301b9b16cec64c5ea565f92c86ae318f2 Mon Sep 17 00:00:00 2001 From: PredictiveManish Date: Thu, 26 Mar 2026 00:15:44 +0530 Subject: [PATCH 2/5] Excluding tests for phase 1 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 5e362eb..98c21b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -203,6 +203,7 @@ warn_redundant_casts = true warn_unused_ignores = true exclude = [ "examples/*.ipynb", + "tests/*.py", ] [[tool.mypy.overrides]] From edf1d6d23e15c2d76b57d5a7c4e4675ea0c6fa3d Mon Sep 17 00:00:00 2001 From: PredictiveManish Date: Thu, 26 Mar 2026 00:19:09 +0530 Subject: [PATCH 3/5] Excluding tests for phase 1 --- pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 98c21b1..365aa45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -248,3 +248,7 @@ ignore_errors = true [[tool.mypy.overrides]] module = ["scripts.*"] ignore_errors = true + +[[tool.mypy.overrides]] +module = ["tests.*"] +ignore_errors = true \ No newline at end of file From bdb6d624126ee31d692ef4a862ebf50a1036356c Mon Sep 17 00:00:00 2001 From: PredictiveManish Date: Thu, 26 Mar 2026 00:40:37 +0530 Subject: [PATCH 4/5] Ignoring examples for phase-1 --- landmarkdiff/api_client_async.py | 6 +++--- pyproject.toml | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/landmarkdiff/api_client_async.py b/landmarkdiff/api_client_async.py index 307dd20..15b0284 100644 --- a/landmarkdiff/api_client_async.py +++ b/landmarkdiff/api_client_async.py @@ -22,7 +22,7 @@ async def main(): import base64 import logging from pathlib import Path -from typing import Any +from typing import Any, cast import cv2 import numpy as np @@ -91,7 +91,7 @@ async def _handle_response(self, resp: Any) -> dict[str, Any]: if resp.status >= 400: text = await resp.text() raise LandmarkDiffAPIError(f"Server returned {resp.status}: {text[:200]}") - return await resp.json() + return cast(dict[str, Any], await resp.json()) # ------------------------------------------------------------------ # API methods @@ -124,7 +124,7 @@ async def procedures(self) -> list[str]: try: async with session.get(f"{self.base_url}/procedures") as resp: data = await self._handle_response(resp) - return data.get("procedures", []) + return cast(list[str], data.get("procedures", [])) except LandmarkDiffAPIError: raise except Exception as e: diff --git a/pyproject.toml b/pyproject.toml index 365aa45..b18666f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -204,6 +204,7 @@ warn_unused_ignores = true exclude = [ "examples/*.ipynb", "tests/*.py", + "examples/", ] [[tool.mypy.overrides]] @@ -251,4 +252,8 @@ ignore_errors = true [[tool.mypy.overrides]] module = ["tests.*"] -ignore_errors = true \ No newline at end of file +ignore_errors = true + +[[tool.mypy.overrides]] +module = ["examples.*"] +ignore_errors = true From 7ae8f5276306af10f5553364021d21cea808c51a Mon Sep 17 00:00:00 2001 From: PredictiveManish Date: Thu, 26 Mar 2026 01:36:44 +0530 Subject: [PATCH 5/5] Updated return statements --- landmarkdiff/comparison.py | 9 +++++---- landmarkdiff/planning.py | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/landmarkdiff/comparison.py b/landmarkdiff/comparison.py index c1ead45..1b28cdb 100644 --- a/landmarkdiff/comparison.py +++ b/landmarkdiff/comparison.py @@ -7,6 +7,7 @@ from __future__ import annotations import logging +from typing import cast import cv2 import numpy as np @@ -47,7 +48,7 @@ def create_slider_composite( if line_width > 0 and 0 < split_x < w: cv2.line(result, (split_x, 0), (split_x, h - 1), line_color, line_width) - return result + return cast(np.ndarray, result) def create_side_by_side( @@ -101,7 +102,7 @@ def create_side_by_side( cv2.LINE_AA, ) - return canvas + return cast(np.ndarray, canvas) def create_difference_heatmap( @@ -127,7 +128,7 @@ def create_difference_heatmap( diff = cv2.absdiff(original, pred) gray_diff = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY) amplified = np.clip(gray_diff.astype(np.float32) * amplify, 0, 255).astype(np.uint8) - return cv2.applyColorMap(amplified, colormap) + return cast(np.ndarray, cv2.applyColorMap(amplified, colormap)) def create_checkerboard_blend( @@ -166,4 +167,4 @@ def create_checkerboard_blend( mask_3ch = np.stack([mask] * 3, axis=-1) result = original.astype(np.float32) * mask_3ch + pred.astype(np.float32) * (1.0 - mask_3ch) - return np.clip(result, 0, 255).astype(np.uint8) + return cast(np.ndarray, np.clip(result, 0, 255).astype(np.uint8)) diff --git a/landmarkdiff/planning.py b/landmarkdiff/planning.py index dfa23e9..72abeaf 100644 --- a/landmarkdiff/planning.py +++ b/landmarkdiff/planning.py @@ -8,6 +8,7 @@ from __future__ import annotations from dataclasses import dataclass +from typing import cast import cv2 import numpy as np @@ -214,4 +215,4 @@ def visualize_planning( cv2.LINE_AA, ) - return canvas + return cast(np.ndarray, canvas)