Improve __enter__ typing for things
This commit is contained in:
parent
d52548cc13
commit
afbc00acef
6 changed files with 19 additions and 20 deletions
|
|
@ -15,7 +15,7 @@ import tempfile
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any, Literal, Mapping, Optional, Tuple
|
from typing import Any, Literal, Mapping, Optional, Self, Tuple
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import piexif
|
import piexif
|
||||||
|
|
@ -180,7 +180,7 @@ class BaseCamera(lt.Thing):
|
||||||
}
|
}
|
||||||
self._detector_name = "Channel Deviations (LUV)"
|
self._detector_name = "Channel Deviations (LUV)"
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> Self:
|
||||||
"""Open hardware connection when the Thing context manager is opened."""
|
"""Open hardware connection when the Thing context manager is opened."""
|
||||||
raise NotImplementedError("CameraThings must define their own __enter__ method")
|
raise NotImplementedError("CameraThings must define their own __enter__ method")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ from __future__ import annotations
|
||||||
import logging
|
import logging
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Literal, Optional
|
from typing import Literal, Optional, Self
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
@ -39,7 +39,7 @@ class OpenCVCamera(BaseCamera):
|
||||||
self._capture_thread: Optional[Thread] = None
|
self._capture_thread: Optional[Thread] = None
|
||||||
self._capture_enabled = False
|
self._capture_enabled = False
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> Self:
|
||||||
"""Start the capture thread when the Thing context manager is opened."""
|
"""Start the capture thread when the Thing context manager is opened."""
|
||||||
self.cap = cv2.VideoCapture(self.camera_index)
|
self.cap = cv2.VideoCapture(self.camera_index)
|
||||||
self._capture_enabled = True
|
self._capture_enabled = True
|
||||||
|
|
@ -59,7 +59,8 @@ class OpenCVCamera(BaseCamera):
|
||||||
"""
|
"""
|
||||||
if self.stream_active:
|
if self.stream_active:
|
||||||
self._capture_enabled = False
|
self._capture_enabled = False
|
||||||
self._capture_thread.join()
|
if self._capture_thread is not None:
|
||||||
|
self._capture_thread.join()
|
||||||
self.cap.release()
|
self.cap.release()
|
||||||
|
|
||||||
@lt.property
|
@lt.property
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import time
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Annotated, Any, Iterator, Literal, Mapping, Optional
|
from typing import Annotated, Any, Iterator, Literal, Mapping, Optional, Self
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from picamera2 import Picamera2
|
from picamera2 import Picamera2
|
||||||
|
|
@ -148,7 +148,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
f"are {SUPPORTED_CAMS_SENSOR_INFO.keys()}."
|
f"are {SUPPORTED_CAMS_SENSOR_INFO.keys()}."
|
||||||
)
|
)
|
||||||
self._sensor_info = SUPPORTED_CAMS_SENSOR_INFO[camera_board]
|
self._sensor_info = SUPPORTED_CAMS_SENSOR_INFO[camera_board]
|
||||||
self._picamera_lock = None
|
self._picamera_lock = RLock()
|
||||||
self._picamera = None
|
self._picamera = None
|
||||||
|
|
||||||
# Load the tuning file for the specified sensor mode.
|
# Load the tuning file for the specified sensor mode.
|
||||||
|
|
@ -340,10 +340,7 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
:raises PicameraModelError: If check_sensor_model is True and the real
|
:raises PicameraModelError: If check_sensor_model is True and the real
|
||||||
camera sensor model doesn't match the expected sensor model.
|
camera sensor model doesn't match the expected sensor model.
|
||||||
"""
|
"""
|
||||||
if self._picamera_lock is not None:
|
with self._picamera_lock, tempfile.NamedTemporaryFile("w") as tuning_file:
|
||||||
# Don't close the camera if it's in use
|
|
||||||
self._picamera_lock.acquire()
|
|
||||||
with tempfile.NamedTemporaryFile("w") as tuning_file:
|
|
||||||
json.dump(self.tuning, tuning_file)
|
json.dump(self.tuning, tuning_file)
|
||||||
tuning_file.flush() # but leave it open as closing it will delete it
|
tuning_file.flush() # but leave it open as closing it will delete it
|
||||||
os.environ["LIBCAMERA_RPI_TUNING_FILE"] = tuning_file.name
|
os.environ["LIBCAMERA_RPI_TUNING_FILE"] = tuning_file.name
|
||||||
|
|
@ -371,9 +368,8 @@ class StreamingPiCamera2(BaseCamera):
|
||||||
f"Wrong Picamera model. Expecting {self._sensor_info.sensor_model}, "
|
f"Wrong Picamera model. Expecting {self._sensor_info.sensor_model}, "
|
||||||
f"but found {hw_sensor_model}."
|
f"but found {hw_sensor_model}."
|
||||||
)
|
)
|
||||||
self._picamera_lock = RLock()
|
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> Self:
|
||||||
"""Start streaming when the Thing context manager is opened.
|
"""Start streaming when the Thing context manager is opened.
|
||||||
|
|
||||||
This opens the picamera connection, initialises the camera, sets the
|
This opens the picamera connection, initialises the camera, sets the
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import logging
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Literal, Optional
|
from typing import Literal, Optional, Self
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PIL import Image, ImageFilter
|
from PIL import Image, ImageFilter
|
||||||
|
|
@ -239,7 +239,7 @@ class SimulatedCamera(BaseCamera):
|
||||||
pos = {"x": 0, "y": 0, "z": 0}
|
pos = {"x": 0, "y": 0, "z": 0}
|
||||||
return self.generate_image((pos["y"], pos["x"], pos["z"]))
|
return self.generate_image((pos["y"], pos["x"], pos["z"]))
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> Self:
|
||||||
"""Start the capture thread when the Thing context manager is opened."""
|
"""Start the capture thread when the Thing context manager is opened."""
|
||||||
self.start_streaming()
|
self.start_streaming()
|
||||||
return self
|
return self
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
||||||
import time
|
import time
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional, Self
|
||||||
|
|
||||||
import labthings_fastapi as lt
|
import labthings_fastapi as lt
|
||||||
|
|
||||||
|
|
@ -36,9 +36,10 @@ class DummyStage(BaseStage):
|
||||||
self.step_time = step_time
|
self.step_time = step_time
|
||||||
self.instantaneous_position = self._hardware_position
|
self.instantaneous_position = self._hardware_position
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> Self:
|
||||||
"""Register the stage position when the Thing context manager is opened."""
|
"""Register the stage position when the Thing context manager is opened."""
|
||||||
self.instantaneous_position = self._hardware_position
|
self.instantaneous_position = self._hardware_position
|
||||||
|
return self
|
||||||
|
|
||||||
def __exit__(
|
def __exit__(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from collections.abc import Mapping
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any, Iterator, Literal, Optional
|
from typing import Any, Iterator, Literal, Optional, Self
|
||||||
|
|
||||||
import semver
|
import semver
|
||||||
|
|
||||||
|
|
@ -33,7 +33,7 @@ class SangaboardThing(BaseStage):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
thing_server_interface: lt.ThingServerInterface,
|
thing_server_interface: lt.ThingServerInterface,
|
||||||
port: str = None,
|
port: Optional[str] = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialise SangaboardThing.
|
"""Initialise SangaboardThing.
|
||||||
|
|
@ -53,13 +53,14 @@ class SangaboardThing(BaseStage):
|
||||||
self._sangaboard_lock = threading.RLock()
|
self._sangaboard_lock = threading.RLock()
|
||||||
super().__init__(thing_server_interface, **kwargs)
|
super().__init__(thing_server_interface, **kwargs)
|
||||||
|
|
||||||
def __enter__(self) -> None:
|
def __enter__(self) -> Self:
|
||||||
"""Connect to the sangaboard when the Thing context manager is opened."""
|
"""Connect to the sangaboard when the Thing context manager is opened."""
|
||||||
self._sangaboard = sangaboard.Sangaboard(**self.sangaboard_kwargs)
|
self._sangaboard = sangaboard.Sangaboard(**self.sangaboard_kwargs)
|
||||||
with self.sangaboard() as sb:
|
with self.sangaboard() as sb:
|
||||||
sb.query("blocking_moves false")
|
sb.query("blocking_moves false")
|
||||||
self.check_firmware()
|
self.check_firmware()
|
||||||
self.update_position()
|
self.update_position()
|
||||||
|
return self
|
||||||
|
|
||||||
def __exit__(
|
def __exit__(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue