Source code for yarp.general

"""
General purpose utility functions for manipulating :py:class:`Value` values.
"""

from yarp import NoChange, NoValue, Value, Event, fn, ensure_value
from ._utils import on_value


__names__ = [
    "window",
    "no_repeat",
    "filter",
    "replace_novalue",
]


[docs] def window(source_value: Value | Event, num_values: int | Value) -> Value: """make a Value with the num_values most recent values or events from source_value If num_values is decreased then the return value will be cropped. If it is increased, then the return value will lengthen gradually with new events or changes. """ num_values = ensure_value(num_values) output_values = [] @num_values.on_value_changed def limit_values(num_values_value): while len(output_values) > num_values_value: output_values.pop(0) def add_value(new_value): output_values.append(new_value) limit_values(num_values.value) on_value(source_value, add_value) return Value( inputs=(source_value, num_values), get_value=lambda: output_values.copy(), )
[docs] def no_repeat(source): """don't repeat the previous event or value of source""" last_value = object() @fn def f(value): nonlocal last_value if value != last_value: last_value = value return value else: return NoChange return f(source)
def _check_value(value, rule): """Internal. Test a value, return whether it should be retained or not according to the provided rule. If the rule is NoValue, returns True for non-NoValue values, including None or falsey values. If the rule is None, returns True for non-NoValue values which are truthy. If the rule is a function, calls it with the value and expects a boolean to be returned. """ if rule is NoValue: return value is not NoValue elif rule is None: return value is not NoValue and bool(value) else: return rule(value)
[docs] @fn def filter(source, rule=NoValue): """Filter change events. The filter rule should be a function which takes the new value as an argument and returns a boolean indicating if the value should be passed on or not. If the source value is a Value, the old value will remain unchanged when a value change is not passed on. If the initial value does not pass the test, the initial value of the result will be NoValue. If the filter rule is ``None``, non-truthy values and ``NoValue`` will be filtered out. If the filter rule is ``NoValue`` (the default) only ``NoValue`` will be filtered out. """ return source if _check_value(source, rule) else NoChange
[docs] @fn def replace_novalue(source_value, replacement_if_novalue=None): """ If the ``source_value`` is `NoValue`, return ``replacement_if_novalue`` instead. Parameters ---------- source_value : `Value` or `Event` replacement_if_novalue : Python object or `Value` Replacement value to use if ``source_value`` has the value `NoValue`. Returns ------- A `Value` or `Event` matching ``source_value``. """ if source_value is NoValue: return replacement_if_novalue else: return source_value