bluesky / ophyd

hardware abstraction in Python with an emphasis on EPICS
https://blueskyproject.io/ophyd
BSD 3-Clause "New" or "Revised" License
51 stars 79 forks source link

v2: ValueChecker needs a default value for _last_value #1156

Open rosesyrett opened 1 year ago

rosesyrett commented 1 year ago

Recently, at diamond we've been coming across an error that occasionally crops up and originates in the _ValueChecker:

class _ValueChecker(Generic[T]):
    def __init__(self, matcher: Callable[[T], bool], matcher_name: str):
        self._last_value: Optional[T]
        self._matcher = matcher
        self._matcher_name = matcher_name

    ...

    async def wait_for_value(self, signal: SignalR[T], timeout: float):
        try:
            await asyncio.wait_for(self._wait_for_value(signal), timeout)
        except asyncio.TimeoutError as e:
            raise TimeoutError(
                f"{signal.name} didn't match {self._matcher_name} in {timeout}s, "
                f"last value {self._last_value!r}"
            ) from e

we found the TimeoutError inconsistently raised AttributeError complaining that _ValueChecker doesn't have the attribute ._last_value.

To fix, the __init__ should look like:

class _ValueChecker(Generic[T]):
    def __init__(self, matcher: Callable[[T], bool], matcher_name: str):
        self._last_value: Optional[T] = None
        self._matcher = matcher
        self._matcher_name = matcher_name