================ Migrating to 1.5 ================ This migration guide lists all the deprecations introduced by ska-tango-base release 1.5.0. .. contents:: Contents :depth: 2 :local: :backlinks: none Assigning NoValue to signal deprecated -------------------------------------- The ska-tango-base 1.4.0 release introduced the signal bus mechanism and :class:`~.attribute_from_signal` attribute decorator, with a special :data:`~.NoValue` type that can be assigned to :class:`~.Signal` objects. Rationale ^^^^^^^^^ The original intent was to have :data:`~.NoValue` serve two distinct purposes when assigned to a signal: 1. To automatically set the quality of an attribute linked to the signal to :class:`ATTR_INVALID `. 2. To delete the signal's value stored on the bus when it's initialised with ``stored=True``. However, the mistake with the original implementation was to not rather have ``None`` assigned to an attribute's signal set the attribute's quality to :class:`ATTR_INVALID ` (and consequently also its value to ``None``). With the ska-tango-base 1.5.0 release assigning ``None`` to an attribute's signal does this as well. Another oversight was not originally implementing a ``__delete__`` method in the :class:`~.Signal` descriptor. With the ska-tango-base 1.5.0 release using the ``del`` keyword on a signal will delete the value stored on the bus without emitting anything. This means the two functions above are now decoupled from one another and as a result assigning :data:`~.NoValue` to a :class:`~.Signal` object has been deprecated. :data:`~.NoValue` is only used as the default for a signal's ``initial_value`` to distinguish from ``None``, which is a valid initial value to emit. Preparing for removal ^^^^^^^^^^^^^^^^^^^^^ 1. Assign ``None`` instead of :data:`~.NoValue` to a signal to automatically set a linked attribute's quality to :class:`ATTR_INVALID `. 2. Use the ``del`` keyword on a signal instantiated with ``stored=True`` instead of assigning :data:`~.NoValue` if you have to delete its last value stored on the bus. .. warning:: Assigning :data:`~.NoValue` to a signal will raise an exception in the next major release. obsMode attribute becoming optional and a spectrum -------------------------------------------------- The :attr:`~ska_tango_base.obs.obs_interface.ObsInterface.obsMode` attribute with a scalar type is deprecated. A deprecation warning will be emitted at initialisation time if the :attr:`~ska_tango_base.obs.obs_interface.ObsInterface.obsMode` attribute is a scalar. In the next major release this attribute will be optional with a spectrum data type. Rationale ^^^^^^^^^ Some devices that support observing modes support multiple concurrent modes so their observer mode attribute needs to be a spectrum. For devices that only support a single concurrent observing mode it is preferable to still have a specturm attribute for consistency. Some devices with an observing state may not support any observing mode at all, therefore this attribute should be an optional part of the :class:`~ska_tango_base.obs.obs_interface.ObsInterface`. Preparing for type change ^^^^^^^^^^^^^^^^^^^^^^^^^ Device's inheriting from :class:`~ska_tango_base.obs.obs_interface.ObsInterface` should use :func:`~ska_tango_base.obs.obs_interface.standard_obs_mode` to override the attribute to have a spectrum type or assign ``obsMode = None`` at class scope to disable the attribute. When using the spectrum observing mode, assigning to the ``self._obs_mode`` signal will push new Tango events and update ``obsMode`` attribute. For example, .. code:: python import ska_control_model as scm import ska_tango_base as stb class WithSpectrumObsMode(stb.obs.ObsInterface): _obs_mode, obsMode = stb.obs.standard_obs_mode() def _update_obs_mode(self, new_obs_mode: list[scm.ObsMode]) -> None: """Example method for updating the spectrum observing mode.""" self._obs_mode = new_obs_mode ... class NoObsMode(stb.obs.ObsInterface): obsMode = None Writing to _health_state deprecated ----------------------------------- Updating the :attr:`~ska_tango_base.base.base_interface.BaseInterface.healthState` attribute by directly assigning to the :attr:`~ska_tango_base.base.base_interface.BaseInterface._health_state` signal has been deprecated and will emit a deprecation warning. Instead the :meth:`~ska_tango_base.base.base_interface.BaseInterface.report_health` method should be used to update the :attr:`~ska_tango_base.base.base_interface.BaseInterface.healthState` and :attr:`~ska_tango_base.base.base_interface.BaseInterface.healthInfo` attributes in tandem. In the next major release, emitting from :attr:`~ska_tango_base.base.base_interface.BaseInterface._health_state` directly will raise an exception. The last emitted health state value can still be read via the :attr:`~ska_tango_base.base.base_interface.BaseInterface._health_state` and this will not be removed. Rationale ^^^^^^^^^ ADR-128 places requirements on the :attr:`~ska_tango_base.base.base_interface.BaseInterface.healthInfo` attribute based on the current value of the :attr:`~ska_tango_base.base.base_interface.BaseInterface.healthState`, as such these attributes are coupled and it makes sense to update these attributes together. The new :meth:`~ska_tango_base.base.base_interface.BaseInterface.report_health` method ensures that the rules specified by ADR-128 are being followed. Also, the :meth:`~ska_tango_base.base.base_interface.BaseInterface.report_health` method will ensure that the attributes have the same time stamp if they change at the same time, allowing users to correlate the values in the archiver. Preparing for removal ^^^^^^^^^^^^^^^^^^^^^ Replace assignments of the :attr:`~ska_tango_base.base.base_interface.BaseInterface._health_state` attribute with calls to :meth:`~ska_tango_base.base.base_interface.BaseInterface.report_health`. This requires providing a non-empty health info list for :class:`HealthState.DEGRADED ` and :class:`HealthState.FAILED `. For example, the following device has a monitoring loop that collects health issues and then reports :class:`HealthState.FAILED ` if any are encountered. .. code:: python import ska_control_model as scm import ska_tango_base as stb class MyDevice(stb.base.BaseInterface): def monitoring(self) -> None: while True: health_infos = [] # ... added entries to health_infos as we detect issues if health_infos: self.report_health(scm.HealthState.FAILED, health_infos) else: self.report_health(scm.HealthState.OK, health_infos) # ... The :meth:`~ska_tango_base.base.base_interface.BaseInterface.report_health` method does not support :class:`HealthState.UNKNOWN ` and you should use :class:`HealthState.FAILED ` with an appropriate message instead.