Skip to content

Commit

Permalink
(#826) Fix, or ignore and note, typing errors (#830)
Browse files Browse the repository at this point in the history
* (#826) fix or ignore and note typing errors

* (#826) update ophyd-async dependency

* (#826) put upper bound on ophyd-async for safety

* (#826) make backlight conform to Moveable
  • Loading branch information
dperl-dls authored Oct 9, 2024
1 parent 49fd0a5 commit 08268c3
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 56 deletions.
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ description = "Ophyd devices and other utils that could be used across DLS beaml
dependencies = [
"click",
"ophyd",
"ophyd-async>=0.6,<0.7",
"ophyd-async>=0.7.0a1,<0.8",
"bluesky",
"pyepics",
"dataclasses-json",
Expand All @@ -24,10 +24,10 @@ dependencies = [
"requests",
"graypy",
"pydantic>=2.0",
"opencv-python-headless", # For pin-tip detection.
"aioca", # Required for CA support with ophyd-async.
"p4p", # Required for PVA support with ophyd-async.
"numpy<2.0", # Unpin when https://github.com/bluesky/ophyd-async/issues/387 resolved
"opencv-python-headless", # For pin-tip detection.
"aioca", # Required for CA support with ophyd-async.
"p4p", # Required for PVA support with ophyd-async.
"numpy<2.0", # Unpin when https://github.com/bluesky/ophyd-async/issues/387 resolved
"aiofiles",
"aiohttp",
"redis",
Expand Down
11 changes: 6 additions & 5 deletions src/dodal/devices/backlight.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from asyncio import sleep
from enum import Enum

from bluesky.protocols import Movable
from ophyd_async.core import AsyncStatus, StandardReadable
from ophyd_async.epics.signal import epics_signal_rw

Expand All @@ -15,7 +16,7 @@ class BacklightPosition(str, Enum):
OUT = "Out"


class Backlight(StandardReadable):
class Backlight(StandardReadable, Movable):
"""Simple device to trigger the pneumatic in/out."""

TIME_TO_MOVE_S = 1 # Tested using a stopwatch on the beamline 09/2024
Expand All @@ -29,7 +30,7 @@ def __init__(self, prefix: str, name: str = "") -> None:
super().__init__(name)

@AsyncStatus.wrap
async def set(self, position: BacklightPosition):
async def set(self, value: BacklightPosition):
"""This setter will turn the backlight on when we move it in to the beam and off
when we move it out.
Expand All @@ -38,10 +39,10 @@ async def set(self, position: BacklightPosition):
to move completely in/out so we sleep here to simulate this.
"""
old_position = await self.position.get_value()
await self.position.set(position)
if position == BacklightPosition.OUT:
await self.position.set(value)
if value == BacklightPosition.OUT:
await self.power.set(BacklightPower.OFF)
else:
await self.power.set(BacklightPower.ON)
if old_position != position:
if old_position != value:
await sleep(self.TIME_TO_MOVE_S)
10 changes: 5 additions & 5 deletions src/dodal/devices/i24/dual_backlight.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def __init__(self, prefix: str, name: str = "") -> None:
super().__init__(name)

@AsyncStatus.wrap
async def set(self, position: BacklightPositions):
await self.pos_level.set(position, wait=True)
async def set(self, value: BacklightPositions):
await self.pos_level.set(value, wait=True)


class DualBacklight(StandardReadable):
Expand All @@ -53,9 +53,9 @@ def __init__(self, prefix: str, name: str = "") -> None:
super().__init__(name)

@AsyncStatus.wrap
async def set(self, position: BacklightPositions):
await self.backlight_position.set(position)
if position == BacklightPositions.OUT:
async def set(self, value: BacklightPositions):
await self.backlight_position.set(value)
if value == BacklightPositions.OUT:
await self.backlight_state.set(LEDStatus.OFF, wait=True)
else:
await self.backlight_state.set(LEDStatus.ON, wait=True)
4 changes: 2 additions & 2 deletions src/dodal/devices/smargon.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ def __init__(self, name: str = "", prefix: str = ""):
super().__init__(name)

@AsyncStatus.wrap
async def set(self, pos: StubPosition):
if pos == StubPosition.CURRENT_AS_CENTER:
async def set(self, value: StubPosition):
if value == StubPosition.CURRENT_AS_CENTER:
await self.center_at_current_position.set(1)
smargon = cast(Smargon, self.parent)
await wait_for_value(
Expand Down
4 changes: 2 additions & 2 deletions src/dodal/devices/tetramm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from bluesky.protocols import Hints
from ophyd_async.core import (
DatasetDescriber,
DetectorControl,
DetectorController,
DetectorTrigger,
Device,
PathProvider,
Expand Down Expand Up @@ -80,7 +80,7 @@ def __init__(
super().__init__(name=name)


class TetrammController(DetectorControl):
class TetrammController(DetectorController):
"""Controller for a TetrAMM current monitor
Attributes:
Expand Down
2 changes: 1 addition & 1 deletion src/dodal/devices/util/adjuster_plans.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ def lookup_table_adjuster(
def adjust(group=None) -> Generator[Msg, None, None]:
setpoint = lookup_table(input)
LOGGER.info(f"lookup_table_adjuster setting {output_device.name} to {setpoint}")
yield from bps.abs_set(output_device, setpoint, group=group)
yield from bps.abs_set(output_device, setpoint, group=group) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827

return adjust
17 changes: 10 additions & 7 deletions src/dodal/plans/motor_util_plans.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import uuid
from collections.abc import Generator
from typing import Any, TypeVar
from typing import Any, TypeVar, cast

from bluesky import plan_stubs as bps
from bluesky.preprocessors import finalize_wrapper, pchain
Expand All @@ -9,13 +9,14 @@
from ophyd_async.epics.motor import Motor

from dodal.common import MsgGenerator
from dodal.utils import MovableReadable

AnyDevice = TypeVar("AnyDevice", bound=Device)
MovableReadableDevice = TypeVar("MovableReadableDevice", bound=MovableReadable)


class MoveTooLarge(Exception):
def __init__(
self, axis: Device, maximum_move: float, position: float, *args: object
self, axis: MovableReadable, maximum_move: float, position: float, *args: object
) -> None:
self.axis = axis
self.maximum_move = maximum_move
Expand All @@ -24,10 +25,10 @@ def __init__(


def _check_and_cache_values(
devices_and_positions: dict[AnyDevice, float],
devices_and_positions: dict[MovableReadableDevice, float],
smallest_move: float,
maximum_move: float,
) -> Generator[Msg, Any, dict[AnyDevice, float]]:
) -> Generator[Msg, Any, dict[MovableReadableDevice, float]]:
"""Caches the positions of all Motors on specified device if they are within
smallest_move of home_position. Throws MoveTooLarge if they are outside maximum_move
of the home_position
Expand All @@ -51,7 +52,9 @@ def home_and_reset_wrapper(
wait_for_all: bool = True,
) -> MsgGenerator:
home_positions = {
axis: 0.0 for _, axis in device.children() if isinstance(axis, Motor)
cast(MovableReadable, axis): 0.0
for _, axis in device.children()
if isinstance(axis, Motor)
}
return move_and_reset_wrapper(
plan, home_positions, smallest_move, maximum_move, group, wait_for_all
Expand All @@ -60,7 +63,7 @@ def home_and_reset_wrapper(

def move_and_reset_wrapper(
plan: MsgGenerator,
device_and_positions: dict[AnyDevice, float],
device_and_positions: dict[MovableReadable, float],
smallest_move: float,
maximum_move: float,
group: str | None = None,
Expand Down
7 changes: 7 additions & 0 deletions src/dodal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
from types import ModuleType
from typing import (
Any,
Protocol,
TypeGuard,
TypeVar,
runtime_checkable,
)

from bluesky.protocols import (
Expand Down Expand Up @@ -62,6 +64,11 @@
Triggerable,
]


@runtime_checkable
class MovableReadable(Movable, Readable, Protocol): ...


AnyDevice: TypeAlias = OphydV1Device | OphydV2Device
V1DeviceFactory: TypeAlias = Callable[..., OphydV1Device]
V2DeviceFactory: TypeAlias = Callable[..., OphydV2Device]
Expand Down
4 changes: 2 additions & 2 deletions system_tests/test_aperturescatterguard_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ def monitor_and_moves():
yield from bps.open_run()
yield from bps.monitor(ap_sg.aperture.y.motor_done_move, name="ap_y")
yield from bps.monitor(ap_sg.scatterguard.y.motor_done_move, name="sg_y")
yield from bps.mv(ap_sg, pos1)
yield from bps.mv(ap_sg, pos2)
yield from bps.mv(ap_sg, pos1) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.mv(ap_sg, pos2) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.close_run()

RE(monitor_and_moves())
Expand Down
16 changes: 8 additions & 8 deletions system_tests/test_oav_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@

def take_snapshot_with_grid(oav: OAV, snapshot_filename, snapshot_directory):
oav.wait_for_connection()
yield from bps.abs_set(oav.grid_snapshot.top_left_x, TEST_GRID_TOP_LEFT_X)
yield from bps.abs_set(oav.grid_snapshot.top_left_y, TEST_GRID_TOP_LEFT_Y)
yield from bps.abs_set(oav.grid_snapshot.box_width, TEST_GRID_BOX_WIDTH)
yield from bps.abs_set(oav.grid_snapshot.num_boxes_x, TEST_GRID_NUM_BOXES_X)
yield from bps.abs_set(oav.grid_snapshot.num_boxes_y, TEST_GRID_NUM_BOXES_Y)
yield from bps.abs_set(oav.grid_snapshot.filename, snapshot_filename)
yield from bps.abs_set(oav.grid_snapshot.directory, snapshot_directory)
yield from bps.trigger(oav.grid_snapshot, wait=True)
yield from bps.abs_set(oav.grid_snapshot.top_left_x, TEST_GRID_TOP_LEFT_X) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.abs_set(oav.grid_snapshot.top_left_y, TEST_GRID_TOP_LEFT_Y) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.abs_set(oav.grid_snapshot.box_width, TEST_GRID_BOX_WIDTH) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.abs_set(oav.grid_snapshot.num_boxes_x, TEST_GRID_NUM_BOXES_X) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.abs_set(oav.grid_snapshot.num_boxes_y, TEST_GRID_NUM_BOXES_Y) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.abs_set(oav.grid_snapshot.filename, snapshot_filename) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.abs_set(oav.grid_snapshot.directory, snapshot_directory) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
yield from bps.trigger(oav.grid_snapshot, wait=True) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827


# We need to find a better way of integrating this, see https://github.com/DiamondLightSource/mx-bluesky/issues/183
Expand Down
2 changes: 1 addition & 1 deletion tests/devices/unit_tests/i24/test_pmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def test_pmac_can_be_created(fake_pmac: PMAC):

async def test_pmac_motor_move(fake_pmac: PMAC, RE):
pos = (1.0, 0.5)
RE(bps.mv(fake_pmac.x, pos[0], fake_pmac.y, pos[1]))
RE(bps.mv(fake_pmac.x, pos[0], fake_pmac.y, pos[1])) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827

assert await fake_pmac.x.user_readback.get_value() == 1.0
assert await fake_pmac.y.user_readback.get_value() == 0.5
Expand Down
8 changes: 4 additions & 4 deletions tests/devices/unit_tests/test_backlight.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async def test_backlight_can_be_written_and_read_from(fake_backlight: Backlight)
async def test_when_backlight_moved_out_it_switches_off(
mock_sleep: AsyncMock, fake_backlight: Backlight, RE: RunEngine
):
RE(bps.mv(fake_backlight, BacklightPosition.OUT))
RE(bps.mv(fake_backlight, BacklightPosition.OUT)) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
assert await fake_backlight.position.get_value() == BacklightPosition.OUT
assert await fake_backlight.power.get_value() == BacklightPower.OFF

Expand All @@ -48,7 +48,7 @@ async def test_when_backlight_moved_out_it_switches_off(
async def test_when_backlight_moved_in_it_switches_on(
mock_sleep, fake_backlight: Backlight, RE: RunEngine
):
RE(bps.mv(fake_backlight, BacklightPosition.IN))
RE(bps.mv(fake_backlight, BacklightPosition.IN)) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
assert await fake_backlight.position.get_value() == BacklightPosition.IN
assert await fake_backlight.power.get_value() == BacklightPower.ON

Expand All @@ -58,7 +58,7 @@ async def test_given_backlight_in_when_backlight_moved_in_it_does_not_sleep(
mock_sleep: AsyncMock, fake_backlight: Backlight, RE: RunEngine
):
set_mock_value(fake_backlight.position, BacklightPosition.IN)
RE(bps.mv(fake_backlight, BacklightPosition.IN))
RE(bps.mv(fake_backlight, BacklightPosition.IN)) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
mock_sleep.assert_not_awaited()


Expand All @@ -67,5 +67,5 @@ async def test_given_backlight_out_when_backlight_moved_in_it_sleeps(
mock_sleep: AsyncMock, fake_backlight: Backlight, RE: RunEngine
):
set_mock_value(fake_backlight.position, BacklightPosition.OUT)
RE(bps.mv(fake_backlight, BacklightPosition.IN))
RE(bps.mv(fake_backlight, BacklightPosition.IN)) # type: ignore # See: https://github.com/DiamondLightSource/dodal/issues/827
mock_sleep.assert_awaited_once()
Loading

0 comments on commit 08268c3

Please sign in to comment.