yarp API¶
Value type¶
At the core of the yarp API is the Value type. This type is
defined below.
-
yarp.NoValue= NoValue¶ A special value indicating that a
yarpvalue has not been assigned a value.
-
class
yarp.Value(initial_value=NoValue)[source]¶ A continuous or instantaneous value which can be read and set.
This base class defines the fundamental type in
yarp: the ‘value’.The actual data contained by this object should be regarded as immutable with changes being made by replacing the Python object with a new one to affect changes.
-
value¶ A property holding the current continuous value held by this object. If not yet set, or if this object represents only instantaneous values, this will be
NoValue.Setting this property sets the (continuous) contents of this value (raising the
on_value_changed()callback afterwards).To set the instantaneous value, see
set_instantaneous_value().To change the value without raising a callback, set the
_valueattribute directly. This may be useful if you wish to make this Value mimic another by, in a callback function, setting_valuein this Value directly from the other Value’svalueand callingset_instantaneous_value()with the passed variable explicitly. You must always be sure to callset_instantaneous_value()after changing_value.
-
set_instantaneous_value(new_value)[source]¶ Set the instantaneous value of this Value, calling the on_value_changed callbacks with the passed value but not storing it in the
valueproperty (which will remain unchanged).
-
on_value_changed(cb)[source]¶ Registers
callbackas a callback function to be called when this value changes.The callback function will be called with a single argument: the value now held by this object. If the value is continuous, the value given as the argument will match the
Value.valueproperty. Otherwise, if this value is instantaneous, the value will not be reflected in theValue.valueproperty.Note
There is no way to remove callbacks. For the moment this is an intentional restriction: if this causes you difficulties this is a good sign what you’re doing is ‘serious’ enough that
yarpis not for you.This function returns the callback passed to it making it possible to use it as a decorator if desired.
-
Aggregate Values¶
The yarp API provides a limited set of convenience functions which which
turn certain native Python data structures into Values which
update whenever the underlying Values do.
-
yarp.value_list(list_of_values)[source]¶ Returns a
Valueconsisting of a fixed list of otherValues. The returnedValuewill change whenever one of its members does.Parameters: - list_of_values: [:py:class:`Value`, …]
A fixed list of
Values. Thevalueof this object will be an array of the underlying values. Callbacks will be raised whenever a value in the list changes.It is not possible to modify the list or set the contained values directly from this object.
For instantaneous list members, the instantaneous value will be present in the version of this list passed to registered callbacks but otherwise not retained. (Typically the instantaneous values will be represented by
NoValueinvalueor in callbacks resulting from otherValues changing.
-
yarp.value_tuple(tuple_of_values)[source]¶ A
Valueconsisting of a tuple of otherValues.Parameters: - tuple_of_values: (:py:class:`Value`, …)
A fixed tuple of
Values. Thevalueof this object will be a tuple of the underlying values. Callbacks will be raised whenever a value in the tuple changes.It is not possible to modify the tuple or set the contained values directly from this object.
For instantaneous tuple members, the instantaneous value will be present in the version of this tuple passed to registered callbacks but otherwise not retained. (Typically the instantaneous values will be represented by
NoValueinvalueor in callbacks resulting from otherValues changing.
-
yarp.value_dict(dict_of_values)[source]¶ A
Valueconsisting of a dictionary where the values (but not keys) areValues.Parameters: - dict_of_values: {key: :py:class:`Value`, …}
A fixed dictionary of
Values. Thevalueof this object will be a dictionary of the underlying values. Callbacks will be raised whenever a value in the dictionary changes.It is not possible to modify the set of keys in the dictionary nor directly change the values of its elements from this object.
For instantaneous dictionary members, the instantaneous value will be present in the version of this dict passed to registered callbacks but otherwise not retained. (Typically the instantaneous values will be represented by
NoValueinvalueor in callbacks resulting from otherValues changing.
Value casting¶
The following low-level funcitons are provided for creating and casting
Value objects.
-
yarp.ensure_value(value)[source]¶ Ensure a variable is a
Valueobject, wrapping it accordingly if not.- If already a
Value, returns unmodified. - If a list, tuple or dict, applies
ensure_value()to all contained values and returns avalue_list,value_tupleorvalue_dictrespectively. - If any other type, wraps the variable in a continous
Valuewith the initial value set to the defined value.
- If already a
Value Operators¶
The Value class also supports many (but not all) of the native
Python operations, producing corresponding (continuous) Value
objects as results. These operations support the mixing of Value
objects and other suitable Python objects. The following operators are
supported:
- Arithmetic
a + ba - ba * ba @ ba / ba // ba % bdivmod(a, b)a ** b
- Bit-wise
a << ba >> ba & ba | ba ^ b
- Unary
-a+aabs(a)~a
- Comparison
a < ba <= ba == ba != ba >= ba > b
- Container operators
a[key]
- Numerical conversions
complex(a)int(a)float(a)round(a)
- Python object/function usage
a(...)will call the value as a function and return aValuecontaining the result. This value will be updated by re-calling the function whenever the Value changes. Likefn(), arguments may beValueobjects and these will be unwrapped before the function is called and will also cause the function to be re-evaluated whenever they change. Do not use this to call functions with side effects.a.nameequivalent toyarp.getattr(a, "name")
Unfortunately this list doesn’t include boolean operators (i.e. not,
and, or and bool). This is due to a limitation of the Python data
model which means that bool may only return an actual boolean value, not
some other type of object. As a workaround you can substitute:
bool(a)fora == True(works in most cases)a and bfora & b(works for boolean values but produces numbers)a or bfora | b(works for boolean values but produces numbers)
For a similar reasons, the len and in operators are also not supported.
This list also doesn’t include mutating operators, for example a[key] = b.
This is because the Python objects within a Value are treated as
being immutable.
Finally, to reiterate, the result of these operators will always be continuous
Values. For instantaneous versions of these operators, see the
Python builtins section below.
Python builtins¶
The yarp API provides Value-compatible versions of a number of
Python builtins and functions from the standard library:
- Builtins
bool(a)any(a)all(a)min(a)max(a)sum(a)map(a)sorted(a)str(a)repr(a)str_format(a, ...)(equivalent toa.format(...))oct(a)hex(a)zip(a)len(a)getattr(object, name[, default])
- Most non-mutating, non-underscore prefixed functions from the
operatormodule.
These wrappers produce continuous Values. Corresponding
versions prefixed with instantaneous_ are provided which produce
instantaneous Values.
Function wrappers¶
The primary mode of interaction with yarp Values is intended
to be via simple Python functions wrapped with fn() or
instantaneous_fn(). These wrappers are defined below.
-
yarp.fn(f)[source]¶ Decorator. Wraps a function so that it may be called with
Valueobjects and itself return a persistentValue.Say a function is defined and wrapped with
fn()like so:>>> @yarp.fn ... def add(a, b): ... return a + b
The function can now be called with
Valueobjects like so:>>> a = yarp.Value(1) >>> b = yarp.Value(2) >>> c = add(a, b)
The returned value will itself be a
Valueobject which will be updated whenever any of the arguments change.>>> c.value 3
The wrapped function doesn’t need to know anything about
Valueobjects: the wrapper unpacks theValues of each argument before passing it on and automatically wrapps the return value in aValue. (Non-Valuearguments passed to the function are automatically passed through without modification).The wrapped function is called once immediately when it is called and then again as required when its arguments change. The output
Valuewill be persistent.See also:
instantaneous_fn().
General Value manipulation¶
The following utility functions are defined which accept and return
Values.
-
yarp.replace_novalue(source_value, replacement_if_novalue=None)[source]¶ If the
source_valueisNoValue, returnreplacement_if_novalueinstead.Parameters: Returns: - A continuous :py:class:`Value` which will be a copy of ``source_value`` if
- ``source_value`` is not :py:data:`NoValue`, otherwise the value of
- ``replacement_if_novalue`` is used instead.
-
yarp.window(source_value, num_values)[source]¶ Produce a moving window over a
Value’s historical values.This function treats the Value it is passed as a persistent Value, even if it is instantaneous (since a window function doesn’t really have any meaning for a instantaneous values).
The
num_valuesargument may be a (persistent) Value or a constant indicating the number of entries in the window. If this value later reduced, the contents of the window will be truncated immediately. If it is increaesd, any previously dropped values will not return.num_valuesis always assumed to be an integer greater than zero and neverNoValue.
-
yarp.no_repeat(source_value)[source]¶ Don’t pass on change callbacks if the
Valuehasn’t changed.Works for both continuous and instantaneous
Values.
-
yarp.filter(source_value, rule=NoValue)[source]¶ 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 persistent, the persistent value will remain unchanged when a value change is not passed on.
If the filter rule is
None, non-truthy values andNoValuewill be filtered out. If the filter rule isNoValue(the default) onlyNoValuewill be filtered out.
Temporal Value manipulation¶
The following utility functions are defined which accept and return
Values but may delay or filter changes. These all use
asyncio internally and require that a
asyncio.BaseEventLoop be running.
-
yarp.delay(source_value, delay_seconds, loop=None)[source]¶ Produce a time-delayed version of a
Value.Supports both instantaneous and continous
Values. For continuousValues, the initial value is set immediately.The
delay_secondsargument may be a constant or a Value giving the number of seconds to delay value changes. If it is increased, previously delayed values will be delayed further. If it is decreased, values which should already have been output will be output rapidly one after another.The
loopargument should be anasyncio.BaseEventLoopin which the delays will be scheduled. IfNone, the default loop is used.
-
yarp.time_window(source_value, duration, loop=None)[source]¶ Produce a moving window over a
Value’s historical values within a given time period.This function treats the
Valueit is passed as a persistentValue, even if it is instantaneous (since a window function doesn’t really have any meaning for an instantaneous value).The
durationmay be a constant or a (persistent) Value giving the window duration as a number of seconds. The duration should be a number of seconds greater than zero and never beNoValue. If the value is reduced, previously inserted values will be expired earlier, possibly immediately if they should already have expired. If the value is increased, previously inserted values will have an increased timeout.The
loopargument should be anasyncio.BaseEventLoopin which windowing will be scheduled. IfNone, the default loop is used.
-
yarp.rate_limit(source_value, min_interval=0.1, loop=None)[source]¶ Prevent changes occurring above a particular rate, dropping or postponing changes if necessary.
The
min_intervalargument may be a constant or aValue. If this value is decreased, currently delayed values will be output early (or immediately if the value would have been output previously). If increased, the current delay will be increased.The
loopargument should be anasyncio.BaseEventLoopin which the delays will be scheduled. IfNone, the default loop is used.
File-backed Values¶
The following function can be used to make very persistent
Values
-
yarp.file_backed_value(filename, initial_value=NoValue)[source]¶ A persistent, file-backed value.
Upon creation, the value will be loaded from the specified filename. Whenever the value is changed it will be rewritten to disk. Changes made to the file while your program is running will be ignored.
If the file does not exist, it will be created and the value set to the value given by initial_value.
The value must be pickleable.
Time Values¶
The following function can be used to get the (continously changing) date and time:
-
yarp.now(interval=1.0, tz=None, loop=None)[source]¶ Returns a continuous
Valuecontaining adatetime.datetimeobject holding the current time, refreshed everyintervalseconds.The
intervalargument may be a constant or aValuegiving the number of seconds to wait between updates. If the Value changes, the time until the next update will be reset starting from that moment in time.The
tzargument is passed on todatetime.datetime.now(). This must be a constant.The
loopargument should be anasyncio.BaseEventLoopin which the delays will be scheduled. IfNone, the default loop is used.