Configuration File Handling¶
Handlers for text configuration files. Configurations are simple string to string mappings, with the configuration files using the following rules…
the key/value is separated by a space
anything after a ‘#’ is ignored as a comment
excess whitespace is trimmed
empty lines are ignored
multi-line values can be defined by following the key with lines starting with a ‘|’
For instance…
# This is my sample config
user.name Galen
user.password yabba1234 # here's an inline comment
user.notes takes a fancy to pepperjack cheese
blankEntry.example
msg.greeting
|Multi-line message exclaiming of the
|wonder and awe that is pepperjack!
… would be loaded as…
config = {
'user.name': 'Galen',
'user.password': 'yabba1234',
'user.notes': 'takes a fancy to pepperjack cheese',
'blankEntry.example': '',
'msg.greeting': 'Multi-line message exclaiming of the\nwonder and awe that is pepperjack!',
}
Configurations are managed via the Config
class. The
Config
can be be used directly with its
get()
and set()
methods, but usually modules will want a local dictionary with just the
configurations that it cares about.
To do this use the config_dict()
function. For example…
import getpass
from stem.util import conf, connection
def config_validator(key, value):
if key == 'timeout':
# require at least a one second timeout
return max(1, value)
elif key == 'endpoint':
if not connection.is_valid_ipv4_address(value):
raise ValueError("'%s' isn't a valid IPv4 address" % value)
elif key == 'port':
if not connection.is_valid_port(value):
raise ValueError("'%s' isn't a valid port" % value)
elif key == 'retries':
# negative retries really don't make sense
return max(0, value)
CONFIG = conf.config_dict('ssh_login', {
'username': getpass.getuser(),
'password': '',
'timeout': 10,
'endpoint': '263.12.8.0',
'port': 22,
'reconnect': False,
'retries': 3,
}, config_validator)
There’s several things going on here so lets take it step by step…
The
config_dict()
provides a dictionary that’s bound to a given configuration. If the “ssh_proxy_config” configuration changes then so will the contents of CONFIG.The dictionary we’re passing to
config_dict()
provides two important pieces of information: default values and their types. See the Config’sget()
method for how these type inferences work.The config_validator is a hook we’re adding to make sure CONFIG only gets values we think are valid. In this case it ensures that our timeout value is at least one second, and rejects endpoints or ports that are invalid.
Now lets say our user has the following configuration file…
username waddle_doo
password jabberwocky
timeout -15
port 9000000
retries lots
reconnect true
logging debug
… and we load it as follows…
>>> from stem.util import conf
>>> our_config = conf.get_config('ssh_login')
>>> our_config.load('/home/atagar/user_config')
>>> print CONFIG
{
"username": "waddle_doo",
"password": "jabberwocky",
"timeout": 1,
"endpoint": "263.12.8.0",
"port": 22,
"reconnect": True,
"retries": 3,
}
Here’s an expanation of what happened…
the username, password, and reconnect attributes took the values in the configuration file
the ‘config_validator’ we added earlier allows for a minimum timeout of one and rejected the invalid port (with a log message)
we weren’t able to convert the retries’ “lots” value to an integer so it kept its default value and logged a warning
the user didn’t supply an endpoint so that remained unchanged
our CONFIG didn’t have a ‘logging’ attribute so it was ignored
Module Overview:
config_dict - provides a dictionary that's kept in sync with our config
get_config - singleton for getting configurations
uses_settings - provides an annotation for functions that use configurations
parse_enum_csv - helper funcion for parsing confguration entries for enums
Config - Custom configuration
|- load - reads a configuration file
|- save - writes the current configuration to a file
|- clear - empties our loaded configuration contents
|- add_listener - notifies the given listener when an update occurs
|- clear_listeners - removes any attached listeners
|- keys - provides keys in the loaded configuration
|- set - sets the given key/value pair
|- unused_keys - provides keys that have never been requested
|- get - provides the value for a given key, with type inference
+- get_value - provides the value for a given key as a string