sunflare.engine#

class sunflare.engine.Status(*, timeout=None, settle_time=0)#

Track the status of a potentially-lengthy action like moving or triggering.

Parameters:
  • timeout (float, optional) – The amount of time to wait before marking the Status as failed. If None (default) wait forever. It is strongly encouraged to set a finite timeout. If settle_time below is set, that time is added to the effective timeout.

  • settle_time (float, optional) – The amount of time to wait between the caller specifying that the status has completed to running callbacks. Default is 0.

Notes

Theory of operation:

This employs two threading.Event objects, one thread that runs for (timeout + settle_time) seconds, and one thread that runs for settle_time seconds (if settle_time is nonzero).

At __init__ time, a timeout and settle_time are specified. A thread is started, on which user callbacks, registered after __init__ time via add_callback(), will eventually be run. The thread waits on an Event be set or (timeout + settle_time) seconds to pass, whichever happens first.

If (timeout + settle_time) expires and the Event has not been set, an internal Exception is set to StatusTimeoutError, and a second Event is set, marking the Status as done and failed. The callbacks are run.

If a callback is registered after the Status is done, it will be run immediately.

If the first Event is set before (timeout + settle_time) expires, then the second Event is set and no internal Exception is set, marking the Status as done and successful. The callbacks are run.

There are two methods that directly set the first Event. One, :meth:set_exception, sets it directly after setting the internal Exception. The other, set_finished(), starts a threading.Timer that will set it after a delay (the settle_time). One of these methods may be called, and at most once. If one is called twice or if both are called, InvalidState is raised. If they are called too late to prevent a StatusTimeoutError, they are ignored but one call is still allowed. Thus, an external callback, e.g. pyepics, may reports success or failure after the Status object has expired, but to no effect because the callbacks have already been called and the program has moved on.

property timeout: float | None#

The timeout for this action.

This is set when the Status is created, and it cannot be changed.

property settle_time: float#

A delay between when set_finished() is when the Status is done.

This is set when the Status is created, and it cannot be changed.

property done: bool#

Boolean indicating whether associated operation has completed.

This is set to True at __init__ time or by calling set_finished(), set_exception(). Once True, it can never become False.

property success: bool#

Boolean indicating whether associated operation has completed.

This is set to True at __init__ time or by calling set_finished(), set_exception() . Once True, it can never become False.

set_exception(exc)#

Mark as finished but failed with the given Exception.

This method should generally not be called by the recipient of this Status object, but only by the object that created and returned it.

Parameters:

exc (Exception)

Return type:

None

set_finished()#

Mark as finished successfully.

This method should generally not be called by the recipient of this Status object, but only by the object that created and returned it.

Return type:

None

exception(timeout=None)#

Return the exception raised by the action.

If the action has completed successfully, return None. If it has finished in error, return the exception.

Parameters:

timeout (Union[Number, None], optional) – If None (default) wait indefinitely until the status finishes.

Returns:

The exception raised by the action. If the action has completed successfully, return None.

Return type:

Exception

Raises:

WaitTimeoutError – If the status has not completed within timeout (starting from when this method was called, not from the beginning of the action).

wait(timeout=None)#

Block until the action completes.

When the action has finished succesfully, return None. If the action has failed, raise the exception.

Parameters:

timeout (float, optional) – If None (default) wait indefinitely until the status finishes.

Raises:
  • WaitTimeoutError – If the status has not completed within timeout (starting from when this method was called, not from the beginning of the action).

  • StatusTimeoutError – If the status has failed because the timeout that it was initialized with has expired.

  • Exception – This is status.exception(), raised if the status has finished with an error. This may include TimeoutError, which indicates that the action itself raised TimeoutError, distinct from WaitTimeoutError above.

Return type:

None

property callbacks: deque[Callable[[Status], None]]#

Callbacks to be run when the status is marked as finished.

add_callback(callback)#

Register a callback to be called once when the Status finishes.

The callback will be called exactly once. If the Status is finished before a callback is added, it will be called immediately. This is threadsafe. The callback will be called regardless of success of failure. The callback has access to this status object, so it can distinguish success or failure by inspecting the object.

Parameters:

callback (Callable[[Status], None]) –

The callback to be called when the status is marked as finished.

def callback(status: Status) -> None:
    # Do something with the status object
    ...

Return type:

None

class sunflare.engine.RunEngine(*args, **kwargs)#

Subclass of bluesky.run_engine.RunEngine to allow execution in a separate thread.

Additional features:

  • socket: A ZMQ socket to send messages to a remote endpoint;

  • socket_prefix: A prefix to be used in the ZMQ topic when sending messages.

When launching a plan, the RunEngine, the __call__ method returns a Future object. This allows to set a callback on the future to retrieve the result of the execution. Alternatively, the result can be accessed directly from the result attribute when the future is done.

Suppressed features:

  • context_managers: The context managers are forced to be an empty list to avoid the use of the built-in SignalHandler context manager.

The rationale is that the original implementation is meant for interactive usage (e.g., Jupyter notebooks, scripts) and not for applications relying on an event loop.

  • pause_msg: Overridden to be an empty string.

  • during_task: Overridden to DuringTask, so the RunEngine does not interact with any possible event loop in the main thread.

For the original class initializer signature, refer to the RunEngine documentation.

Parameters:
  • socket_prefix (str, keyword-only, optional) – Prefix to be used in the ZMQ topic when sending messages. Default is RE{N}, where {N} is a counter that increments for each instance.

  • socket (zmq.Socket[bytes], keyword-only, optional) – ZMQ socket to send messages to a remote endpoint. Default is None (no messages are sent).

  • args (Any)

  • kwargs (Any)

emit_sync(name, doc)#

Emit a document synchronously.

Reimplemented to send documents also through a ZMQ socket.

Warning

This method is not meant to be used directly. The RunEngine will emit documents automatically during the execution of a plan. Any subscriber will receive the documents.

Parameters:
  • name (DocumentNames)

  • doc (dict[str, Any])

Return type:

None

class sunflare.engine.RunEngineResult(run_start_uids, plan_result, exit_status, interrupted, reason, exception)#

Information about the plan that was run

Parameters:
  • run_start_uids (tuple[str, ...])

  • plan_result (Any)

  • exit_status (str)

  • interrupted (bool)

  • reason (str)

  • exception (Exception | None)

run_start_uids#

A list of the UIDs generated during the plan (if any)

Type:

list

plan_result#

The return value of the top-level plan that was run

Type:

Any

exit_status#
Type:

str

interrupted#

True if the plan was halted, stopped or aborted

Type:

bool

reason#

A text description of the reason why the plan was aborted (if aborted)

Type:

str

exception#

The exception generated by the plan, if any

Type:

Exception | None