Skip to content

Support of non-bound methods for attributes.

Closes #435 (closed) and #497 (closed) and additionally, extend support of non-bounds methods to dynamic attributes

  1. I found, that we treat "fget" keyword differently comparing "fread", "fset", "fwrite", "fisallowed": we specify it explicitly in init and then store it to fget attribute of attribute(AttrData) class:
def __init__(self, fget=None, **kwargs):

...
    if fget:
        if inspect.isroutine(fget):
            self.fget = fget
            if 'doc' not in kwargs and 'description' not in kwargs:
                if fget.__doc__ is not None:
                    kwargs['doc'] = fget.__doc__
        kwargs['fget'] = fget

and later we, when we wrap attributes with executors, we first take method from fget attribute of attribute(AttrData), and only then try to find method locally:

    read_method = getattr(attribute, "fget", None)
    if read_method:
        method_name = "__read_{0}__".format(attribute.attr_name)
        attribute.read_method_name = method_name
    else:
        method_name = attribute.read_method_name
        read_method = getattr(tango_device_klass, method_name)

    read_attr = _get_wrapped_read_method(attribute, read_method)
    method_name = "__read_{0}_wrapper__".format(attribute.attr_name)
    attribute.read_method_name = method_name

    setattr(tango_device_klass, method_name, read_attr)
  1. in case of set(write) method we do differently, since we do not store user method, and, even the code in similar, write_method = getattr(attribute, "fset", None) does not work, so we go to the search of the local method.

  2. with fisallowed situation is that we do not wrap it at all, so this is why it is not working in async mode.

So I propose:

  1. to treat "fread", "fset", "fwrite", "fisallowed" similar to fget and save then to fget, fset and fisallowed attributes of attribute(AttrData)

  2. add wrapper for fisallowed and also to introduce isallowed_green_mode keyword, similar to the read_green_mode and write_green_mode

  3. to make thing symmetrical, I propose, that we allow non-bound methods for dynamic attributes too:

in ensure_user_method_is_bounded instead of:

        is_device_method = getattr(obj, name, None) == user_method

        if not is_device_method:
            # in case user gave us class method, we are trying to find it in device:
            bound_user_method = getattr(obj, name, None)
            if bound_user_method is None:
                raise ValueError(

we do "ESRF trick" automatically and add method to the server dict:

        if not is_device_method:
            # in case user gave us class method, we are trying to find it in device:
            bound_user_method = getattr(obj, name, None)
            if bound_user_method:
                user_method = bound_user_method
            else:
                setattr(obj, name, user_method)
Edited by Yury Matveyev

Merge request reports