From 1ba799de227ec593b6dcb62b76c1961e4516b302 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Thu, 28 Nov 2024 17:35:56 +0000 Subject: [PATCH] Migrate to new Blob type and update imports This now uses the latest version of labthings-fastapi. --- pyproject.toml | 4 +-- .../things/camera/__init__.py | 27 ++++++++++++++++--- .../things/camera/opencv.py | 7 +---- .../things/settings_manager.py | 3 ++- .../things/smart_scan.py | 9 +++---- .../things/stitching.py | 5 ++-- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7c335a84..05ec3ba5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "labthings-fastapi[server] == 0.0.6", + "labthings-fastapi[server] == 0.0.7", "labthings-sangaboard", "camera-stage-mapping ~= 0.1.6", "numpy ~= 1.20", @@ -31,7 +31,7 @@ dev = [ "labthings-fastapi[dev]", ] pi = [ - "labthings-picamera2 == 0.0.1-dev1", + "labthings-picamera2 == 0.0.1-dev2", ] [project.scripts] diff --git a/src/openflexure_microscope_server/things/camera/__init__.py b/src/openflexure_microscope_server/things/camera/__init__.py index 14e386fa..43d4694d 100644 --- a/src/openflexure_microscope_server/things/camera/__init__.py +++ b/src/openflexure_microscope_server/things/camera/__init__.py @@ -14,15 +14,35 @@ from labthings_fastapi.decorators import thing_action, thing_property from labthings_fastapi.dependencies.metadata import GetThingStates from labthings_fastapi.dependencies.blocking_portal import BlockingPortal from labthings_fastapi.outputs.mjpeg_stream import MJPEGStreamDescriptor -from labthings_fastapi.outputs.blob import BlobOutput +from labthings_fastapi.outputs.blob import blob_type from labthings_fastapi.types.numpy import NDArray -class JPEGBlob(BlobOutput): - media_type = "image/jpeg" +JPEGBlob = blob_type("image/jpeg") + +class CameraMeta: + def __subclasscheck__(cls, C): + """Override Python's default behaviour and use duck typing""" + print(f"Checking if {C} is a camera...") + for action in ["snap_image", "capture_array", "capture_jpeg", "grab_jpeg", "grab_jpeg_size"]: + a = getattr(C, action, None) + if not callable(a): + return False + for prop in ["stream_active"]: + if not hasattr(C, prop): + return False + for k in ["mjpeg_stream", "lores_mjpeg_stream"]: + stream = getattr(C, k) + if not isinstance(stream, MJPEGStreamDescriptor): + return False + return True + + def __instancecheck__(cls, I): + return cls.__subclasscheck__(I) class Camera(Thing): + __metaclass__ = CameraMeta """A Thing representing a camera""" def __enter__(self): @@ -104,3 +124,4 @@ class Camera(Thing): self.lores_mjpeg_stream if stream_name == "lores" else self.mjpeg_stream ) return portal.call(stream.next_frame_size) + diff --git a/src/openflexure_microscope_server/things/camera/opencv.py b/src/openflexure_microscope_server/things/camera/opencv.py index bc7641cd..7285d35c 100644 --- a/src/openflexure_microscope_server/things/camera/opencv.py +++ b/src/openflexure_microscope_server/things/camera/opencv.py @@ -19,14 +19,9 @@ from labthings_fastapi.utilities import get_blocking_portal from labthings_fastapi.decorators import thing_action, thing_property from labthings_fastapi.dependencies.metadata import GetThingStates from labthings_fastapi.outputs.mjpeg_stream import MJPEGStreamDescriptor -from labthings_fastapi.outputs.blob import BlobOutput from labthings_fastapi.types.numpy import NDArray -from . import Camera - - -class JPEGBlob(BlobOutput): - media_type = "image/jpeg" +from . import Camera, JPEGBlob class OpenCVCamera(Camera): diff --git a/src/openflexure_microscope_server/things/settings_manager.py b/src/openflexure_microscope_server/things/settings_manager.py index 6221e398..b6e3794c 100644 --- a/src/openflexure_microscope_server/things/settings_manager.py +++ b/src/openflexure_microscope_server/things/settings_manager.py @@ -13,7 +13,8 @@ from fastapi import Depends, HTTPException, Request from labthings_fastapi.dependencies.metadata import GetThingStates from labthings_fastapi.thing import Thing from labthings_fastapi.decorators import thing_action, thing_property -from labthings_fastapi.server import find_thing_server, ThingServer +from labthings_fastapi.dependencies.thing_server import find_thing_server +from labthings_fastapi.server import ThingServer from labthings_fastapi.dependencies.invocation import InvocationLogger diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 3ffa976b..a05372d3 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -27,7 +27,7 @@ from labthings_fastapi.dependencies.metadata import GetThingStates from labthings_fastapi.dependencies.thing import direct_thing_client_dependency from labthings_fastapi.dependencies.invocation import CancelHook, InvocationLogger, InvocationCancelledError from labthings_fastapi.decorators import thing_action, thing_property, fastapi_endpoint -from labthings_fastapi.outputs.blob import BlobOutput +from labthings_fastapi.outputs.blob import blob_type from .camera import Camera from .stage import Stage from openflexure_microscope_server.things.autofocus import AutofocusThing @@ -335,11 +335,8 @@ DOWNLOADABLE_SCAN_FILES = ( "images.zip", ) -class JPEGBlob(BlobOutput): - media_type = "image/jpeg" - -class ZipBlob(BlobOutput): - media_type = "application/zip" +JPEGBlob = blob_type("image/jpeg") +ZipBlob = blob_type("application/zip") class SmartScanThing(Thing): def __init__(self, path_to_openflexure_stitch: str): diff --git a/src/openflexure_microscope_server/things/stitching.py b/src/openflexure_microscope_server/things/stitching.py index b2911a2d..03b421c3 100644 --- a/src/openflexure_microscope_server/things/stitching.py +++ b/src/openflexure_microscope_server/things/stitching.py @@ -6,15 +6,14 @@ from labthings_fastapi.thing import Thing from labthings_fastapi.dependencies.raw_thing import raw_thing_dependency from labthings_fastapi.dependencies.invocation import InvocationLogger from labthings_fastapi.decorators import thing_action -from labthings_fastapi.outputs.blob import BlobOutput +from labthings_fastapi.outputs.blob import blob_type from .smart_scan import SmartScanThing SmartScanDep = raw_thing_dependency(SmartScanThing) -class JPEGBlob(BlobOutput): - media_type = "image/jpeg" +JPEGBlob = blob_type("image/jpeg") class Stitcher(Thing):