1 # Copyright 2015 Intel Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 """Settings and configuration handlers.
17 Settings will be loaded from several .conf files
18 and any user provided settings file.
21 # pylint: disable=invalid-name
27 class Settings(object):
28 """Holding class for settings.
33 def getValue(self, attr):
34 """Return a settings item value
36 if attr in self.__dict__:
37 return getattr(self, attr)
39 raise AttributeError("%r object has no attribute %r" %
40 (self.__class__, attr))
42 def __setattr__(self, name, value):
45 # skip non-settings. this should exclude built-ins amongst others
46 if not name.isupper():
49 # we can assume all uppercase keys are valid settings
50 super(Settings, self).__setattr__(name, value)
52 def load_from_file(self, path):
53 """Update ``settings`` with values found in module at ``path``.
57 custom_settings = imp.load_source('custom_settings', path)
59 for key in dir(custom_settings):
60 if getattr(custom_settings, key) is not None:
61 setattr(self, key, getattr(custom_settings, key))
63 def load_from_dir(self, dir_path):
64 """Update ``settings`` with contents of the .conf files at ``path``.
66 Each file must be named Nfilename.conf, where N is a single or
67 multi-digit decimal number. The files are loaded in ascending order of
68 N - so if a configuration item exists in more that one file the setting
69 in the file with the largest value of N takes precedence.
71 :param dir_path: The full path to the dir from which to load the .conf
76 regex = re.compile("^(?P<digit_part>[0-9]+).*.conf$")
78 def get_prefix(filename):
80 Provide a suitable function for sort's key arg
82 match_object = regex.search(os.path.basename(filename))
83 return int(match_object.group('digit_part'))
85 # get full file path to all files & dirs in dir_path
86 file_paths = os.listdir(dir_path)
87 file_paths = [os.path.join(dir_path, x) for x in file_paths]
89 # filter to get only those that are a files, with a leading
90 # digit and end in '.conf'
91 file_paths = [x for x in file_paths if os.path.isfile(x) and
92 regex.search(os.path.basename(x))]
94 # sort ascending on the leading digits
95 file_paths.sort(key=get_prefix)
97 # load settings from each file in turn
98 for filepath in file_paths:
99 self.load_from_file(filepath)
101 def load_from_dict(self, conf):
103 Update ``settings`` with values found in ``conf``.
105 Unlike the other loaders, this is case insensitive.
108 if conf[key] is not None:
109 setattr(self, key.upper(), conf[key])
111 def load_from_env(self):
113 Update ``settings`` with values found in the environment.
115 for key in os.environ:
116 setattr(self, key, os.environ[key])
119 """Provide settings as a human-readable string.
121 This can be useful for debug.
124 A human-readable string.
126 return pprint.pformat(self.__dict__)
129 settings = Settings()
132 def get_test_param(key, default=None):
133 """Retrieve value for test param ``key`` if available.
135 :param key: Key to retrieve from test params.
136 :param default: Default to return if key not found.
138 :returns: Value for ``key`` if found, else ``default``.
140 test_params = settings.getValue('TEST_PARAMS')
141 return test_params.get(key, default) if test_params else default