36
def search_conffile():
38
Search for the config file, and return it as a filename.
39
1. Environment var IVLECONF (full filename).
41
3. /etc/ivle/ivle.conf
41
Search for the config file, and return the directory it is in.
42
1. Environment var IVLECONF (path to directory)
42
44
Raises a ConfigError on error.
44
46
if 'IVLECONF' in os.environ:
45
fname = os.environ['IVLECONF']
47
fname = os.path.join(os.environ['IVLECONF'])
46
48
if os.path.exists(fname):
48
if os.path.exists('./etc/ivle.conf'):
49
return './etc/ivle.conf'
50
if os.path.exists('/etc/ivle/ivle.conf'):
51
return '/etc/ivle/ivle.conf'
52
raise ConfigError("Could not find IVLE config file")
50
if os.path.exists('/etc/ivle'):
52
raise ConfigError("Could not find IVLE config directory")
54
def get_plugin(pluginstr):
55
plugin_path, classname = pluginstr.split('#')
56
# Load the plugin module from somewhere in the Python path
57
# (Note that plugin_path is a fully-qualified Python module name).
59
getattr(__import__(plugin_path, fromlist=[classname]), classname))
54
62
class Config(ConfigObj):
56
64
The configuration object. Can be instantiated with no arguments (will
57
65
implicitly find the ivle.conf file and load it).
67
Automatically validates the file against the spec (found in
68
./ivle-spec.conf relative to this module).
59
def __init__(self, *args, **kwargs):
60
conffile = search_conffile()
61
super(Config, self).__init__(infile=conffile, *args, **kwargs)
70
def __init__(self, blank=False, plugins=True, *args, **kwargs):
71
"""Initialises a new Config object. Searches for the config file,
72
loads it, and validates it.
73
@param blank: If blank=True, will create a blank config instead, and
74
not search for the config file.
75
@param plugins: If True, will find and index plugins.
76
@raise ConfigError: If the config file cannot be found.
78
specfile = os.path.join(os.path.dirname(__file__), 'ivle-spec.conf')
80
super(Config, self).__init__(configspec=specfile, *args, **kwargs)
82
confdir = search_confdir()
83
conffile = os.path.join(confdir, 'ivle.conf')
84
super(Config, self).__init__(infile=conffile, configspec=specfile,
85
interpolation='template',
87
# XXX This doesn't raise errors if it doesn't validate
88
self.validate(Validator())
93
self.plugin_configs = {}
94
# Go through the plugin config files, looking for plugins.
95
for pconfn in glob.glob(os.path.join(confdir, 'plugins.d/*.conf')):
96
pconf = ConfigObj(pconfn)
97
for plugin_section in pconf:
98
# We have a plugin path. Resolve it into a class...
99
plugin_path, plugin = get_plugin(plugin_section)
100
self.plugins[plugin_path] = plugin
101
# ... and add it to the registry.
102
self.plugin_configs[plugin] = pconf[plugin_section]
104
# Create a registry mapping plugin classes to paths.
105
self.reverse_plugins = dict([(v, k) for (k, v) in
106
self.plugins.items()])
108
# Create an index of plugins by base class.
109
self.plugin_index = {}
110
for plugin in self.plugins.values():
111
# Getmro returns a tuple of all the super-classes of the plugin
112
for base in inspect.getmro(plugin):
113
if base not in self.plugin_index:
114
self.plugin_index[base] = []
115
self.plugin_index[base].append(plugin)
117
def set_by_path(self, path, value=_NO_VALUE, comment=None):
118
"""Writes a value to an option, given a '/'-separated path.
119
@param path: '/'-separated path to configuration option.
120
@param value: Optional - value to write to the option.
121
@param comment: Optional - comment string (lines separated by '\n's).
122
Note: If only a comment is being inserted, and the value does not
123
exist, fails silently.
125
path = path.split('/')
126
# Iterate over each segment of the path, and find the section in conf
127
# file to insert the value into (use all but the last path segment)
129
for seg in path[:-1]:
130
# Create the section if it isn't there
131
if seg not in conf_section:
132
conf_section[seg] = {}
133
conf_section = conf_section[seg]
134
# The final path segment names the key to insert into
136
if value is not _NO_VALUE:
137
conf_section[keyname] = value
138
if comment is not None:
140
conf_section[keyname]
144
conf_section.comments[keyname] = comment.split('\n')
146
def get_by_path(self, path):
147
"""Gets an option's value, given a '/'-separated path.
148
@param path: '/'-separated path to configuration option.
149
@raise KeyError: if no config option is at that path.
151
# Iterate over each segment of the path, and find the value in conf file
153
for seg in path.split('/'):
154
value = value[seg] # May raise KeyError