Runner & config¶
The easiest way to get a host up is by running IMMP using the built-in runner:
$ immp [-w] <config file>
The expected configuration method is via a config file. Most file formats are understood, as long as the relevant parser libraries are installed (e.g. PyYAML for YAML files).
Pass -w
to have the runner write the current config back to the file on exit. This is useful
for plugs and hooks that change their state at runtime (e.g. commands to manage their settings).
Note that any comments in the file will be lost – it will be regenerated from scratch.
IMMP is config-driven: plugs and hooks are all created with a given configuration. This allows for a richer specification to suit each instance, and means all instances can be created in the same way with the same basic arguments.
The examples below assume a YAML config file for succinctness.
Plugs¶
Plug directives go under a root plugs
section of the config. Each plug instance has a name,
which can be referenced elsewhere in the config, and needs a path
attribute to the
corresponding Python module and class. A config
subkey is generally needed to provide
plug-specific options.
A sample plug config may look like this:
plugs:
demo:
path: demo.DemoPlug
config:
api-key: xyzzy
Channels¶
Most networks will provide multiple “rooms” or “conversations” where messages come from, which are all handled by a single plug. A channel is used to specify which rooms are monitored.
Channels are used to name and pair room identifiers with the plug they belong to:
channels:
foo:
plug: demo
source: 12345
bar:
plug: demo
source: 98765
Groups¶
A group defines a set of plugs, or a subset of their channels, and can be referenced by hooks to limit the scope of their actions, for example to provide features only in private or named channels.
Each group can contain channels
, a list of individual channels to be included, or lists of
certain categories of plugs:
private
: all private channels from this plugshared
: all non-private channels from this plugnamed
: all channels from this plug declared in the channels section aboveanywhere
: all channels provided by this plug (i.e.private
+shared
)
You can also declare exclude
alongside categories, to remove named channels individually.
groups:
secure:
channels: [foo, bar]
private: [demo-x, demo-y]
named: [demo-z]
Hooks¶
Hooks are configured in essentially the same way as plugs. A common idiom for hooks is to accept a list of group or channel names where the hook should apply:
hooks:
test:
path: test.TestHook
priority: 1
config:
groups: [secure]
args: [123, 456]
Hooks accept an optional top-level property: priority
. If specified as an integer, it defines
the order in which hooks receive each new message, lowest first. This will incur a performance
penalty as prioritised hooks run in serial, so only apply to those that need it – hooks without a
priority will all run against each message in parallel.
Search path¶
During development, or when working with a third-party module, you may want to include plugs or
hooks from Python modules outside the usual search path. You can do this by setting path
to a
list of additional paths, which will be added to sys.path
.
path:
- /path/to/repo/a
- /path/to/repo/b
If you have a hook YourHook
defined in /path/to/repo/a/module/file.py, you would use
module.file.YourHook
as its path.
Logging¶
By default, only startup and shutdown messages are displayed. To see what’s going on under the
hood, you can provide your own logging options, suitable for Python’s logging.config
:
logging:
version: 1
handlers:
console:
class: logging.StreamHandler
level: INFO
file:
class: logging.FileHandler
filename: debug.log
level: DEBUG
loggers:
immp:
level: DEBUG
asyncio:
level: ERROR
root:
level: WARNING
handlers: [console, file]
This example defines behaviour for both stdout (at info level) and a log file (debug level), with IMMP’s full output and warnings/errors for external modules included.