live_cells package

Module contents

class live_cells.Cell

Bases: object

Base cell class.

All cells should inherited this class.

add_observer(observer)

Add an observer to the cell.

observer is notified whenever the value of this cell changes.

Parameters:

observer – The observer to add to the cell.

error(all=False, type=None)

Create a cell that captures exceptions raised by this cell.

The returned cell evaluates to the last exception raised while computing the value of this cell..

If type is not None, the returned cell only captures exceptions which are of the type provided in type.

Parameters:
  • all – If True, the returned cell evaluates to None when this cell does not raise an exception. Defaults to False.

  • type – The type of exceptions to capture or None (default) to capture all exceptions.

Returns:

A new cell.

Return type:

Cell

Note

The value of the returned cell is None until an exception is raised while computing the value of this cell, regardless of the value of all.

logand(b)

Create a cell that computes the logical and of this cell and b.

Note

Cells returned by this method compare equal when called on the same object and the same arguments are provided.

Parameters:

b (Cell) – The operand cell.

Returns:

A cell which evaluates to the logical and of this cell’s value and the value of b.

Return type:

Cell

lognot()

Create a cell that computes the logical not of this cell.

Note

Cells returned by this method compare equal when called on the same object.

Returns:

A cell which evaluates to the logical not of the value of this cell.

Return type:

Cell

logor(b)

Create a cell that computes the logical or of this cell and b.

Note

Cells returned by this method compare equal when called on the same object and the same arguments are provided.

Parameters:

b (Cell) – The operand cell.

Returns:

A cell which evaluates to the logical or of this cell’s value and the value of b.

Return type:

Cell

on_error(other, type=None)

Create a cell that evaluates to another cell when this cell raises an exception.

When an exception is raised while computing the value of this cell, the returned cell evaluates to the value of other.

If type is not None, the returned cell evaluates to the value of other only when an exception of the same type as that provided in type is raised.

Parameters:
  • other (Cell) – The cell to evaluate to when this cell raises an exception.

  • type – Type of exceptions to handle or None (default) to handle all exceptions.

Returns:

A new cell.

Return type:

Cell

property peek

Read the value of this cell without reacting to changes.

This property returns a cell that has the same value as this cell but does not notify its observers when the value of this cell changes.

This should be used rather than accessing the Cell.value property directly to ensure that this cell is active.

remove_observer(observer)

Remove an observer from the cell.

After observer is removed, it is no longer notified when the value of the cell changes.

Note

To remove a given observer, this method has to be called the same number of times as add_observer was called for the same observer.

Parameters:

observer – The observer to remove.

select(if_true, if_false=None)

Create a new cell which selects between the values of two cells based on cond.

If the value of cond is True, the cell evaluates to the value of the if_true cell. If cond is False, the cell evaluates to the value of the if_false cell.

If if_false is None, the previous value of the cell is preserved when cond is False.

Parameters:
  • cond (Cell) – A condition cell evaluating to a boolean.

  • if_true (Cell) – Cell to evaluate to when cond is True.

  • if_false (Cell) – Cell to evaluate to when cond is False. If None (the default), the value of the returned cell is preserved when cond evaluates to False.

Returns:

A new cell.

Type:

Cell

property value

The value of the cell.

wait(*cells, **kwargs)

Create a wait cell, as if by waited and access its value.

Calling this function is equivalent to:

waited(self, *cells, **kwargs)()

This function accepts the same positional and keyword arguments as waited.

Returns:

The value of the wait cell

waited(*cells, **kwargs)

Create a wait cell that awaits one or more asynchronous cells.

The value of the returned cell is the completed value of the awaitable held in self. If the awaitable, or the cell self itself, raises an exception then accessing the value of the returned cell raises the same exception.

Important

If the value of the returned cell is accessed before the coroutine held in self has completed, a PendingAsyncValueError exception is raised.

If multiple arguments are given, a cell is returned that awaits the awaitables held in self and each cell in cells. The value of the cell is a list holding the completed value of self followed by the completed value of each cell in cells. This is equivalent to the following:

[await self(), await cells[0](), ...]

The difference between a single call to waited:

@computed
def sum():
    x, y = waited(a, b)()
    return x, y

and multiple calls to waited:

@computed
def sum():
    return a.waited()() + b.waited()()

becomes apparent when an update to the asynchronous cells is triggered by a common ancestor of the cells. With a single call to waited, the value of the sum cell is recomputed only once when both the awaitables held in a and b have completed. In the second example, the value of sum is recomputed once when the awaitable held in a has completed and a second time when the awaitable held in b has completed.

This function also accepts a number of keyword arguments that modify the behaviour of the cell.

The reset keyword argument controls whether the value of the cell is reset when the values of the asynchronous cells changes.

By default this is True, which means that when the values of the asynchronous cells changes the value of the returned wait cell is reset. Accessing the value of the returned cell at this point results in a PendingAsyncValueError exception being raised, until the awaitables held in the asynchronous cells have completed.

async def coro1():
    await asyncio.sleep(1)
    return 1

async def coro2():
    await asyncio.sleep(1)
    return 2

arg = mutable(coro1)

w1 = arg.waited()
w2 = arg.waited(reset=False)

await asyncio.sleep(2)

# The values of both `w1` and `w2` are 1

arg.value = coro2

# Accessing the value of `w1` raises `PendingAsyncValueError`
# The value of `w2` is still 1

The queue keyword argument controls what happens when the values of the asynchronous cells change before the awaitables, for which the wait cell is currently waiting, have completed.

If queue is True, when the values of the asynchronous cells change, the wait cell first waits for the previous awaitables to complete, and only then waits for the new awaitables. The value of the wait cell is updated in the order in which the awaitables were assigned to the asynchronous cell and not necessarily in the order of completion.

If queue is False, the default, the wait cell only waits for the last awaitable and ignores previous awaitables that have not completed.

The following example illustrates the difference:

async def coro1():
    await asyncio.sleep(5)
    return 1

async def coro2():
    await asyncio.sleep(1)
    return 2

arg = mutable(coro1)

w1 = arg.waited(reset=False, queue=True)
w2 = arg.waited(reset=False)

@watch
def watch_w1():
    print(f'W1 = {w1()}')

@watch
def watch_w2():
    print(f'W2 = {w2()}')

# NOTE: There is no await meaning coro1 has not completed
arg.value = coro2

For w1 two lines are printed: W1 = 1 and W1 = 2, while for w2 only a single line W2 = 2 is printed.

Attention

The queue argument has no effect if reset is True.

Parameters:

cells (List[Cell]) – Additional cells to await

The following keyword arguments are accepted:

Parameters:
  • reset (bool) – If True (the default), the value of the cell is reset, whenever the values of the asynchronous cells change. Otherwise the last completed value (or exception) is retained until the new awaitables have completed.

  • queue (bool) – If true, the returned cell waits for all awaitables that were assigned to the asynchronous cell(s) to complete. If false, the cell only waits for the last awaitables that were assigned.

Returns:

The wait cell

Return type:

Cell

class live_cells.CellWatcher(callback, schedule=None)

Bases: object

Maintains the state of a cell watch function.

stop()

Stop the watch function from being called for future updates.

The watch callback will not be called again after this method is called.

exception live_cells.PendingAsyncValueError

Bases: Exception

Exception raised when accessing the value of a wait cell before the awaitable has completed.

exception live_cells.StopComputeException(default_value=None)

Bases: Exception

Exception used to indicate that the cell’s value should not be computed.

When this exception is raised inside the value computation function of a cell, the cell’s value is not updated. Instead the cell’s current value is preserved.

Parameters:

default_value – The value to initialize the cell to, if this exception is thrown while computing the initial value of the cell.

live_cells.batch()

Batch changes to mutable cells within a given managed context.

When this context manager is used, the observers of the mutable cells that are set within the with block managed by the context manager, are only notified when exiting the context.

This has no effect when used when a batching is already in effect before the context manager is created.

Example
with batch():
    a.value = 1
    b.value = 2

# Observers of `a` and `b` are only notified when
# exiting the `with` block.
live_cells.batched(fn)

Apply the batch context manager to the decorated function.

This decorator is equivalent to replacing wrapping a call to fn with the following:

with batch():
    fn()
Parameters:

fn (function) – A function

Returns:

A function that calls fn while applying cell batching.

Return type:

function

live_cells.computed(compute=None, key=None, changes_only=False)

Create a computed cell with dynamically determined arguments.

A computed cell with compute function compute is created. compute is a function of no arguments, that is called to compute the value of the cell. The cells referenced within compute, using the function call syntax, are automatically registered as dependencies of the cell such that when their values change the value of the computed cell is recomputed.

Note

This function may be used as a decorator by omitting the compute argument, in which case the decorated function is used as the compute function. The cell is then referenced using the name of the decorated function.

Parameters:
  • compute (function) – Function of no arguments called to compute the value of the cell.

  • key – Key identifying the cell if not None. Defaults to None.

  • changes_only – If True the cell only notifies its observers if its new value is not equal to its previous value. Defaults to False.

Returns:

A computed cell.

live_cells.mutable(value=None, key=None)

Create a mutable cell with an initial value.

The value of a mutable cell can be changed by setting its value property.

Parameters:
  • value – The initial value of the cell, defaults to None.

  • key – Key identifying the cell if not None, defaults to None.

Returns:

A mutable cell.

live_cells.none(default_value=None)

Stop the computation of a computed cell’s value.

When this method is called inside the value computation function of a computed cell, the cell’s value is not updated. Instead the cell’s current value is preserved.

If this function is called during the computation of the cell’s initial value, the cell’s initial value is set to default_value.

Parameters:

default_value – The value to assign to the cell if called during the computation of its initial value.

Raises:

StopComputeException – This exception is raised to signal to the enclosing computed cell to abort the computation.

live_cells.value(value)

Create a cell with a constant value.

The value of a constant cell never changes and its observers are never notified.

Note

Two constant cells compare equal if their values are equal.

Parameters:

value – The constant value of the cell.

Returns:

A constant cell.

live_cells.wait(self, *cells, **kwargs)

Create a wait cell, as if by waited and access its value.

Calling this function is equivalent to:

waited(self, *cells, **kwargs)()

This function accepts the same positional and keyword arguments as waited.

Returns:

The value of the wait cell

live_cells.waited(self, *cells, **kwargs)

Create a wait cell that awaits one or more asynchronous cells.

The value of the returned cell is the completed value of the awaitable held in self. If the awaitable, or the cell self itself, raises an exception then accessing the value of the returned cell raises the same exception.

Important

If the value of the returned cell is accessed before the coroutine held in self has completed, a PendingAsyncValueError exception is raised.

If multiple arguments are given, a cell is returned that awaits the awaitables held in self and each cell in cells. The value of the cell is a list holding the completed value of self followed by the completed value of each cell in cells. This is equivalent to the following:

[await self(), await cells[0](), ...]

The difference between a single call to waited:

@computed
def sum():
    x, y = waited(a, b)()
    return x, y

and multiple calls to waited:

@computed
def sum():
    return a.waited()() + b.waited()()

becomes apparent when an update to the asynchronous cells is triggered by a common ancestor of the cells. With a single call to waited, the value of the sum cell is recomputed only once when both the awaitables held in a and b have completed. In the second example, the value of sum is recomputed once when the awaitable held in a has completed and a second time when the awaitable held in b has completed.

This function also accepts a number of keyword arguments that modify the behaviour of the cell.

The reset keyword argument controls whether the value of the cell is reset when the values of the asynchronous cells changes.

By default this is True, which means that when the values of the asynchronous cells changes the value of the returned wait cell is reset. Accessing the value of the returned cell at this point results in a PendingAsyncValueError exception being raised, until the awaitables held in the asynchronous cells have completed.

async def coro1():
    await asyncio.sleep(1)
    return 1

async def coro2():
    await asyncio.sleep(1)
    return 2

arg = mutable(coro1)

w1 = arg.waited()
w2 = arg.waited(reset=False)

await asyncio.sleep(2)

# The values of both `w1` and `w2` are 1

arg.value = coro2

# Accessing the value of `w1` raises `PendingAsyncValueError`
# The value of `w2` is still 1

The queue keyword argument controls what happens when the values of the asynchronous cells change before the awaitables, for which the wait cell is currently waiting, have completed.

If queue is True, when the values of the asynchronous cells change, the wait cell first waits for the previous awaitables to complete, and only then waits for the new awaitables. The value of the wait cell is updated in the order in which the awaitables were assigned to the asynchronous cell and not necessarily in the order of completion.

If queue is False, the default, the wait cell only waits for the last awaitable and ignores previous awaitables that have not completed.

The following example illustrates the difference:

async def coro1():
    await asyncio.sleep(5)
    return 1

async def coro2():
    await asyncio.sleep(1)
    return 2

arg = mutable(coro1)

w1 = arg.waited(reset=False, queue=True)
w2 = arg.waited(reset=False)

@watch
def watch_w1():
    print(f'W1 = {w1()}')

@watch
def watch_w2():
    print(f'W2 = {w2()}')

# NOTE: There is no await meaning coro1 has not completed
arg.value = coro2

For w1 two lines are printed: W1 = 1 and W1 = 2, while for w2 only a single line W2 = 2 is printed.

Attention

The queue argument has no effect if reset is True.

Parameters:

cells (List[Cell]) – Additional cells to await

The following keyword arguments are accepted:

Parameters:
  • reset (bool) – If True (the default), the value of the cell is reset, whenever the values of the asynchronous cells change. Otherwise the last completed value (or exception) is retained until the new awaitables have completed.

  • queue (bool) – If true, the returned cell waits for all awaitables that were assigned to the asynchronous cell(s) to complete. If false, the cell only waits for the last awaitables that were assigned.

Returns:

The wait cell

Return type:

Cell

live_cells.watch(callback=None, schedule=None)

Register a callback to run when the values of cells change.

callback (A function of no arguments) is called once immediately to determine the cells referenced within it. It is then called again whenever the values of the referenced cells change.

To stop callback from being called for further changes to the referenced cell values, call the CellWatcher.stop method on the CellWatcher object returned by this function.

Attention

Within callback, Cells should only be referenced using the function call syntax and never by referencing the value property directly.

Note

This function may be used as a decorator by omitting the callback argument, in which case the decorated function is used as the watch function. The watch function’s CellWatcher is then referenced using the name of the decorated function.

Parameters:
  • callback (function) – The watch function.

  • schedule (function, optional) – A function which is called with the callback function provided as an argument. When this function is called, it should schedule the callback function provided to it to be called.

Returns:

The handle to the watch function’s state.

Return type:

CellWatcher