diff --git a/hardware-specific-tests/picamera2/cam_test_utils/__init__.py b/hardware-specific-tests/picamera2/cam_test_utils/__init__.py index 145510f1..a7baeb0e 100644 --- a/hardware-specific-tests/picamera2/cam_test_utils/__init__.py +++ b/hardware-specific-tests/picamera2/cam_test_utils/__init__.py @@ -32,10 +32,10 @@ def camera_test_client( if settings_folder is None: settings_folder = tmpdir server = lt.ThingServer(settings_folder=settings_folder) - server.add_thing(cam, "/camera/") + server.add_thing(cam, "camera") with TestClient(server.app) as test_client: - client = lt.ThingClient.from_url("/camera/", client=test_client) + client = lt.ThingClient.from_url("camera", client=test_client) yield client del server del cam diff --git a/hardware-specific-tests/picamera2/conftest.py b/hardware-specific-tests/picamera2/conftest.py index f62b22a1..d6f4568d 100644 --- a/hardware-specific-tests/picamera2/conftest.py +++ b/hardware-specific-tests/picamera2/conftest.py @@ -26,7 +26,7 @@ def picamera_client(picamera_thing) -> lt.ThingClient: This fixture: * Sets up a ThingServer, - * Registers a StreamingPiCamera2 instance at the "/camera/" endpoint + * Registers a StreamingPiCamera2 instance at the "camera" endpoint * Provides a ThingClient for interacting with it during tests. """ with camera_test_client(cam=picamera_thing) as picamera_client: diff --git a/src/openflexure_microscope_server/server/__init__.py b/src/openflexure_microscope_server/server/__init__.py index 2533ad20..73cb609c 100644 --- a/src/openflexure_microscope_server/server/__init__.py +++ b/src/openflexure_microscope_server/server/__init__.py @@ -63,11 +63,11 @@ def customise_server( def _get_scans_dir(config: dict) -> Optional[str]: """Read the config and return the scans directory. - Return is None if there is no /smart_scan/ thing loaded. + Return is None if there is no smart_scan thing loaded. """ - if "/smart_scan/" in config["things"]: + if "smart_scan" in config["things"]: try: - return config["things"]["/smart_scan/"]["kwargs"]["scans_folder"] + return config["things"]["smart_scan"]["kwargs"]["scans_folder"] except KeyError as e: msg = "Configuration error: smart scan should have scans_folder kwarg set" raise RuntimeError(msg) from e @@ -96,7 +96,7 @@ def serve_from_cli(argv: Optional[list[str]] = None) -> None: def shutdown_call() -> None: try: # Kill any mjpeg streams so that StreamingResponses close. - server.things["/camera/"].kill_mjpeg_streams() + server.things["camera"].kill_mjpeg_streams() except BaseException as e: # Catch anything and log as it is essential that this # function cannot raise an unhandled exception or Uvicorn diff --git a/src/openflexure_microscope_server/things/camera/__init__.py b/src/openflexure_microscope_server/things/camera/__init__.py index 67f00b32..e2299737 100644 --- a/src/openflexure_microscope_server/things/camera/__init__.py +++ b/src/openflexure_microscope_server/things/camera/__init__.py @@ -731,7 +731,7 @@ class BaseCamera(lt.Thing): return {} -CameraDependency = lt.deps.direct_thing_client_dependency(BaseCamera, "/camera/") +CameraDependency = lt.deps.direct_thing_client_dependency(BaseCamera, "camera") RawCameraDependency = lt.deps.raw_thing_dependency(BaseCamera) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 951e6988..62db3062 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -42,9 +42,9 @@ T = TypeVar("T") P = ParamSpec("P") CSMDep = lt.deps.direct_thing_client_dependency( - CameraStageMapper, "/camera_stage_mapping/" + CameraStageMapper, "camera_stage_mapping" ) -AutofocusDep = lt.deps.direct_thing_client_dependency(AutofocusThing, "/autofocus/") +AutofocusDep = lt.deps.direct_thing_client_dependency(AutofocusThing, "autofocus") class ScanListInfo(BaseModel): diff --git a/src/openflexure_microscope_server/things/stage/__init__.py b/src/openflexure_microscope_server/things/stage/__init__.py index f6ae2526..d22809ce 100644 --- a/src/openflexure_microscope_server/things/stage/__init__.py +++ b/src/openflexure_microscope_server/things/stage/__init__.py @@ -228,4 +228,4 @@ class BaseStage(lt.Thing): self.move_absolute(cancel=cancel, x=xyz_pos[0], y=xyz_pos[1], z=xyz_pos[2]) -StageDependency = lt.deps.direct_thing_client_dependency(BaseStage, "/stage/") +StageDependency = lt.deps.direct_thing_client_dependency(BaseStage, "stage") diff --git a/src/openflexure_microscope_server/things/stage_measure.py b/src/openflexure_microscope_server/things/stage_measure.py index 439561e7..4c244d9e 100644 --- a/src/openflexure_microscope_server/things/stage_measure.py +++ b/src/openflexure_microscope_server/things/stage_measure.py @@ -30,9 +30,9 @@ from .camera_stage_mapping import CameraStageMapper from .stage import StageDependency as StageDep CSMDep = lt.deps.direct_thing_client_dependency( - CameraStageMapper, "/camera_stage_mapping/" + CameraStageMapper, "camera_stage_mapping" ) -AutofocusDep = lt.deps.direct_thing_client_dependency(AutofocusThing, "/autofocus/") +AutofocusDep = lt.deps.direct_thing_client_dependency(AutofocusThing, "autofocus") ## Size of movement in percentage of field of view SMALL_STEP = 20 diff --git a/src/openflexure_microscope_server/ui.py b/src/openflexure_microscope_server/ui.py index 9de8396c..3b7ace59 100644 --- a/src/openflexure_microscope_server/ui.py +++ b/src/openflexure_microscope_server/ui.py @@ -54,9 +54,8 @@ def action_button_for(action: Callable[..., Any], **kwargs: Any) -> ActionButton :param kwargs: Any attribute of `ActionButton` except for ``thing`` or ``action``. """ thing = action.args[0] - thing_path = thing.path.strip("/") action_name = action.func.__name__ - return ActionButton(thing=thing_path, action=action_name, **kwargs) + return ActionButton(thing=thing.name, action=action_name, **kwargs) class PropertyControl(BaseModel): @@ -94,7 +93,6 @@ def property_control_for( :param kwargs: Any attribute of `PropertyControl` except for ``thing`` or ``property_name``. If label is not set here it will be the property name. """ - thing_path = thing.path.strip("/") if "label" not in kwargs: kwargs["label"] = property_name - return PropertyControl(thing=thing_path, property_name=property_name, **kwargs) + return PropertyControl(thing=thing.name, property_name=property_name, **kwargs) diff --git a/tests/test_camera.py b/tests/test_camera.py index 18c8214a..628f2a09 100644 --- a/tests/test_camera.py +++ b/tests/test_camera.py @@ -21,7 +21,7 @@ def camera_server(camera: SimulatedCamera) -> lt.ThingClient: """ with tempfile.TemporaryDirectory() as tmpdir: server = lt.ThingServer(settings_folder=tmpdir) - server.add_thing(camera, "/camera/") + server.add_thing(camera, "camera") with TestClient(server.app): yield server diff --git a/tests/test_dummy_server.py b/tests/test_dummy_server.py index 08715d7a..16b7aa0e 100644 --- a/tests/test_dummy_server.py +++ b/tests/test_dummy_server.py @@ -35,12 +35,12 @@ def thing_server(): SimulatedCamera( shape=(240, 320, 3), canvas_shape=(1000, 1500, 3), frame_interval=0.01 ), - "/camera/", + "camera", ) - server.add_thing(DummyStage(step_time=0.000001), "/stage/") - server.add_thing(AutofocusThing(), "/autofocus/") - server.add_thing(CameraStageMapper(), "/camera_stage_mapping/") - assert os.path.exists(os.path.join(temp_folder.name, "camera/")) + server.add_thing(DummyStage(step_time=0.000001), "stage") + server.add_thing(AutofocusThing(), "autofocus") + server.add_thing(CameraStageMapper(), "camera_stage_mapping") + assert os.path.exists(os.path.join(temp_folder.name, "camera")) # Note: yield is important. If return is used the temp folder gets deleted # before the test runs. Silence PT022 as ruff doesn't think yield is needed. yield server # noqa: PT022 @@ -60,7 +60,7 @@ def slower_client(thing_server): The step time for the stage is 100 microseconds rather than 1 microsecond. """ - thing_server.things["/stage/"].step_time = 0.0001 + thing_server.things["stage"].step_time = 0.0001 with TestClient(thing_server.app) as client: yield client @@ -68,31 +68,31 @@ def slower_client(thing_server): def test_autofocus(slower_client): """Test Fast Autofocus can run doesn't raise an exception.""" client = slower_client - autofocus = lt.ThingClient.from_url("/autofocus/", client) + autofocus = lt.ThingClient.from_url("autofocus", client) _ = autofocus.fast_autofocus() def test_grab_jpeg(client): """Check that grab_jpeg returns a blob that can be opened.""" - camera = lt.ThingClient.from_url("/camera/", client) + camera = lt.ThingClient.from_url("camera", client) blob = camera.grab_jpeg() _image = Image.open(blob.open()) def test_capture_jpeg_metadata(client): """Check that the position is encoded into the image metadata.""" - camera = lt.ThingClient.from_url("/camera/", client) + camera = lt.ThingClient.from_url("camera", client) blob = camera.capture_jpeg() image = Image.open(blob.open()) exif_dict = piexif.load(image.info["exif"]) encoded_metadata = exif_dict["Exif"][piexif.ExifIFD.UserComment] metadata = json.loads(encoded_metadata) - assert "position" in metadata["/stage/"] + assert "position" in metadata["stage"] def test_stage(client): """Test moving th stage forwards and backwards.""" - stage = lt.ThingClient.from_url("/stage/", client) + stage = lt.ThingClient.from_url("stage", client) start = stage.position move = {"x": 1, "y": 2, "z": 3} stage.move_relative(**move) @@ -107,14 +107,14 @@ def test_stage(client): def test_capture_array(client): """Capture array from simulation and check the size is as expected.""" - camera = lt.ThingClient.from_url("/camera/", client) + camera = lt.ThingClient.from_url("camera", client) array = np.asarray(camera.capture_array()) assert array.shape == (240, 320, 3) def test_camera_stage_mapping_calibration(client): """Check that camera stage mapping can run without an exception.""" - camera = lt.ThingClient.from_url("/camera/", client) + camera = lt.ThingClient.from_url("camera", client) camera.settling_time = 0 - camera_stage_mapping = lt.ThingClient.from_url("/camera_stage_mapping/", client) + camera_stage_mapping = lt.ThingClient.from_url("camera_stage_mapping", client) camera_stage_mapping.calibrate_xy() diff --git a/tests/test_legacy_api.py b/tests/test_legacy_api.py index 2f7f105d..b040d064 100644 --- a/tests/test_legacy_api.py +++ b/tests/test_legacy_api.py @@ -12,8 +12,8 @@ def test_v2_endpoints(mocker): """Check that the expected v2 endpoints are added.""" mock_server = mocker.Mock() # Mock the camera thing to mocke the lores_mjpeg stream get_frame() - mock_server.things = {"/camera/": mocker.Mock()} - mock_server.things["/camera/"].lores_mjpeg_stream.grab_frame = mocker.AsyncMock( + mock_server.things = {"camera": mocker.Mock()} + mock_server.things["camera"].lores_mjpeg_stream.grab_frame = mocker.AsyncMock( return_value="Mock Frame" ) mock_app = mock_server.app diff --git a/tests/test_server_config.py b/tests/test_server_config.py index d3a267cb..82b22929 100644 --- a/tests/test_server_config.py +++ b/tests/test_server_config.py @@ -102,7 +102,7 @@ def test_get_scans_dir_no_smart_scan(): with open(FULL_CONFIG, "r", encoding="utf-8") as f_obj: config_dict = json.load(f_obj) # Delete smart scan - del config_dict["things"]["/smart_scan/"] + del config_dict["things"]["smart_scan"] # No SmartScanThing, should return None assert ofm_server._get_scans_dir(config_dict) is None @@ -116,14 +116,14 @@ def test_get_scans_dir_bad_smart_scan_config(): # Copy the dictionary broken_config = deepcopy(config_dict) # Delete all the smart scan kwargs - del broken_config["things"]["/smart_scan/"]["kwargs"] + del broken_config["things"]["smart_scan"]["kwargs"] # Creates an Error with pytest.raises(RuntimeError): ofm_server._get_scans_dir(broken_config) # Same thing should happen if just the scans_folder key is deleted broken_config = deepcopy(config_dict) - del broken_config["things"]["/smart_scan/"]["kwargs"] + del broken_config["things"]["smart_scan"]["kwargs"] # Creates an Error with pytest.raises(RuntimeError): ofm_server._get_scans_dir(broken_config) diff --git a/tests/test_stack.py b/tests/test_stack.py index 3f92aedc..9b2f39c0 100644 --- a/tests/test_stack.py +++ b/tests/test_stack.py @@ -270,7 +270,7 @@ def autofocus_thing(): autofocus_thing = AutofocusThing() with tempfile.TemporaryDirectory() as tmpdir: server = lt.ThingServer(settings_folder=tmpdir) - server.add_thing(autofocus_thing, "/autofocus/") + server.add_thing(autofocus_thing, "autofocus") with TestClient(server.app): yield autofocus_thing diff --git a/tests/test_stage.py b/tests/test_stage.py index a95d0b33..e2fa0163 100644 --- a/tests/test_stage.py +++ b/tests/test_stage.py @@ -41,7 +41,7 @@ def thing_server(dummy_stage): """Yield a server with a very basic configuration.""" with tempfile.TemporaryDirectory() as tmpdir: server = lt.ThingServer(settings_folder=tmpdir) - server.add_thing(dummy_stage, "/stage/") + server.add_thing(dummy_stage, "stage") yield server @@ -49,7 +49,7 @@ def thing_server(dummy_stage): def stage_client(thing_server): """Yield a labthings ThingClient for the stage.""" with TestClient(thing_server.app) as test_client: - yield lt.ThingClient.from_url("/stage/", client=test_client) + yield lt.ThingClient.from_url("stage", client=test_client) def test_override_base_movement(): diff --git a/tests/test_stage_measure.py b/tests/test_stage_measure.py index f2a8205b..7a992756 100644 --- a/tests/test_stage_measure.py +++ b/tests/test_stage_measure.py @@ -158,7 +158,7 @@ def rom_thing(example_rom_data) -> stage_measure.RangeofMotionThing: with tempfile.TemporaryDirectory() as tmpdir: server = lt.ThingServer(settings_folder=tmpdir) - server.add_thing(rom_thing, "/rom_thing/") + server.add_thing(rom_thing, "rom_thing") with TestClient(server.app): yield rom_thing