2
# This file is part of Checkbox.
4
# Copyright 2008 Canonical Ltd.
6
# Checkbox is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
11
# Checkbox is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
25
from checkbox.lib.cache import cache
26
from checkbox.lib.path import path_expand_recursive
28
from checkbox.properties import List, String
29
from checkbox.variables import get_variables
32
class ComponentSection(object):
34
Component section which is essentially a container of modules. These
35
map to the modules referenced in the configuration passed as argument
39
modules = List(type=String())
40
whitelist = List(type=String(), default_factory=lambda:"")
41
blacklist = List(type=String(), default_factory=lambda:"")
43
def __init__(self, config, name):
45
Constructor which takes a configuration instance and name as
46
argument. The former is expected to contain modules.
51
self.modules = config.modules
52
self.whitelist = config.get("whitelist")
53
self.blacklist = config.get("blacklist")
58
Get all the module names contained in the filenames or directories
61
whitelist_patterns = [re.compile(r"^%s$" % r) for r in self.whitelist]
62
blacklist_patterns = [re.compile(r"^%s$" % r) for r in self.blacklist]
66
filenames = itertools.chain(*[path_expand_recursive(m)
67
for m in self.modules])
68
for filename in filenames:
69
name = posixpath.basename(filename)
70
if not name.endswith(".py") or name == "__init__.py":
74
name = name.replace(".py", "")
75
if whitelist_patterns:
76
if not [name for p in whitelist_patterns if p.match(name)]:
77
logging.info("Not whitelisted module: %s", name)
79
elif blacklist_patterns:
80
if [name for p in blacklist_patterns if p.match(name)]:
81
logging.info("Blacklisted module: %s", name)
88
def has_module(self, name):
90
Check if the given name is in this section.
92
return name in self.get_names()
94
def load_module(self, name):
96
Load a single module by name from this section.
98
logging.info("Loading module %s from section %s",
101
if not self.has_module(name):
102
raise Exception, "No such such module: %s" % name
104
filenames = itertools.chain(*[path_expand_recursive(m)
105
for m in self.modules])
106
for filename in filenames:
107
if filename.endswith(".py") and posixpath.exists(filename):
108
basename = posixpath.basename(filename)
109
basename = basename.replace(".py", "")
112
exec open(filename) in globals
113
if "factory" not in globals:
114
raise Exception, "Variable 'factory' not found in: %s" \
117
module = globals["factory"]()
119
config_name = "/".join([self.name, name])
120
config = self._config.parent.get_section(config_name)
122
# Set configuration values
123
variables = get_variables(module)
124
environ = dict([(k.lower(), v) for k, v in os.environ.items()])
125
for attribute, variable in variables.iteritems():
126
if config and attribute.name in config:
127
value = config.get(attribute.name)
130
value = variable.get()
131
if isinstance(value, basestring):
132
value = value % environ
134
elif isinstance(value, list):
135
value = [v % environ for v in value]
138
# Check required attributes
139
for attribute, variable in variables.iteritems():
140
value = variable.get()
141
if value is None and variable._required:
142
raise Exception, "Configuration '%s' missing " \
143
"required attribute: %s" \
144
% (config_name, attribute.name)
148
raise Exception, "Failed to find module '%s' in: %s" % (name, filenames)
150
def load_modules(self):
152
Load all modules contained in this section.
155
for name in self.get_names():
156
module = self.load_module(name)
157
modules.append(module)
162
class ComponentManager(object):
164
Component manager which is essentially a container of sections.
167
_section_factory = ComponentSection
169
def __init__(self, config):
171
Constructor which takes a configuration instance as argument. This
172
will be used to load sections by name.
174
self._config = config
176
def load_section(self, name):
178
Load a section by name which must correspond to a module in the
179
configuration instance pased as argument to the constructor.
181
logging.info("Loading component section %s", name)
182
config = self._config.get_section(name)
183
return self._section_factory(config, name)