Skip to content

Improve spectrum and image attribute behaviour with empty lists (breaking change to API!)

Breaking change to spectrum and image attributes API!

It make the behaviour more Pythonic when lists are empty: you get empty lists instead of None values.


Closes #229 (closed) and #230 (closed)

First #229 (closed) - this is easy: can be fixed in the __get_write_value_array_pytango3 method in ext/server/wattribute.cpp

Instead of

	if (buffer == NULL) {
	    *obj = boost::python::object();
	    return;
	}

we should do

	if (buffer == NULL) {
	    *obj = boost::python::list();
	    return;
	}

Then #230 (closed). This was fixed at several places:

a) starting from cpptango 9.4.1 attribute's get_type() method was fixed Improve DeviceAttribute::get_type - so we can run proper update_value_as.... method

b) for "simple" cases: "tuples" and "lists" we change return from bopy::object() to bopy::list() or bopy::tuple()

c) in case of bin, bytes and numpy the easiest solution is to create an empty array with the same type, attribute should have, and run the conversion till the end - this will result in wanted behavior: e.g. from:

        if (value_ptr == 0) {
            // Empty device attribute
            PyObject* value = PyArray_SimpleNew(0, 0, typenum);
            if (!value)
                throw_error_already_set();
            py_value.attr(value_attr_name) = object(handle<>(value));
            py_value.attr(w_value_attr_name) = object();
            return;
        }

to:

        TangoArrayType empty;
        if (value_ptr == 0) {
            // Empty device attribute
            value_ptr = &empty;
        }
        
       do whatever we need to convert.....

This works well for the most of the cases. However, we found, that our code was broken in general for the conversion to bin, bytearray and strings, so we decided to block (temporary?) this functionality.

In addition, we added a new check of the attribute quality, to maintain backward compatibility, that for invalid attribute return is None:

        const int quality = self.get_quality();
        const bool is_invalid = quality == Tango::ATTR_INVALID;

...

        if (failed_data_type || has_failed || is_invalid) {
            // In these cases we cannot/should not (to maintain backward compatibility) extract data
            py_value.attr(value_attr_name) = object();
            py_value.attr(w_value_attr_name) = object();
            return;
        }
Edited by Yury Matveyev

Merge request reports