Skip to content

fisallowed=<non-device method callable> does not work in high-level attribute API

According to the documentation (https://pytango.readthedocs.io/en/stable/server_api/server.html#tango.server.attribute), we're allowed to provide an ad-hoc function for the fisallowed parameter of an attribute, just like for fget and fset. However, doing this results in the provided function not being called, for example:

from tango.server import Device, attribute
from tango.test_context import DeviceTestContext

def is_A_allowed_global(*args, **kwargs):
    print("is_A_allowed called globally with args", args, kwargs)
    return False

class test_device(Device):
    A = attribute(dtype=float, fisallowed=is_A_allowed_global)

    def init_device(self):
        print("init_device")
        Device.init_device(self)

    def read_A(self):
        return 42.0

    def is_A_allowed_obj(*args, **kwargs):
        print("is_A_allowed called on object with args", args, kwargs)
        return False

if __name__ == "__main__":
    with DeviceTestContext(test_device, process=True) as proxy:
        proxy.init()
        print(proxy.A)

The above code results in the following output:

Can't create notifd event supplier. Notifd event not available
init_device
Ready to accept request
init_device
42.0

Even though the provided fisallowed function always returns False. Note that setting fisallowed="is_A_allowed_obj" for example, as expected, does work in the above setup, but will of course redirect the call to test_device.is_A_allowed_obj.

We use the fget/fset=<callable> construct to dynamically provide the attribute access using a derived attribute class. It would be very nice to be able to take fisallowed along in the same construct, to allow full flexibility in the attribute access definition.

Edited by Jan David Mol