Source code for taurus.core.util.eventfilters

#!/usr/bin/env python

# ###########################################################################
#
# This file is part of Taurus
#
# http://taurus-scada.org
#
# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
#
# Taurus is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Taurus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
#
# ###########################################################################

"""event filters library to be used with
:meth:`taurus.qt.qtgui.base.TaurusBaseComponent.setFilters`
"""

__all__ = [
    "IGNORE_ALL",
    "ONLY_CHANGE",
    "IGNORE_CHANGE",
    "ONLY_CHANGE_AND_PERIODIC",
    "IGNORE_CHANGE_AND_PERIODIC",
    "ONLY_CONFIG",
    "IGNORE_CONFIG",
    "IGNORE_FAKE",
    "ONLY_VALID",
    "EventValueMap",
    "RepeatedEventFilter",
    "filterEvent",
]


[docs]def IGNORE_ALL(s, t, v): """Will discard all events""" return None
[docs]def ONLY_CHANGE(s, t, v): """Only change events pass""" from taurus.core import TaurusEventType if t == TaurusEventType.Change: return s, t, v else: return None
[docs]def IGNORE_CHANGE(s, t, v): """Config events are discarded""" from taurus.core import TaurusEventType if t != TaurusEventType.Change: return s, t, v else: return None
[docs]def ONLY_CHANGE_AND_PERIODIC(s, t, v): """Only change events pass""" from taurus.core import TaurusEventType if t in [TaurusEventType.Change, TaurusEventType.Periodic]: return s, t, v else: return None
[docs]def IGNORE_CHANGE_AND_PERIODIC(s, t, v): """Config events are discarded""" from taurus.core import TaurusEventType if t not in [TaurusEventType.Change, TaurusEventType.Periodic]: return s, t, v else: return None
[docs]def ONLY_CONFIG(s, t, v): """Only config events pass""" from taurus.core import TaurusEventType if t == TaurusEventType.Config: return s, t, v else: return None
[docs]def IGNORE_CONFIG(s, t, v): """Config events are discarded""" from taurus.core import TaurusEventType if t != TaurusEventType.Config: return s, t, v else: return None
[docs]def IGNORE_FAKE(s, t, v): """Only events with actual value (!=None) pass""" if v is not None: return s, t, v else: return None
[docs]def ONLY_VALID(s, t, v): """Only events whose quality is VALID pass""" from taurus.core import AttrQuality if t == AttrQuality.ATTR_VALID: return s, t, v else: return None
[docs]class EventValueMap(dict): """A filter destined to change the original value into another one according to a given map. Example: filter = EventValueMap({1:"OPEN", 2:"CHANGING", 3:"CLOSED"}) this will create a filter that changes the integer value of the event into a string. The event type is changed according to the python type in the map value. For now it only supports simple types: str, int, long, float, bool """ def __call__(self, s, t, v): import copy from taurus.core import TaurusEventType, DataType if t not in (TaurusEventType.Change, TaurusEventType.Periodic): return s, t, v if v is None: return s, t, v # make a copy v = copy.copy(v) v.value = self.get(v.rvalue, v.rvalue) v.type = DataType.from_python_type(type(v.rvalue), v.type) return s, t, v
[docs]class RepeatedEventFilter(object): """ The instances of this class will be callables that can be used as filters of repeated-value events. If the event type is Change or Periodic, it will only pass when its evt_value.value is different from that of the last event received from the same source and type. If evt_value.value is not available in the current event, the whole evt_value is used for comparison and as a future reference. This is useful to avoid processing repetitive events. Note that you cannot use this class as a filter: you need to use an instance of it. Note 2: Use a different instance each time you insert this filter into a different widget unless you *really* know what you are doing. Example of usage:: filters = [RepeatedEventFilter(), IGNORE_CONFIG] filterEvent(s, t, v, filters) """ def __init__(self): self._lastValues = {} def __call__(self, s, t, v): # restrict this filter only to change and periodic events. if ONLY_CHANGE_AND_PERIODIC(s, t, v) is None: return s, t, v # block event if we recorded one before with same src, type and v.value new_value = getattr(v, "value", v) try: if self._lastValues[(s, t)] == new_value: return None except KeyError: pass # if it was't blocked, store src, type and v.value for future checks self._lastValues[(s, t)] = new_value return s, t, v
[docs]def filterEvent(evt_src=-1, evt_type=-1, evt_value=-1, filters=()): """The event is processed by each and all filters in strict order unless one of them returns None (in which case the event is discarded) :param evt_src: object that triggered the event :type evt_src: object :param evt_type: type of event :type evt_type: TaurusEventType :param evt_value: event value :type evt_value: object :param filters: a sequence of callables, each returning either None (to discard the event) or the tuple (with possibly transformed values) of (evt_src, evt_type, evt_value) :type filters: sequence<callable> :return: The result of piping the event through the given filters. :rtype: None or tuple """ evt = evt_src, evt_type, evt_value for f in filters: evt = f(*evt) if evt is None: return None return evt