Add return typehints to magic methods

This commit is contained in:
Julian Stirling 2025-08-27 14:04:25 +01:00
parent 4c46330959
commit 2ce49088e7
17 changed files with 41 additions and 34 deletions

View file

@ -134,7 +134,6 @@ ignore = [
"D203", # incompatible with D204
"D213", # incompatible with D212
"D400", # A stricter version of #415 that doesn't allow !
"ANN204", # Requrite type hints for
"ANN401", # Disalows Any, Any is needed at times, Once MyPy is running Any will be
# handled appropriately
]

View file

@ -55,7 +55,7 @@ class BackgroundDetectAlgorithm:
settings_data_model: BaseModel = BaseModel
"""The data model of algorithm settings. This must be set by child classes"""
def __init__(self):
def __init__(self) -> None:
"""Initialise the algorithm settings."""
try:
self._settings: BaseModel = self.settings_data_model()

View file

@ -120,7 +120,7 @@ class OFMLogFileFormatter(logging.Formatter):
class OFMHandler(logging.Handler):
"""A logging.Handler that stores the most recent logs for access by the server."""
def __init__(self, level: int = logging.INFO, max_logs: int = 250):
def __init__(self, level: int = logging.INFO, max_logs: int = 250) -> None:
"""Initialise the handler with a set logging level and message buffer size.
:param level: The level of logs captured. As standard logs of INFO and above

View file

@ -167,7 +167,7 @@ class ScanDirectoryManager:
_base_scan_dir: str
def __init__(self, base_scan_dir: str):
def __init__(self, base_scan_dir: str) -> None:
"""Initialise the scan directory manager.
:param base_scan_dir: Path of the directory that holds all scans.
@ -374,7 +374,7 @@ class ScanDirectory:
_name: str
_base_scan_dir: str
def __init__(self, name: str, base_scan_dir: str):
def __init__(self, name: str, base_scan_dir: str) -> None:
"""Initialise the scan directory.
:param name: the name of the scan (the scan directory basename).

View file

@ -80,7 +80,7 @@ class ScanPlanner:
def __init__(
self, initial_position: XYPos, planner_settings: Optional[dict] = None
):
) -> None:
"""Set up lists for the path planning, and scan history."""
self._initial_position = enforce_xy_tuple(initial_position)
self._parse(planner_settings)

View file

@ -59,7 +59,9 @@ class BaseStitcher:
complete.
"""
def __init__(self, images_dir: str, *, overlap: float, correlation_resize: float):
def __init__(
self, images_dir: str, *, overlap: float, correlation_resize: float
) -> None:
"""Initialise a stitcher.
All args except images_dir are positional only.
@ -128,7 +130,9 @@ class PreviewStitcher(BaseStitcher):
one preview must finish before another can be started.
"""
def __init__(self, images_dir: str, *, overlap: float, correlation_resize: float):
def __init__(
self, images_dir: str, *, overlap: float, correlation_resize: float
) -> None:
"""Initialise a preview stitcher.
All args except images_dir are positional only.
@ -192,7 +196,7 @@ class FinalStitcher(BaseStitcher):
correlation_resize: Optional[float] = None,
stitch_tiff: bool = False,
scan_data_dict: Optional[dict[str, Any]] = None,
):
) -> None:
"""Initialise a final stitcher, this has more args than the base class.
All args except images_dir are positional only.

View file

@ -215,7 +215,9 @@ class JPEGSharpnessMonitor:
SharpnessMonitorDep as an argument is called.
"""
def __init__(self, stage: Stage, camera: RawCamera, portal: lt.deps.BlockingPortal):
def __init__(
self, stage: Stage, camera: RawCamera, portal: lt.deps.BlockingPortal
) -> None:
"""Initialise a new JPEGSharpnessMonitor. The args are injected automatically.
:param stage: A direct_thing_client dependency for the the microscope stage.

View file

@ -69,7 +69,7 @@ class CameraMemoryBuffer:
_storage: dict[int, tuple[Any, Optional[dict]]]
def __init__(self):
def __init__(self) -> None:
"""Create the buffer instance."""
# This dictionary is the main store for data. Dictionaries are ordered since
# Python 3.6, so the order in the dictionary is the capture order
@ -170,7 +170,7 @@ class BaseCamera(lt.Thing):
lores_mjpeg_stream = lt.outputs.MJPEGStreamDescriptor()
_memory_buffer = CameraMemoryBuffer()
def __init__(self):
def __init__(self) -> None:
"""Initialise the base camera, this creates the background detectors.
This must be run by all child camera classes.

View file

@ -25,7 +25,7 @@ from . import BaseCamera
class OpenCVCamera(BaseCamera):
"""A Thing that provides and interface to an OpenCV Camera."""
def __init__(self, camera_index: int = 0):
def __init__(self, camera_index: int = 0) -> None:
"""Iniatilise the thing storing the index of the camera to use.
:param camera_index: The index of the camera to use for the microscope.
@ -35,7 +35,7 @@ class OpenCVCamera(BaseCamera):
self._capture_thread: Optional[Thread] = None
self._capture_enabled = False
def __enter__(self):
def __enter__(self) -> None:
"""Start the capture thread when the Thing context manager is opened."""
self.cap = cv2.VideoCapture(self.camera_index)
self._capture_enabled = True
@ -48,7 +48,7 @@ class OpenCVCamera(BaseCamera):
_exc_type: type[BaseException],
_exc_value: Optional[BaseException],
_traceback: Optional[TracebackType],
):
) -> None:
"""Release the camera when the Thing context manager is closed.
Before releasing the camera the capture thread is closed.

View file

@ -53,7 +53,9 @@ class MissingCalibrationError(RuntimeError):
class PicameraStreamOutput(Output):
"""An Output class that sends frames to a stream."""
def __init__(self, stream: lt.outputs.MJPEGStream, portal: lt.deps.BlockingPortal):
def __init__(
self, stream: lt.outputs.MJPEGStream, portal: lt.deps.BlockingPortal
) -> None:
"""Create an output that puts frames in an MJPEGStream.
We need to pass the stream object, and also the blocking portal, because
@ -126,7 +128,7 @@ class StreamingPiCamera2(BaseCamera):
generalisation.
"""
def __init__(self, camera_num: int = 0):
def __init__(self, camera_num: int = 0) -> None:
"""Initialise the camera with the given camera number.
This makes no connection to the camera (except to get the default tuning file).
@ -384,7 +386,7 @@ class StreamingPiCamera2(BaseCamera):
)
self._picamera_lock = RLock()
def __enter__(self):
def __enter__(self) -> None:
"""Start streaming when the Thing context manager is opened.
This opens the picamera connection, initialises the camera, sets the
@ -430,7 +432,7 @@ class StreamingPiCamera2(BaseCamera):
_exc_type: type[BaseException],
_exc_value: Optional[BaseException],
_traceback: Optional[TracebackType],
):
) -> None:
"""Close the picamera connection when the Thing context manager is closed."""
self.stop_streaming()
with self._streaming_picamera() as cam:

View file

@ -54,7 +54,7 @@ class SimulatedCamera(BaseCamera):
glyph_shape: tuple[int, int, int] = (91, 91, 3),
canvas_shape: tuple[int, int, int] = (3000, 4000, 3),
frame_interval: float = 0.1,
):
) -> None:
"""Initialise the simulated with settings for how images are generated.
:param shape: The shape (size) of the generated image.
@ -208,7 +208,7 @@ class SimulatedCamera(BaseCamera):
pos = {"x": 0, "y": 0, "z": 0}
return self.generate_image((pos["y"], pos["x"], pos["z"]))
def __enter__(self):
def __enter__(self) -> None:
"""Start the capture thread when the Thing context manager is opened."""
self.start_streaming()
return self
@ -218,7 +218,7 @@ class SimulatedCamera(BaseCamera):
_exc_type: type[BaseException],
_exc_value: Optional[BaseException],
_traceback: Optional[TracebackType],
):
) -> None:
"""Close the capture thread when the Thing context manager is closed."""
if self.stream_active:
self._capture_enabled = False

View file

@ -62,7 +62,7 @@ class RecordedMove:
for calibrating the stage as it allows measuring how long moves take.
"""
def __init__(self, stage: Stage):
def __init__(self, stage: Stage) -> None:
"""Set the stage client used for for movement.
:param stage: the stage client to be used. ``stage.move_to_xyz_position`` will
@ -72,7 +72,7 @@ class RecordedMove:
self._current_position: Optional[CoordinateType] = None
self._history: List[Tuple[float, Optional[CoordinateType]]] = []
def __call__(self, new_position: CoordinateType):
def __call__(self, new_position: CoordinateType) -> None:
"""Move to a new position, and record it."""
self._history.append((time.time(), self._current_position))
self._stage.move_to_xyz_position(xyz_pos=new_position)
@ -99,7 +99,7 @@ class CSMUncalibratedError(HTTPException):
live preview to move, or when performing a scan.
"""
def __init__(self):
def __init__(self) -> None:
"""Customise the default error code and message of HTTPException."""
HTTPException.__init__(
self,

View file

@ -85,7 +85,7 @@ class SmartScanThing(lt.Thing):
past scans.
"""
def __init__(self, scans_folder: str):
def __init__(self, scans_folder: str) -> None:
"""Initialise a SmartScanThing saving to and loading from the input directory.
:param scans_folder: This is the path to the directory where all scans will be

View file

@ -45,7 +45,7 @@ class BaseStage(lt.Thing):
_axis_names = ("x", "y", "z")
def __init__(self):
def __init__(self) -> None:
"""Initialise the stage.
:raises RedefinedBaseMovementError: if ``move_relative`` and/or

View file

@ -19,7 +19,7 @@ class DummyStage(BaseStage):
hardware attached.
"""
def __init__(self, step_time: float = 0.001, **kwargs: Any):
def __init__(self, step_time: float = 0.001, **kwargs: Any) -> None:
"""Initialise the Dummy stage, setting the step_time to adjust the speed.
:param step_time: The time in seconds per "motor" step. The default of 0.001
@ -31,7 +31,7 @@ class DummyStage(BaseStage):
self.step_time = step_time
self.instantaneous_position = self._hardware_position
def __enter__(self):
def __enter__(self) -> None:
"""Register the stage position when the Thing context manager is opened."""
self.instantaneous_position = self._hardware_position
@ -40,7 +40,7 @@ class DummyStage(BaseStage):
_exc_type: type[BaseException],
_exc_value: Optional[BaseException],
_traceback: Optional[TracebackType],
):
) -> None:
"""Nothing to do when the Thing context manager is closed."""
axis_inverted = lt.ThingSetting(

View file

@ -25,7 +25,7 @@ class SangaboardThing(BaseStage):
functionality is accessed by directly querying the serial interface.
"""
def __init__(self, port: str = None, **kwargs: Any):
def __init__(self, port: str = None, **kwargs: Any) -> None:
"""Initialise SangaboardThing.
Initialise the "Thing", but do not initialise an underlying
@ -42,7 +42,7 @@ class SangaboardThing(BaseStage):
self.sangaboard_kwargs["port"] = port
super().__init__(**kwargs)
def __enter__(self):
def __enter__(self) -> None:
"""Connect to the sangaboard when the Thing context manager is opened."""
self._sangaboard = sangaboard.Sangaboard(**self.sangaboard_kwargs)
self._sangaboard_lock = threading.RLock()
@ -59,7 +59,7 @@ class SangaboardThing(BaseStage):
_exc_type: type[BaseException],
_exc_value: Optional[BaseException],
_traceback: Optional[TracebackType],
):
) -> None:
"""Close the sangaboard connection when the Thing context manager is closed."""
with self.sangaboard() as sb:
sb.close()

View file

@ -78,7 +78,7 @@ class ErrorCapturingThread(Thread):
kwargs: Optional[dict[str, Any]] = None,
*,
daemon: Optional[bool] = None,
):
) -> None:
"""Initialise with the same arguments as Thread."""
# As all inputs are keywords we need to set the default values for args and kwargs:
if args is None: