API¶
-
class
approxeng.task.
Resource
(name, dependencies=None)[source]¶ Abstract base class for resources, things which are used by tasks and which may have a lifecycle. When a new task is started, any resources the task requires are started. On each task tick the value method is called on each resource and is used to populate the world dict passed to the task function. When the task is shut down each resource has its shutdown function called.
-
__init__
(name, dependencies=None)[source]¶ - Parameters
name – Name used when referencing this resource
dependencies – Optional list of strings containing names of resources which this resource depends upon. This does a number of things, firstly it determines the order of startup and shutdown (with resources being started after their dependencies and shut down before them), and secondly it causes any specified dependencies to be provided as parameters to the value(..) method.
-
abstract
shutdown
()[source]¶ Called after a task which used this resource has finished. Also called if another resource is registered with the same name, or if the task loop exits. You must implement this to handle multiple calls sensibly, i.e. check that you haven’t already tidied up, don’t assume this will only be called after the resource has been started.
-
-
class
approxeng.task.
SimpleResource
(name, value_func, startup_func=None, shutdown_func=None)[source]¶ Simple resource constructed with value, and optional setup / teardown functions.
-
__init__
(name, value_func, startup_func=None, shutdown_func=None)[source]¶ - Parameters
name – Name used when referencing this resource
dependencies – Optional list of strings containing names of resources which this resource depends upon. This does a number of things, firstly it determines the order of startup and shutdown (with resources being started after their dependencies and shut down before them), and secondly it causes any specified dependencies to be provided as parameters to the value(..) method.
-
shutdown
()[source]¶ Called after a task which used this resource has finished. Also called if another resource is registered with the same name, or if the task loop exits. You must implement this to handle multiple calls sensibly, i.e. check that you haven’t already tidied up, don’t assume this will only be called after the resource has been started.
-
-
class
approxeng.task.
SimpleTask
(task_function, name)[source]¶ Class that wraps a single task function, including basic state consisting of an initially blank dict that the task can safely write to and read from for the duration of the run.
The function wrapped by the task can accept any or all of the following parameters:
state : passed the state dict, persists across multiple calls within a task session. world : passed the world state, consisting of a set of named resources as requested by the task specification. count : monotonically ascending tick count across the entire application.
-
__init__
(task_function, name)[source]¶ Create a new simple task instance, this is generally going to be called from within the library when wrapping a task function.
- Parameters
task_function – A function which will be called every tick while this task is active. If the function accepts parameters, these are interpreted as the names of resources required by the task, and provided when the function is called.
name – The name of the task, this is only really used internally for logging, the canonical name is defined by the key under which the task is registered.
-
tick
(world)[source]¶ A single task tick. Calls the task function, supplying it with whatever parameters it needs.
- Parameters
world – World state, set of resources accessible as properties.
- Returns
The return value from the task function. As elsewhere, this is interpreted as follows: None - don’t change anything, keep this task running, call it again TaskStop - exit from the task processing loop, shutting down the process Task or String - shut this task down, set the named or provided task as the current task
-
-
class
approxeng.task.
Task
(name, resources=None)[source]¶ Abstract base class for tasks, things which are called repeatedly to perform some higher function.
-
class
World
(resources, global_count, task_count)[source]¶ The world that the task tick sees, consists of all resources the task said it needed.
-
__init__
(name, resources=None)[source]¶ Create a new task
- Parameters
name – Name used internally by this task
resources – A string, or list of strings, containing names of resources which must be available for this task to function. Any such resources will be initialised and shutdown alongside the task itself. If this is set to None then all resources registered will be available, otherwise only those explicitly named here will be accessible from the task logic.
-
do_startup
()[source]¶ If this task is not currently active, call startup on any required resources, then call startup on the task implementation. No need to call this explicitly as it’s called if the task isn’t active on the first tick.
-
do_tick
()[source]¶ Start up the task, if needed, then call the tick method, passing in the world and tick count.
-
property
resources
¶ A list of names of resources needed by this task, if this was originally set to None then this returns a list containing all the registered resource names.
-
abstract
tick
(world)[source]¶ Called every tick, do your stuff here!
- Parameters
world – A world object, access any required resources through properties on this object.
- Returns
Used to signal what to do at the end of the tick: None - continue, call the same task again True - exit from the task loop. Probably don’t do this, instead… …String or Task - shut this task down and set the specified task (name or direct reference) to be the active one. If you want to exit the best way to do so is to delegate to the exit task, or to a custom task which gracefully shuts down your hardware before exiting from the loop.
-
class
-
class
approxeng.task.
TaskStop
(return_value=None)[source]¶ Wraps a single value, defaulting to None. If a task returns an instance of this class, the task loop will exit and the return value of the run() function will be the wrapped value. This allows tasks to exit the loop and pass information to the caller as they do so.
-
approxeng.task.
exit_task
(error=None)[source]¶ Exit the loop. If there was an exception raised causing this task to run then wrap the exception in the TaskStop, otherwise it’ll be empty.
-
approxeng.task.
get_resource_total_order
(resources=None)[source]¶ Resolve a set of resources into an ordering which respects any dependencies, this will also extend the supplied list to include any transitive dependencies if required.
- Parameters
resources – An iterable of resource names, or None to use all names
- Returns
A list of resource names such that no resource depends on a resource later in the list
-
approxeng.task.
register_resource
(name, value)[source]¶ Explicitly register a value as a resource. If the value is a function then wrap it up as the value() method of a resource class instance. If it is already a resource class instance just register it. If it’s a plain static value then wrap it in a function that always returns that value, then wrap that up in the simple class.
-
approxeng.task.
register_task
(name, value)[source]¶ Explicitly register a task, either from a function or from an instance of Task
- Parameters
name – Name used to reference the task
value – Either a task function, in which case this behaves as if the function were annotated with @task, or a Task object. You may want to use the latter, more verbose, form if extensive setup or custom state handling is needed by your task, although in general most of such handling should be done with resources and tasks themselves should remain largely state free.
-
approxeng.task.
resource
(_func=None, *, name=None)[source]¶ Decorator to indicate that a function produces a resource. If the resource is a static value you should probably use the register_resource instead.
-
approxeng.task.
run
(root_task, error_task='exit', check_tasks=None, raise_exceptions=False)[source]¶ Run the task loop!
- Parameters
root_task – The first task to start with
error_task – The task to switch to if an exception occurs, defaults to the ExitTask to exit the loop. If you have hardware such as motors that you need to ensure is deactivated, the best approach is to have a task that only does hardware shutdown, handles any errors with that process internally, and then delegates to the exit task to stop the task look. Defaults to the exit task if not specified.
check_tasks – A sequence of functions which will be called before each tick of the selected task. If any of them return then the return value is used instead of calling and using the value of the task’s tick. This can be done to handle cases like ‘make the home button always jump back to the root task’, or ‘exit the task loop on low battery conditions’ or similar. Don’t put too much logic here, it’ll get called every tick. Also good for cases where you absolutely want to bail if hardware isn’t available (joystick out of range is a particular case)
raise_exceptions – Defaults to False, if set to True then any exceptions raised by a task will be handled, then wrapped in a TaskException and raised from this call. If False then they will be handled, and control passed to the designated error task.
- Returns
If the loop exits as the result of a task returning a
TaskStop
it will return the value wrapped by that instance, otherwise None.
-
approxeng.task.
task
(_func=None, *, name=None)[source]¶ Decorator to indicate that a function is a simple task. The function will be registered, using either the name if explicitly provided, or the name of the function otherwise.
Not particularly clever implementation of
MenuTask
that uses print statements andinput()
to get menu choices. Has the advantage of working with no additional resources, so handy for testing.Don’t display here, because we block on input so if we did this properly we’d end up waiting for the user to enter a response before then showing them the options. While this is amusing, it’s probably not helpful.
Print the menu, then prompt the user to select an index or, if parent is defined,
u
to to up.
An enumeration.
A single menu, consisting of a title and a set of items, each of which will launch a task when selected. Optionally menus may have a parent.
Create a new task
- Parameters
name – Name used internally by this task
resources – A string, or list of strings, containing names of resources which must be available for this task to function. Any such resources will be initialised and shutdown alongside the task itself. If this is set to None then all resources registered will be available, otherwise only those explicitly named here will be accessible from the task logic.
Display the current menu state
- Parameters
world – Provides any resources needed to display the menu
title – Title for the current menu
item_title – Title for the currently selected item
item_index – Index of the currently selected item
item_count – Number of available items
Get the action, if any, to take on this menu item.
- Parameters
world – Provides any resources needed to read the appropriate action
- Returns
None for no action, or an instance of
MenuAction
for navigation, or an int to immediately select that index item.
Implement to provide shutdown logic for the task.
- Internal
Called every tick, do your stuff here!
- Parameters
world – A world object, access any required resources through properties on this object.
- Returns
Used to signal what to do at the end of the tick: None - continue, call the same task again True - exit from the task loop. Probably don’t do this, instead… …String or Task - shut this task down and set the specified task (name or direct reference) to be the active one. If you want to exit the best way to do so is to delegate to the exit task, or to a custom task which gracefully shuts down your hardware before exiting from the loop.
- Parameters
menu_dicts – A sequence of dicts, each of which defines a menu. Each menu follows the structure described in Menu Definitions.
menu_task_class – The subclass of
MenuTask
to be used when displaying and navigating the resultant menus. Instances of this task will be constructed for each menu in the menu_dicts input.resources – A list of names of resources which should be made available to the menu task instances. These are generally going to be a display and some kind of input facility and will be used when displaying and receiving navigation instructions.
- Returns
A list of all the new task names created. Task names which are created dynamically are included, these will appear if you have any nested (anonymous) menus, or any return values as both of these are mapped to new tasks which have to be named on the fly to ensure uniqueness.
- Parameters
filename – Filename of a YAML file, should contain a top level list as defined in Menu Definitions.
menu_task_class – The subclass of
MenuTask
to be used when displaying and navigating the resultant menus. Instances of this task will be constructed for each menu in the menu_dicts input.resources – A list of names of resources which should be made available to the menu task instances. These are generally going to be a display and some kind of input facility and will be used when displaying and receiving navigation instructions.
- Returns
A list of all the new task names created. Task names which are created dynamically are included, these will appear if you have any nested (anonymous) menus, or any return values as both of these are mapped to new tasks which have to be named on the fly to ensure uniqueness.