-
Notifications
You must be signed in to change notification settings - Fork 0
Willie tutorial, Part 3
Willie has a config file, written in an INI-like format. It can provide configuration options not just for the bot itself, but for modules as well. Here, we're going to cover how you can leverage that configuration, as well as how to make your module configurable in the wizard like we showed back in Part 1.
The config file is made up of a number of sections, each of which has a number of keys or attributes. If you open up your config file, you'll see something like this.
[core]
nick = Willie
host = irc.dftba.net
use_ssl = False
port = 6667
owner = Embolalia
channels = #YourPants,#tech
[admin]
hold_ground = False
[bugzilla]
domains = bugzilla.redhat.com,bugzilla.gnome.org
Here, core
and bugzilla
are sections. As you may have guessed, core
contains attributes relevant to the bot's core functionality - it's nick, the
host to connect to, etc., and bugzilla
and admin
contain attributes
relevant to two of the bot's modules.
In the context of your callable, the config file is available as an attribute
of the bot
parameter. Each section is an attribute of the config file, and
each key in a section is an attribute of its respective section. For example,
if we wanted to get the owner of the bot, we would use bot.config.core.owner
.
The config object also has a number of methods. Some of these relate to making
the wizard, which we'll discuss later. Others are helpers to make dealing with
the config a bit easier. For example, instead of trying to split up those
bugzilla domains ourselves, we can use bot.config.bugzilla.get_list('domains')
.
This takes care of splitting up that list for us.
Changing attributes is as easy as just assigning a value to them. You should
probably avoid doing this in the core
section from your module, unless you
know what you're doing. But if, for example, you wanted to change hold_ground
to True, you would simply do bot.config.admin.hold_ground = True
. You can
also do this with lists. If you wanted to add bugzilla.mozilla.org
to the
list of bugzilla domains, you could do
bot.config.bugzilla.domains = ['bugzilla.redhat.com', 'bugzilla.gnome.org', 'bugzilla.mozilla.org']
and it would change it properly. If you do an assignement to a config attribute
that doesn't exist, it will create it for you. However, changes aren't
automatically written to the config file itself, so they'll disappear when you
restart the bot unless you call bot.config.save()
.
You may want to make a script that will help users in configuring your module. This is helpful for when new users are setting up your script for the first time. You can provide them with an easy way to set up the options, and even test to make sure they gave you options that make sense.
This is done through a special function in your module, called configure
. It
is different from the callables you made in the previous sections. When it's
called, the bot isn't actually running, you're just interfacing with the user
in the terminal. The function is passed just one argument, config
, which is
the same as the bot.config
you would get in one of your callables.
What you'll probably want to do first in here is ask whether the user actually
wants to configure your module. They may just want to ignore it for now, and
configure it later (especially if the setting of these config values isn't
critical to making your module work.) You can do this with
config.option(question, default)
. This asks the given question (which you
should give it without the question mark; it adds one on its own). If the user
just hits enter without giving an answer, it defaults to the given default. If
you just give it the question, with no default, the default will be False. The
choice the user makes will be returned as a boolean; either True or False.
Next, you'll probably want to create a section in the config file for your
module by doing config.add_section('yourmodulename')
. The name should
probably be the same as your module's name. From there, there are four
functions that you'll probably rely on most:
-
interactive_add(section, option, prompt, default=None)
will add a new key to the section you specify, with the name you specify with "option". It will give the user the prompt you specify. You don't have to pass default, but if you do, it will use that as the default answer. You can also use that as an example value, as long as it won't cause you problems later on. If the value has already been configured, that will always be the default used here whether you provide one or not. -
add_list(section, option, message, prompt)
is likeinteractive_add
, but it makes a list. If there are already values there, it will ask if the user wants to keep them before proceeding. -
add_option(section, option, question, default=False)
This is like theoption
function above, but it saves the value to the given section and value.
You don't need to worry about saving at the end of this function; the wizard will do that for you. It's a good idea to check the values to make sure they're valid. If it's a file the bot should write to, for example, make sure you have permissions to do so. It's better to find a problem here, since you can immediately get the user to fix it.
Another special function is setup
. Like configure
, it's a bit special. This
function is run when the module is loaded. You should use this to make sure
everything is properly set up for your module to function properly. It is
passed one argument, bot
, but it's a bit different from the one you get in
your callables. Like normal, it has access to the config
file, the database,
and most of the rest. However, since this is run before the bot has completely
finished booting up, it's not guaranteed that it has finished connecting to the
server yet. As such, functions that send messages to the server, like msg
,
might not work as expected in here. Additionally, since it's not triggered from
a message but from within the bot itself, say
and reply
don't work at all
(they wouldn't know where they're replying to).
It's a good idea that you check that things like config options you rely on later are here and valid. We'll talk about memory keys and the database later on, and setting those up is often done in this function.
If you find a problem with something here - a vital config option is missing or
something like that - which you can't recover from on your own, you may decide
to throw some sort of exception, which will prevent the rest of the module from
loading. (You can import willie.config.ConfigurationError
and raise it for
this, if it's a problem with the config file.) This way, you can assume in the
rest of your module that everything you check here is in order.