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
yarp
value 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
_value
attribute directly. This may be useful if you wish to make this Value mimic another by, in a callback function, setting_value
in this Value directly from the other Value’svalue
and 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
value
property (which will remain unchanged).
-
on_value_changed
(cb)[source]¶ Registers
callback
as 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.value
property. Otherwise, if this value is instantaneous, the value will not be reflected in theValue.value
property.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
yarp
is 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 Value
s which
update whenever the underlying Value
s do.
-
yarp.
value_list
(list_of_values)[source]¶ Returns a
Value
consisting of a fixed list of otherValues
. The returnedValue
will change whenever one of its members does.Parameters: - list_of_values: [:py:class:`Value`, …]
A fixed list of
Value
s. Thevalue
of 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
NoValue
invalue
or in callbacks resulting from otherValue
s changing.
-
yarp.
value_tuple
(tuple_of_values)[source]¶ A
Value
consisting of a tuple of otherValues
.Parameters: - tuple_of_values: (:py:class:`Value`, …)
A fixed tuple of
Value
s. Thevalue
of 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
NoValue
invalue
or in callbacks resulting from otherValue
s changing.
-
yarp.
value_dict
(dict_of_values)[source]¶ A
Value
consisting of a dictionary where the values (but not keys) areValues
.Parameters: - dict_of_values: {key: :py:class:`Value`, …}
A fixed dictionary of
Value
s. Thevalue
of 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
NoValue
invalue
or in callbacks resulting from otherValue
s 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
Value
object, 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_tuple
orvalue_dict
respectively. - If any other type, wraps the variable in a continous
Value
with 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 + b
a - b
a * b
a @ b
a / b
a // b
a % b
divmod(a, b)
a ** b
- Bit-wise
a << b
a >> b
a & b
a | b
a ^ b
- Unary
-a
+a
abs(a)
~a
- Comparison
a < b
a <= b
a == b
a != b
a >= b
a > 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 aValue
containing the result. This value will be updated by re-calling the function whenever the Value changes. Likefn()
, arguments may beValue
objects 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.name
equivalent 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 b
fora & b
(works for boolean values but produces numbers)a or b
fora | 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
operator
module.
These wrappers produce continuous Value
s. Corresponding
versions prefixed with instantaneous_
are provided which produce
instantaneous Value
s.
Function wrappers¶
The primary mode of interaction with yarp
Value
s 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
Value
objects 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
Value
objects like so:>>> a = yarp.Value(1) >>> b = yarp.Value(2) >>> c = add(a, b)
The returned value will itself be a
Value
object which will be updated whenever any of the arguments change.>>> c.value 3
The wrapped function doesn’t need to know anything about
Value
objects: the wrapper unpacks theValue
s of each argument before passing it on and automatically wrapps the return value in aValue
. (Non-Value
arguments 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
Value
will be persistent.See also:
instantaneous_fn()
.
General Value manipulation¶
The following utility functions are defined which accept and return
Value
s.
-
yarp.
replace_novalue
(source_value, replacement_if_novalue=None)[source]¶ If the
source_value
isNoValue
, returnreplacement_if_novalue
instead.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_values
argument 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_values
is 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
Value
hasn’t changed.Works for both continuous and instantaneous
Value
s.
-
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 andNoValue
will be filtered out. If the filter rule isNoValue
(the default) onlyNoValue
will be filtered out.
Temporal Value manipulation¶
The following utility functions are defined which accept and return
Value
s 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 continuousValue
s, the initial value is set immediately.The
delay_seconds
argument 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
loop
argument should be anasyncio.BaseEventLoop
in 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
Value
it 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
duration
may 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
loop
argument should be anasyncio.BaseEventLoop
in 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_interval
argument 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
loop
argument should be anasyncio.BaseEventLoop
in 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
Value
s
-
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
Value
containing adatetime.datetime
object holding the current time, refreshed everyinterval
seconds.The
interval
argument may be a constant or aValue
giving 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
tz
argument is passed on todatetime.datetime.now()
. This must be a constant.The
loop
argument should be anasyncio.BaseEventLoop
in which the delays will be scheduled. IfNone
, the default loop is used.