From b038cd534846e0f6c1f034274eb06373f5553021 Mon Sep 17 00:00:00 2001 From: David Perl Date: Fri, 3 Jul 2026 17:36:02 +0200 Subject: [PATCH] wip fix: basedpyright errors --- .gitea/workflows/ci.yml | 9 ++++- src/aarecommon/config/logger.py | 11 +++--- src/aarecommon/errors/exception_handler.py | 41 ++++++---------------- src/aarecommon/math/find_xtal.py | 2 +- tests/test_data_collection_parameters.py | 4 ++- tests/test_find_xtal.py | 4 ++- tests/test_models_extra.py | 6 ++-- 7 files changed, 36 insertions(+), 41 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 7289d28..b43f51d 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -17,11 +17,18 @@ jobs: with: python_version: "3.12" - - name: Format + - name: Activate environment run: | source .venv/bin/activate + + - name: Format + run: | ruff format --check + - name: Type checking + run: | + basedpyright . + test: runs-on: ubuntu-latest needs: "lint" diff --git a/src/aarecommon/config/logger.py b/src/aarecommon/config/logger.py index 92bad7d..9207550 100644 --- a/src/aarecommon/config/logger.py +++ b/src/aarecommon/config/logger.py @@ -3,6 +3,7 @@ import logging.config import os from pathlib import Path +from aarecommon.types import JsonableDict import yaml @@ -33,7 +34,7 @@ class IgnoreSuccessfulStatusAccessFilter(logging.Filter): ) -def get_uvicorn_logging_config() -> dict: +def get_uvicorn_logging_config() -> JsonableDict: return { "version": 1, "disable_existing_loggers": False, @@ -80,10 +81,12 @@ def get_config_path(env: str = "dev") -> Path: return config_path -# TODO fix logging. +_FALLBACK_BASE_DIR = "~/tmp/mxlogs/" def setup_logger( - name="aareDAQ", base_dir: str | None = f"~/tmp/mxlogs/", config_path: str | None = None + name="aareDAQ", base_dir: str | None = _FALLBACK_BASE_DIR, config_path: str | None = None ): + if base_dir is None: + base_dir = _FALLBACK_BASE_DIR # switch to production mode using: $ APP_ENV=prod python main.py env = os.getenv("APP_ENV", "dev") # default: dev @@ -139,7 +142,7 @@ def find_existing_formatter( return logging.Formatter(default_fmt, datefmt=default_datefmt) -def attach_to_logger(logger_name: str = "", handler: logging.Handler = None): +def attach_to_logger(logger_name: str, handler: logging.Handler): logging.getLogger(logger_name).addHandler(handler) diff --git a/src/aarecommon/errors/exception_handler.py b/src/aarecommon/errors/exception_handler.py index c640b6f..530ff84 100644 --- a/src/aarecommon/errors/exception_handler.py +++ b/src/aarecommon/errors/exception_handler.py @@ -10,19 +10,12 @@ logger = setup_logger("aareDAQ") class AareException(Exception): - """Root of the aare exception hierarchy. + """Root of the aare exception hierarchy.""" - Class-level ``critical`` is the default; pass ``critical=...`` to the - constructor of an "optionally critical" subclass to override on a single - raise site. - """ - - critical: ClassVar[bool] = False - - def __init__(self, *args, critical: bool | None = None, **kwargs): - super().__init__(*args, **kwargs) - if critical is not None: - self.critical = critical + def __init__(self, message: str, *args, critical: bool = False, **kwargs): + super().__init__(message, *args, **kwargs) + self.message=message + self.critical = critical class AutomationError(AareException): @@ -76,23 +69,18 @@ class BeamlineStateException(AutomationError): class TransformationInvalidException(AutomationError): - critical: ClassVar[bool] = True - def __init__( - self, message: str = "Transformation is not implemented", *, critical: bool | None = None + self, message: str = "Transformation is not implemented", *, critical: bool = True ): super().__init__(message, critical=critical) - self.message = message def __str__(self) -> str: return self.message class StateTransitionFailed(BeamlineStateException): - critical: ClassVar[bool] = True - def __init__( - self, message: str = "Beamline state transition failed", *, critical: bool | None = None + self, message: str = "Beamline state transition failed", *, critical: bool=True ): super().__init__(message, critical=critical) self.message = message @@ -102,13 +90,10 @@ class StateTransitionFailed(BeamlineStateException): class MaintenanceStateException(BeamlineStateException): - critical: ClassVar[bool] = True - def __init__( - self, message: str = "Beamline is in Maintenance state", *, critical: bool | None = None + self, message: str = "Beamline is in Maintenance state", *, critical: bool = True ): super().__init__(message, critical=critical) - self.message = message def __str__(self) -> str: return self.message @@ -209,13 +194,10 @@ class DoorSafetyError(AutomationError): critical so automation halts and the GUI shows a pop-up. """ - critical: ClassVar[bool] = True - def __init__( - self, message: str = "Door safety could not be activated", *, critical: bool | None = None + self, message: str = "Door safety could not be activated", *, critical: bool = True ): super().__init__(message, critical=critical) - self.message = message def __str__(self) -> str: return self.message @@ -519,13 +501,10 @@ class AerotechCommunicationError(AerotechException): class MagnetPositionSensorErorr(AutomationError): - critical: ClassVar[bool] = True - def __init__( - self, message: str = "Magnet position sensor error", *, critical: bool | None = None + self, message: str = "Magnet position sensor error", *, critical: bool = True ): super().__init__(message, critical=critical) - self.message = message def __str__(self) -> str: return self.message diff --git a/src/aarecommon/math/find_xtal.py b/src/aarecommon/math/find_xtal.py index 1cb0f2d..ea41836 100644 --- a/src/aarecommon/math/find_xtal.py +++ b/src/aarecommon/math/find_xtal.py @@ -540,7 +540,7 @@ def crystal_mask_kmeans(arr: np.ndarray, n_clusters: int = 3) -> tuple[np.ndarra return mask, threshold -CRYSTAL_METHOD_MAP: dict = { +CRYSTAL_METHOD_MAP: dict[str, tuple[str, Callable]] = { "corner": ("Corner background", crystal_mask_corner_background), "otsu": ("Otsu (nonzero)", crystal_mask_otsu_nonzero), "mean_sigma": ("Mean + 0.5σ", lambda arr: crystal_mask_mean_sigma(arr, n_sigma=0.5)), diff --git a/tests/test_data_collection_parameters.py b/tests/test_data_collection_parameters.py index fb66590..c04c8b0 100644 --- a/tests/test_data_collection_parameters.py +++ b/tests/test_data_collection_parameters.py @@ -50,7 +50,9 @@ def test_processingpipeline_accepts_unknown_value_after_refactor(): def test_datacollectionparameters_accepts_legacy_aliases(): params = DataCollectionParameters( - totalrange=180, cellparameters="10 20 30 90 90 120", userresolution=1.4 + totalrange=180, + cellparameters="10 20 30 90 90 120", + userresolution=1.4, # type: ignore # legacy ) assert params.totalangle == 180 assert params.unitcell == "10 20 30 90 90 120" diff --git a/tests/test_find_xtal.py b/tests/test_find_xtal.py index 02f3a56..63f9f57 100644 --- a/tests/test_find_xtal.py +++ b/tests/test_find_xtal.py @@ -102,6 +102,7 @@ def test_raster_centre_of_mass(mock_raster_results): arr = np.zeros((3, 3)) arr[1, 1] = 10.0 com = raster_centre_of_mass(arr, mock_raster_results) + assert com is not None assert com.n_x == 1.0 assert com.n_y == 1.0 @@ -110,7 +111,7 @@ def test_has_sufficient_low_res_spots(): arr = np.array([[1, 2], [3, 4]]) assert has_sufficient_low_res_spots(arr, 3.0) is True assert has_sufficient_low_res_spots(arr, 5.0) is False - assert has_sufficient_low_res_spots(None, 1.0) is False + assert has_sufficient_low_res_spots(None, 1.0) is False # type: ignore # expected wrong type @pytest.fixture @@ -161,6 +162,7 @@ def test_compute_crystal_score_array_weights(): def test_raster_highest_score(mock_score_results): com = raster_highest_score(mock_score_results) + assert com is not None assert com.n_x == 1.0 assert com.n_y == 1.0 assert com.max_image == 3 diff --git a/tests/test_models_extra.py b/tests/test_models_extra.py index e7f863e..a61896d 100644 --- a/tests/test_models_extra.py +++ b/tests/test_models_extra.py @@ -53,6 +53,7 @@ def test_sample_short_info_methods(): } info2 = SampleShortInfo.from_dict(data) assert info2.db_id == 2 + assert info2.location is not None assert info2.location.segment == "B" assert info2.aaredb_params is not None assert info2.aaredb_params.totalangle == 120 @@ -72,6 +73,7 @@ def test_ml_output_model_extra_methods(): key = model.add_box(MLBoxType.CRYSTAL, (1, 2, 3, 4), 0.8) box_model = model.get_box_model(key) + assert box_model is not None assert box_model.conf == 0.8 assert model.get_box_tuple(key) == (1, 2, 3, 4) @@ -94,10 +96,10 @@ def test_ml_output_model_extra_methods(): assert MLOutputModel.get_class_str(MLBoxType.LOOP_FACE) == "Loop_face" assert MLOutputModel.get_class_str(MLBoxType.ICE) == "Ice" assert MLOutputModel.get_class_str(MLBoxType.NEEDLE) == "Needle" - assert MLOutputModel.get_class_str(100) == "Unknown" + assert MLOutputModel.get_class_str(100) == "Unknown" # type: ignore # Should be an unknown argument def test_beamline_state_enum_display_name(): assert BeamlineStateEnum.SampleExchange.display_name() == "Sample exchange" assert BeamlineStateEnum.Moving.display_name() == "Moving" - assert BeamlineStateEnum.display_name(None) == "-" + assert BeamlineStateEnum.display_name(None) == "-" # type: ignore # Should be an unknown argument