Static type analysis
This commit is contained in:
parent
3aebb8bead
commit
7866ec0f47
63 changed files with 1825 additions and 2722 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import io
|
||||
import logging
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from flask import send_file
|
||||
from labthings import Schema, fields, find_component
|
||||
|
|
@ -42,12 +43,14 @@ class CaptureAPI(ActionView):
|
|||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
|
||||
resize = args.get("resize", None)
|
||||
if resize:
|
||||
resize = (
|
||||
int(resize["width"]),
|
||||
int(resize["height"]),
|
||||
resize_dict: Optional[Dict[str, int]] = args.get("resize", None)
|
||||
if resize_dict:
|
||||
resize: Optional[Tuple[int, int]] = (
|
||||
int(resize_dict["width"]),
|
||||
int(resize_dict["height"]),
|
||||
) # Convert dict to tuple
|
||||
else:
|
||||
resize = None
|
||||
|
||||
# Explicitally acquire lock (prevents empty files being created if lock is unavailable)
|
||||
with microscope.camera.lock:
|
||||
|
|
@ -76,12 +79,14 @@ class RAMCaptureAPI(ActionView):
|
|||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
|
||||
resize = args.get("resize", None)
|
||||
if resize:
|
||||
resize = (
|
||||
int(resize["width"]),
|
||||
int(resize["height"]),
|
||||
resize_dict: Optional[Dict[str, int]] = args.get("resize", None)
|
||||
if resize_dict:
|
||||
resize: Optional[Tuple[int, int]] = (
|
||||
int(resize_dict["width"]),
|
||||
int(resize_dict["height"]),
|
||||
) # Convert dict to tuple
|
||||
else:
|
||||
resize = None
|
||||
|
||||
# Open a BytesIO stream to be destroyed once request has returned
|
||||
with microscope.camera.lock, io.BytesIO() as stream:
|
||||
|
|
@ -113,15 +118,18 @@ class GPUPreviewStartAPI(ActionView):
|
|||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
|
||||
window = args.get("window")
|
||||
logging.debug(window)
|
||||
# Get window argument from request
|
||||
window_arg = args.get("window")
|
||||
logging.debug(window_arg)
|
||||
|
||||
if len(window) != 4:
|
||||
fullscreen = True
|
||||
window = None
|
||||
else:
|
||||
# Default to no window
|
||||
fullscreen: bool = True
|
||||
window: Optional[Tuple[int, int, int, int]] = None
|
||||
|
||||
# If request argument is well formed, use that
|
||||
if len(window_arg) == 4:
|
||||
fullscreen = False
|
||||
window = [int(w) for w in window]
|
||||
window = (int(w) for w in window_arg)
|
||||
|
||||
microscope.camera.start_preview(fullscreen=fullscreen, window=window)
|
||||
return microscope.state
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
from typing import List, Tuple
|
||||
|
||||
from labthings import fields, find_component
|
||||
from labthings.views import ActionView
|
||||
|
|
@ -24,11 +25,11 @@ class MoveStageAPI(ActionView):
|
|||
|
||||
# Handle absolute positioning (calculate a relative move from current position and target)
|
||||
if (args.get("absolute")) and (microscope.stage): # Only if stage exists
|
||||
target_position = axes_to_array(args, ["x", "y", "z"])
|
||||
target_position: List[int] = axes_to_array(args, ["x", "y", "z"])
|
||||
logging.debug("TARGET: %s", (target_position))
|
||||
position = [
|
||||
position: Tuple[int, int, int] = (
|
||||
target_position[i] - microscope.stage.position[i] for i in range(3)
|
||||
]
|
||||
)
|
||||
logging.debug("DELTA: %s", (position))
|
||||
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import subprocess
|
|||
from labthings.views import ActionView
|
||||
|
||||
|
||||
def is_raspberrypi():
|
||||
def is_raspberrypi() -> bool:
|
||||
"""
|
||||
Checks if Raspberry Pi.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -34,17 +34,18 @@ class LSTImageProperty(PropertyView):
|
|||
logging.warning("PiCamera.lens_shading_table returned as None")
|
||||
return ("", 204)
|
||||
else:
|
||||
# Get the LST Numpy array from the camera's memoryview
|
||||
lst = np.asarray(microscope.camera.camera.lens_shading_table)
|
||||
# R next to G1
|
||||
# Create array of R next to G1
|
||||
top = np.concatenate(lst[:2], axis=1)
|
||||
# G2 next to B
|
||||
# Create array of G2 next to B
|
||||
bottom = np.concatenate(lst[2:], axis=1)
|
||||
# Combined into a 2x2 grid of greyscale images
|
||||
# Create combined array of 2x2 grid of greyscale images
|
||||
all_channels = np.concatenate((top, bottom), axis=0)
|
||||
# Create a PNG
|
||||
img_bytes = BytesIO()
|
||||
img_bytes: BytesIO = BytesIO()
|
||||
Image.fromarray(np.uint8(all_channels), "L").save(img_bytes, "PNG")
|
||||
img_bytes.seek(0)
|
||||
# Return the image
|
||||
fname = f"lst-{datetime.date.today().isoformat()}.png"
|
||||
fname: str = f"lst-{datetime.date.today().isoformat()}.png"
|
||||
return send_file(img_bytes, as_attachment=True, attachment_filename=fname)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
from io import BytesIO
|
||||
from typing import List, Optional, Union
|
||||
from uuid import UUID
|
||||
|
||||
from flask import abort, redirect, request, send_file, url_for
|
||||
from labthings import Schema, fields, find_component
|
||||
from labthings.marshalling import marshal_with, use_args
|
||||
|
|
@ -6,6 +10,7 @@ from labthings.views import PropertyView, View
|
|||
from marshmallow import pre_dump
|
||||
|
||||
from openflexure_microscope.api.utilities import get_bool
|
||||
from openflexure_microscope.captures import CaptureObject
|
||||
|
||||
# SCHEMAS
|
||||
|
||||
|
|
@ -61,10 +66,10 @@ class CaptureSchema(ImageSchema):
|
|||
links = fields.Dict()
|
||||
|
||||
@pre_dump
|
||||
def generate_links(self, data, **_):
|
||||
def generate_links(self, data: Union[dict, CaptureObject], **_):
|
||||
if isinstance(data, dict):
|
||||
capture_id = data.get("id")
|
||||
capture_name = data.get("name")
|
||||
capture_id: Optional[Union[str, UUID]] = data.get("id")
|
||||
capture_name: Optional[str] = data.get("name")
|
||||
else:
|
||||
capture_id = data.id
|
||||
capture_name = data.name
|
||||
|
|
@ -102,7 +107,7 @@ class CaptureSchema(ImageSchema):
|
|||
if isinstance(data, dict):
|
||||
data["links"] = links
|
||||
else:
|
||||
data.links = links
|
||||
setattr(data, "links", links)
|
||||
|
||||
return data
|
||||
|
||||
|
|
@ -129,7 +134,7 @@ class CaptureList(PropertyView):
|
|||
List all image captures
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
image_list = microscope.captures.images.values()
|
||||
image_list: List[CaptureObject] = microscope.captures.images.values()
|
||||
return image_list
|
||||
|
||||
|
||||
|
|
@ -142,7 +147,7 @@ class CaptureView(View):
|
|||
Description of a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
|
@ -154,7 +159,7 @@ class CaptureView(View):
|
|||
Delete a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
|
@ -171,17 +176,17 @@ class CaptureDownload(View):
|
|||
tags = ["captures"]
|
||||
responses = {200: {"content_type": "image/jpeg"}}
|
||||
|
||||
def get(self, id_, filename):
|
||||
def get(self, id_, filename: Optional[str]):
|
||||
"""
|
||||
Image data for a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
||||
thumbnail = get_bool(request.args.get("thumbnail"))
|
||||
thumbnail: bool = get_bool(request.args.get("thumbnail", ""))
|
||||
|
||||
# If no filename is specified, redirect to the capture's currently set filename
|
||||
if not filename:
|
||||
|
|
@ -189,7 +194,7 @@ class CaptureDownload(View):
|
|||
url_for(
|
||||
"DownloadAPI",
|
||||
id=id_,
|
||||
filename=capture_obj.filename,
|
||||
filename=capture_obj.name,
|
||||
thumbnail=thumbnail,
|
||||
),
|
||||
code=307,
|
||||
|
|
@ -197,10 +202,14 @@ class CaptureDownload(View):
|
|||
|
||||
# Download the image data using the requested filename
|
||||
if thumbnail:
|
||||
img = capture_obj.thumbnail
|
||||
img: Optional[BytesIO] = capture_obj.thumbnail
|
||||
else:
|
||||
img = capture_obj.data
|
||||
|
||||
# If we can't get any data, return 404
|
||||
if not img:
|
||||
return abort(404) # 404 Not Found
|
||||
|
||||
return send_file(img, mimetype="image/jpeg")
|
||||
|
||||
|
||||
|
|
@ -212,7 +221,7 @@ class CaptureTags(View):
|
|||
Get tags associated with a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
|
@ -225,7 +234,7 @@ class CaptureTags(View):
|
|||
Add tags to a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
|
@ -240,7 +249,7 @@ class CaptureTags(View):
|
|||
Delete tags from a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
|
@ -259,7 +268,7 @@ class CaptureAnnotations(View):
|
|||
Get annotations associated with a single image capture
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
capture_obj = microscope.captures.images.get(id_)
|
||||
capture_obj: Optional[CaptureObject] = microscope.captures.images.get(id_)
|
||||
|
||||
if not capture_obj:
|
||||
return abort(404) # 404 Not Found
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
from typing import Any, List
|
||||
|
||||
from flask import abort
|
||||
from labthings import fields, find_component
|
||||
|
|
@ -35,29 +36,29 @@ class NestedSettingsProperty(View):
|
|||
tags = ["properties"]
|
||||
responses = {404: {"description": "Settings key cannot be found"}}
|
||||
|
||||
def get(self, route):
|
||||
def get(self, route: str):
|
||||
"""
|
||||
Show a nested section of the current microscope settings
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
keys = route.split("/")
|
||||
keys: List[str] = route.split("/")
|
||||
|
||||
try:
|
||||
value = get_by_path(microscope.read_settings(), keys)
|
||||
value: Any = get_by_path(microscope.read_settings(), keys)
|
||||
except KeyError:
|
||||
return abort(404)
|
||||
|
||||
return value
|
||||
|
||||
@use_args(fields.Dict())
|
||||
def put(self, args, route):
|
||||
def put(self, args: Any, route: str):
|
||||
"""
|
||||
Update a nested section of the current microscope settings
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
keys = route.split("/")
|
||||
keys: List[str] = route.split("/")
|
||||
|
||||
dictionary = create_from_path(keys)
|
||||
dictionary: dict = create_from_path(keys)
|
||||
set_by_path(dictionary, keys, args)
|
||||
|
||||
microscope.update_settings(dictionary)
|
||||
|
|
@ -84,10 +85,10 @@ class NestedStateProperty(View):
|
|||
Show a nested section of the current microscope state
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
keys = route.split("/")
|
||||
keys: List[str] = route.split("/")
|
||||
|
||||
try:
|
||||
value = get_by_path(microscope.state, keys)
|
||||
value: Any = get_by_path(microscope.state, keys)
|
||||
except KeyError:
|
||||
return abort(404)
|
||||
|
||||
|
|
@ -112,10 +113,10 @@ class NestedConfigurationProperty(View):
|
|||
Show a nested section of the current microscope state
|
||||
"""
|
||||
microscope = find_component("org.openflexure.microscope")
|
||||
keys = route.split("/")
|
||||
keys: List[str] = route.split("/")
|
||||
|
||||
try:
|
||||
value = get_by_path(microscope.configuration, keys)
|
||||
value: Any = get_by_path(microscope.configuration, keys)
|
||||
except KeyError:
|
||||
return abort(404)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ def gen(camera):
|
|||
"""Video streaming generator function."""
|
||||
while True:
|
||||
# the obtained frame is a jpeg
|
||||
frame = camera.stream.getframe()
|
||||
frame: bytes = camera.stream.getframe()
|
||||
|
||||
yield (b"--frame\r\n" b"Content-Type: image/jpeg\r\n\r\n" + frame + b"\r\n")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue