Support of non-bound methods for attributes.
Closes #435 (closed) and #497 (closed) and additionally, extend support of non-bounds methods to dynamic attributes
- 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)
-
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. -
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:
-
to treat "fread", "fset", "fwrite", "fisallowed" similar to fget and save then to fget, fset and fisallowed attributes of attribute(AttrData)
-
add wrapper for fisallowed and also to introduce isallowed_green_mode keyword, similar to the read_green_mode and write_green_mode
-
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)