bluesky / ophyd-async

Hardware abstraction for bluesky written using asyncio
https://blueskyproject.io/ophyd-async
BSD 3-Clause "New" or "Revised" License
11 stars 25 forks source link

TypeError from p4p when running save_device on an HDFPanda #571

Open jwlodek opened 2 months ago

jwlodek commented 2 months ago

Short traceback:

In [1]: from ophyd_async.core import save_device

In [2]: RE(save_device(panda1, "test.yml"))
An exception has occurred, use '%tb verbose' to see the full traceback.
TypeError: string indices must be integers, not 'str'

See /nsls2/users/jwlodek/.cache/bluesky/log/bluesky.log for the full traceback.

In [3]: panda1
Out[3]: <ophyd_async.fastcs.panda._hdf_panda.HDFPanda at 0x7f18f1ec4790>

Doing a verbose traceback shows the error comes from p4p:

File ~/.ipython/profile_collection_tst/venv/lib64/python3.11/site-packages/bluesky/utils/__init__.py:1929, in maybe_await(ret=<coroutine object SignalRW.locate>)
   1927 async def maybe_await(ret: SyncOrAsync[T]) -> T:
   1928     if inspect.isawaitable(ret):
-> 1929         return await ret
        ret = <coroutine object SignalRW.locate at 0x7f18da2e3780>
   1930     else:
   1931         # Mypy does not understand how to narrow type to non-awaitable in this
   1932         # instance, see https://github.com/python/mypy/issues/15520
   1933         return ret

File ~/.ipython/profile_collection_tst/venv/lib64/python3.11/site-packages/ophyd_async/core/_signal.py:263, in SignalRW.locate(self=<ophyd_async.core._signal.SignalRW object>)
    261 async def locate(self) -> Location:
    262     location: Location = {
--> 263         "setpoint": await self._backend.get_setpoint(),
        Location = <class 'bluesky.protocols.Location'>
        self._backend = <ophyd_async.epics.signal._p4p.PvaSignalBackend object at 0x7f18da384a10>
        self = <ophyd_async.core._signal.SignalRW object at 0x7f18da384b50>
    264         "readback": await self.get_value(),
    265     }
    266     return location

File ~/.ipython/profile_collection_tst/venv/lib64/python3.11/site-packages/ophyd_async/epics/signal/_p4p.py:448, in PvaSignalBackend.get_setpoint(self=<ophyd_async.epics.signal._p4p.PvaSignalBackend object>)
    446 async def get_setpoint(self) -> T:
    447     value = await self.ctxt.get(self.write_pv, "field(value)")
--> 448     return self.converter.value(value)
        value = Value(id:epics:nt/NTScalar:1.0, 'PCAP.ACTIVE')
        self.converter = PvaEnumConverter()
        self = <ophyd_async.epics.signal._p4p.PvaSignalBackend object at 0x7f18da384a10>

File ~/.ipython/profile_collection_tst/venv/lib64/python3.11/site-packages/ophyd_async/epics/signal/_p4p.py:231, in PvaEnumConverter.value(self=PvaEnumConverter(), value=Value(id:epics:nt/NTScalar:1.0, 'PCAP.ACTIVE'))
    230 def value(self, value):
--> 231     return self.choices[value["value"]["index"]]
        self.choices = ('ZERO', 'ONE')
        self = PvaEnumConverter()
        value = Value(id:epics:nt/NTScalar:1.0, 'PCAP.ACTIVE')

TypeError: string indices must be integers, not 'str'

It seems value['value'] is returning the string name of the record, not the value.

ipdb> value['value']
'PCAP.ACTIVE'
coretl commented 2 months ago

I think we should:

coretl commented 5 days ago

@jwlodek I think this is now fixed in 0.8.0a4, please could you check if you get a chance?