Configurators
Configurators allow a program to run a configuration
defined elsewhere and registred with an abstract address.
The program will create a Configurator and call its
run() method
cfg = Configurator("some-abstract-address")
cfg.run()
When this code is executed, a lookup is performed in
configoose’s database to see if a configuration file has
been registered for the address "some-abstract-address".
If no such file has been registered, an exception is raised
unless missing_ok=True is passed to run().
Adding protocols
The above code alone does not suffice to process the configuration content that is contained in the file. For this one must declare one or more protocols in the configurator, so the code now looks like
cfg = Configurator("some-abstract-address")
cfg.add_protocol("some.Protocol")
cfg.add_protocol("some.other.Protocol")
cfg.run()
Now when the run() method is called and a configuration file
is found, configoose will look if the protocol defined in the
configuration file matches one of the protocols that were added to
the Configurator instance.
If one of the protocol matches, an instance of the corresponding
subclass of Protocol is created and the protocol’s
own run() method is called with the data found in the configuration
file.
This system enables programs to accept several ways of configuring themselves, for example a program could accept configuration files in the form of ini files or json files or toml files by adding three protocols to the configurator, one for each type of configuration file.
The first argument in add_protocol() is a string representing
a dotted path in Python’s modules system to the target protocol class.
For example to use configoose’s raw configuration protocol,
one would pass "configoose.protocol.raw.Protocol" because
the target class is the class Protocol defined in
module configoose.protocol.raw.
Handler functions
What protocols do in their run() method is specific to each
protocol class.
A mechanism is provided so that these run() method can call
a function provided by the client program, namely the program can
define handler functions when protocols are added. The syntax is
@cfg.add_protocol("some.protocol")
def handler(...):
...
Another way to declare the same thing is
cfg.add_protocol("some.protocol", handler=handler)
The arguments of the handler function depend on the protocol, but typically they include data extracted from the configuration file.
An example with the raw protocol
The raw protocol accepts arbitrary text in the configuration file and it passes that text to the handler function. A program could define the following
cfg = Configurator("some-abstract-address")
@cfg.add_protocol("configoose.protocol.raw.Protocol")
def handler(ap, preamble, text, mediator):
print(text)
cfg.run()
The effect of this code is to print the text found in the configuration file. A configuration file for this Python program could contain
{
"address" : "some-abstract-address",
"protopath" : "configoose.protocol.raw.Protocol",
}
spam spam eggs
eggs eggs and more spam
ham * 3
Upon program execution, the following would be printed in the output
spam spam eggs
eggs eggs and more spam
ham * 3