Advanced settings¶
All configuration in crontabber
is handled by the fact that it’s built
on top of configman. configman
is agnostic to configuration file
format (e.g. .ini
or .json
) and that means you can reference much more
than just strings and integers. For example, you can reference Python
classes by their name and they get imported automatically when need be.
We strongly recommend that when you write a crontabber
app that you
set a sensibile default and only use a configuration file when you
need to override it. Sometimes you can’t put in a sensible default as
the value can’t be written in code. Like a password for example.
Setting up settings¶
The trick to adding configuration is to set a class attribute on your
crontabber
app called required_config
. Let’s dive straight
into an example:
import datetime
from crontabber.base import BaseCronApp
from configman import Namespace
class MyFirstConfigApp(BaseCronApp):
app_name = 'my-first-config-app'
required_config = Namespace()
required_config.add_option(
'date_format',
default='%m/%d %Y - %H:%M',
doc="Format for how the date is reported in the log file."
)
def run(self):
with open(self.app_name + '.log', 'a') as f:
dt = datetime.datetime.now()
f.write('Now is %s\n' % dt.strftime(self.config.date_format))
The magic to notice is how you import Namespace
from configman
,
create a class attribute called required_config
and then inside the
run()
method you can reference to by self.config.date_format
.
Overriding settings¶
So, there are now two ways of overriding this other than letting the
default value play. You can either do it in your existing configuration
file (crontabber.ini
if you’ve played along from the
Introduction) or you can do it right on the
command line as local environment variables.
If you intend to use non-trivial notation for environment variables in bash
you have to prefix the command with a program called env
that is
built in on almost all version of bash. So, here’s an example of doing
just that:
env crontabber.class-MyFirstConfigApp.date_format="%A" crontabber --admin.conf=crontabber.ini
Run that and you’ll notice it picked up the override setting.
Another way of specifying this is in your crontabber.ini
file. Note!
Setting this requires that you do it under the [crontabber]
section
heading. It looks like this:
...
[crontabber]
...
[[class-MyFirstConfigApp]]
# Format for how the date is reported in the log file.
date_format=%W %y %h:%M
If you ever forget this notation, after you have added some setting options you can run:
crontabber --admin.conf=crontabber.ini --admin.print_conf=ini
and look at the commented out examples.
Now, run it again and it should pick this up. Now you don’t need to specify anything extra on the command line, so you can use:
crontabber --admin.conf=crontabber.ini
Let’s now make a setting that is something the app needs to
import (as a Python module, class or function) on the fly. Let’s say
we want override what function our simple app uses to generate the datetime.
So we add another config called date_function
and tell the config that
this is something it needs to import:
import datetime
from crontabber.base import BaseCronApp
from configman import Namespace
class MyFirstConfigApp(BaseCronApp):
app_name = 'my-first-config-app'
required_config = Namespace()
required_config.add_option(
'date_format',
default='%m/%d %Y - %H:%M',
doc="Format for how the date is reported in the log file."
)
required_config.add_option(
'date_function',
default=datetime.datetime.now,
doc="Function that generates datetime instance"
)
def run(self):
with open(self.app_name + '.log', 'a') as f:
dt = self.config.date_function()
f.write('Now is %s\n' % dt.strftime(self.config.date_format))
Configman automatically notices that the default isn’t a string but something
pythonic that it can use. But if you want to change that, in a
crontabber.ini
file you have to reference it as a string. How do you do
that? This trick isn’t for the faint of heart but it’s very powerful one.
What you do is you write a from_string_converter
function.
Mind you, this is a rather odd and complicated example but it shows the power of being able to change anything from a config file:
import datetime
from crontabber.base import BaseCronApp
from configman import Namespace
def function_converter(function_reference):
module, callable, function = function_reference.rsplit('.', 2)
module = __import__(module, globals())
callable = getattr(module, callable)
return getattr(callable, function)
class MyFirstConfigApp(BaseCronApp):
app_name = 'my-first-config-app'
required_config = Namespace()
required_config.add_option(
'date_format',
default='%m/%d %Y - %H:%M',
doc="Format for how the date is reported in the log file."
)
required_config.add_option(
'date_function',
default=datetime.datetime.now,
doc="Function that generates datetime instance",
from_string_converter=function_converter
)
def run(self):
with open(self.app_name + '.log', 'a') as f:
dt = self.config.date_function()
f.write('Now is %s\n' % dt.strftime(self.config.date_format))
Now, let’s try this out on the command line:
env crontabber.class-MyFirstConfigApp.date_function="datetime.datetime.utcnow"\
crontabber --admin.conf=crontabber.ini
The documentation on configman has more examples of using the
from_string_converter
.