dls-controls / pythonSoftIOC

Embed an EPICS IOC in a Python process
Apache License 2.0
32 stars 7 forks source link

Out records without an initial_value cannot be correctly validated #43

Closed AlexanderWells-diamond closed 2 years ago

AlexanderWells-diamond commented 2 years ago

If an out record is constructed without an initial_value or has no set() called before the IOC is initialised, validate methods will not work as expected - they won't work at all. An example program is:

# Import the basic framework components.
from softioc import softioc, builder, asyncio_dispatcher
import asyncio

# Create an asyncio dispatcher, the event loop is now running
dispatcher = asyncio_dispatcher.AsyncioDispatcher()

# Set the record prefix
builder.SetDeviceName("MY-DEVICE-PREFIX")

def _capture_validate(record, new_val) -> bool:
    """Check the required records have been set before allowing Capture=1"""
    try:
        raise ValueError("Test")
    except ValueError:
        return False

    return True

# Create some records
ao = builder.boolOut('BO', ZNAM="0", ONAM="1", validate=_capture_validate)

# Boilerplate get the IOC started
builder.LoadDatabase()
softioc.iocInit(dispatcher)

# Finally leave the IOC running with an interactive shell.
softioc.interactive_ioc(globals())

And running the following commands in the terminal, we see an error message BUT we also see the underlying value has changed:

[...]$ caget MY-DEVICE-PREFIX:BO
MY-DEVICE-PREFIX:BO            0
[...]$ caput MY-DEVICE-PREFIX:BO 1
Old : MY-DEVICE-PREFIX:BO            0
CA.Client.Exception...............................................
    Warning: "Channel write request failed"
    Context: "op=1, channel=MY-DEVICE-PREFIX:BO, type=DBR_STRING, count=1, ctx="MY-DEVICE-PREFIX:BO""
    Source File: ../oldChannelNotify.cpp line 160
    Current Time: Tue Oct 05 2021 09:30:02.714662686
..................................................................
New : MY-DEVICE-PREFIX:BO            1
[...]$ caget MY-DEVICE-PREFIX:BO
MY-DEVICE-PREFIX:BO            1
[eyh46967@pc0103 PandABlocks-client]$ 

Following a bit of debugging with @Araneidae it seems that all Out records will face similar issues if there is no initial_value set.

AlexanderWells-diamond commented 2 years ago

This issue should be solved after #40 as it'll add typing info to the record creation functions (longout, longin, etc.) in device.py.

Then self._value = kargs.pop('initial_value', None) could have the None changed to be the default value of the type.