Merge branch 'v3-labthings-validate-properties-on-set' into 'v3'
Update to validating properties on write. See merge request openflexure/openflexure-microscope-server!555
This commit is contained in:
commit
eff66eb667
13 changed files with 26 additions and 4 deletions
Binary file not shown.
|
|
@ -405,6 +405,7 @@ class AutofocusThing(lt.Thing):
|
||||||
field of view to assess focus (autofocus and testing the success of a z-stack)
|
field of view to assess focus (autofocus and testing the success of a z-stack)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
_cam: BaseCamera = lt.thing_slot()
|
_cam: BaseCamera = lt.thing_slot()
|
||||||
_stage: BaseStage = lt.thing_slot()
|
_stage: BaseStage = lt.thing_slot()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ class ChannelBlankError(lt.exceptions.InvocationError):
|
||||||
class BackgroundDetectAlgorithm(lt.Thing):
|
class BackgroundDetectAlgorithm(lt.Thing):
|
||||||
"""The base class for defining background detect algorithms."""
|
"""The base class for defining background detect algorithms."""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
display_name: str = lt.property(default="Base Detector", readonly=True)
|
display_name: str = lt.property(default="Base Detector", readonly=True)
|
||||||
|
|
||||||
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
|
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,8 @@ class BaseCamera(OFMThing):
|
||||||
``__init__`` method of the subclass.
|
``__init__`` method of the subclass.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
_all_background_detectors: Mapping[str, BackgroundDetectAlgorithm] = lt.thing_slot()
|
_all_background_detectors: Mapping[str, BackgroundDetectAlgorithm] = lt.thing_slot()
|
||||||
|
|
||||||
mjpeg_stream = lt.outputs.MJPEGStreamDescriptor()
|
mjpeg_stream = lt.outputs.MJPEGStreamDescriptor()
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,8 @@ class CameraStageMapper(lt.Thing):
|
||||||
override the ``get_xyz_position()`` and ``move_to_xyz_position()`` methods.
|
override the ``get_xyz_position()`` and ``move_to_xyz_position()`` methods.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
_cam: BaseCamera = lt.thing_slot()
|
_cam: BaseCamera = lt.thing_slot()
|
||||||
_stage: BaseStage = lt.thing_slot()
|
_stage: BaseStage = lt.thing_slot()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ from .stage.sangaboard import SangaboardThing
|
||||||
class Illumination(lt.Thing):
|
class Illumination(lt.Thing):
|
||||||
"""Base class for an illumination controller."""
|
"""Base class for an illumination controller."""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
@lt.action
|
@lt.action
|
||||||
def set_led(self, led_on: bool = True) -> None:
|
def set_led(self, led_on: bool = True) -> None:
|
||||||
"""Set the LED to on or off."""
|
"""Set the LED to on or off."""
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ class ScanWorkflow(Generic[SettingModelType], lt.Thing):
|
||||||
scan planning, acquisition routine.
|
scan planning, acquisition routine.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
display_name: str = lt.property(default="Base Workflow", readonly=True)
|
display_name: str = lt.property(default="Base Workflow", readonly=True)
|
||||||
ui_blurb: str = lt.property(
|
ui_blurb: str = lt.property(
|
||||||
default="If you see this message, something is wrong.", readonly=True
|
default="If you see this message, something is wrong.", readonly=True
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,8 @@ class SmartScanThing(OFMThing):
|
||||||
past scans.
|
past scans.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
_cam: BaseCamera = lt.thing_slot()
|
_cam: BaseCamera = lt.thing_slot()
|
||||||
_stage: BaseStage = lt.thing_slot()
|
_stage: BaseStage = lt.thing_slot()
|
||||||
_all_workflows: Mapping[str, ScanWorkflow] = lt.thing_slot()
|
_all_workflows: Mapping[str, ScanWorkflow] = lt.thing_slot()
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ class BaseStage(lt.Thing):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_axis_names = ("x", "y", "z")
|
_axis_names = ("x", "y", "z")
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
|
def __init__(self, thing_server_interface: lt.ThingServerInterface) -> None:
|
||||||
"""Initialise the stage.
|
"""Initialise the stage.
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,8 @@ class ParasiticMotionError(lt.exceptions.InvocationError):
|
||||||
class RangeofMotionThing(lt.Thing):
|
class RangeofMotionThing(lt.Thing):
|
||||||
"""A class used to measure the range of motion of the stage in X and Y."""
|
"""A class used to measure the range of motion of the stage in X and Y."""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
_autofocus: AutofocusThing = lt.thing_slot()
|
_autofocus: AutofocusThing = lt.thing_slot()
|
||||||
_cam: BaseCamera = lt.thing_slot()
|
_cam: BaseCamera = lt.thing_slot()
|
||||||
_csm: CameraStageMapper = lt.thing_slot()
|
_csm: CameraStageMapper = lt.thing_slot()
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ class OpenFlexureSystem(lt.Thing):
|
||||||
of the system.
|
of the system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_class_settings = {"validate_properties_on_set": True}
|
||||||
|
|
||||||
_microscope_id: Optional[str] = None
|
_microscope_id: Optional[str] = None
|
||||||
|
|
||||||
@lt.setting
|
@lt.setting
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
from hypothesis import given
|
from hypothesis import given
|
||||||
from hypothesis import strategies as st
|
from hypothesis import strategies as st
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
import labthings_fastapi as lt
|
import labthings_fastapi as lt
|
||||||
|
|
||||||
|
|
@ -210,7 +211,7 @@ def test_objective_getter_setter(camera):
|
||||||
camera.objective = 15
|
camera.objective = 15
|
||||||
with pytest.raises(ValueError, match=err_msg):
|
with pytest.raises(ValueError, match=err_msg):
|
||||||
camera.objective = 0
|
camera.objective = 0
|
||||||
with pytest.raises(ValueError, match=err_msg):
|
with pytest.raises(ValidationError):
|
||||||
camera.objective = "twenty"
|
camera.objective = "twenty"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, ValidationError
|
||||||
|
|
||||||
from labthings_fastapi.exceptions import InvocationCancelledError
|
from labthings_fastapi.exceptions import InvocationCancelledError
|
||||||
from labthings_fastapi.testing import create_thing_without_server
|
from labthings_fastapi.testing import create_thing_without_server
|
||||||
|
|
@ -206,8 +206,11 @@ def test_setting_workflows(caplog, mocker):
|
||||||
with caplog.at_level(logging.WARNING), smart_scan_thing:
|
with caplog.at_level(logging.WARNING), smart_scan_thing:
|
||||||
assert smart_scan_thing._workflow_name == "foo"
|
assert smart_scan_thing._workflow_name == "foo"
|
||||||
assert smart_scan_thing._workflow is workflows["foo"]
|
assert smart_scan_thing._workflow is workflows["foo"]
|
||||||
# Can't set None, warns doesn't change
|
# Can't set None, raises a ValidationError
|
||||||
smart_scan_thing.workflow_name = None
|
with pytest.raises(ValidationError):
|
||||||
|
smart_scan_thing.workflow_name = None
|
||||||
|
# Empty string still won't change, but just warns
|
||||||
|
smart_scan_thing.workflow_name = ""
|
||||||
assert len(caplog.records) == 1
|
assert len(caplog.records) == 1
|
||||||
assert smart_scan_thing._workflow_name == "foo"
|
assert smart_scan_thing._workflow_name == "foo"
|
||||||
assert smart_scan_thing._workflow is workflows["foo"]
|
assert smart_scan_thing._workflow is workflows["foo"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue