bugfix: Fix failure caused by unset locale
[vswitchperf.git] / conf / __init__.py
1 # Copyright 2015 Intel Corporation.
2 #
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
6 #
7 #   http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 """Settings and configuration handlers.
16
17 Settings will be loaded from several .conf files
18 and any user provided settings file.
19 """
20
21 # pylint: disable=invalid-name
22
23 import os
24 import re
25 import pprint
26
27 class Settings(object):
28     """Holding class for settings.
29     """
30     def __init__(self):
31         pass
32
33     def getValue(self, attr):
34         """Return a settings item value
35         """
36         if attr in self.__dict__:
37             return getattr(self, attr)
38         else:
39             raise AttributeError("%r object has no attribute %r" %
40                                  (self.__class__, attr))
41
42     def __setattr__(self, name, value):
43         """Set a value
44         """
45         # skip non-settings. this should exclude built-ins amongst others
46         if not name.isupper():
47             return
48
49         # we can assume all uppercase keys are valid settings
50         super(Settings, self).__setattr__(name, value)
51
52     def setValue(self, name, value):
53         """Set a value
54         """
55         if name is not None and value is not None:
56             super(Settings, self).__setattr__(name, value)
57
58     def load_from_file(self, path):
59         """Update ``settings`` with values found in module at ``path``.
60         """
61         import imp
62
63         custom_settings = imp.load_source('custom_settings', path)
64
65         for key in dir(custom_settings):
66             if getattr(custom_settings, key) is not None:
67                 setattr(self, key, getattr(custom_settings, key))
68
69     def load_from_dir(self, dir_path):
70         """Update ``settings`` with contents of the .conf files at ``path``.
71
72         Each file must be named Nfilename.conf, where N is a single or
73         multi-digit decimal number.  The files are loaded in ascending order of
74         N - so if a configuration item exists in more that one file the setting
75         in the file with the largest value of N takes precedence.
76
77         :param dir_path: The full path to the dir from which to load the .conf
78             files.
79
80         :returns: None
81         """
82         regex = re.compile("^(?P<digit_part>[0-9]+).*.conf$")
83
84         def get_prefix(filename):
85             """
86             Provide a suitable function for sort's key arg
87             """
88             match_object = regex.search(os.path.basename(filename))
89             return int(match_object.group('digit_part'))
90
91         # get full file path to all files & dirs in dir_path
92         file_paths = os.listdir(dir_path)
93         file_paths = [os.path.join(dir_path, x) for x in file_paths]
94
95         # filter to get only those that are a files, with a leading
96         # digit and end in '.conf'
97         file_paths = [x for x in file_paths if os.path.isfile(x) and
98                       regex.search(os.path.basename(x))]
99
100         # sort ascending on the leading digits
101         file_paths.sort(key=get_prefix)
102
103         # load settings from each file in turn
104         for filepath in file_paths:
105             self.load_from_file(filepath)
106
107     def load_from_dict(self, conf):
108         """
109         Update ``settings`` with values found in ``conf``.
110
111         Unlike the other loaders, this is case insensitive.
112         """
113         for key in conf:
114             if conf[key] is not None:
115                 setattr(self, key.upper(), conf[key])
116
117     def load_from_env(self):
118         """
119         Update ``settings`` with values found in the environment.
120         """
121         for key in os.environ:
122             setattr(self, key, os.environ[key])
123
124     def __str__(self):
125         """Provide settings as a human-readable string.
126
127         This can be useful for debug.
128
129         Returns:
130             A human-readable string.
131         """
132         return pprint.pformat(self.__dict__)
133
134
135 settings = Settings()
136
137
138 def get_test_param(key, default=None):
139     """Retrieve value for test param ``key`` if available.
140
141     :param key: Key to retrieve from test params.
142     :param default: Default to return if key not found.
143
144     :returns: Value for ``key`` if found, else ``default``.
145     """
146     test_params = settings.getValue('TEST_PARAMS')
147     return test_params.get(key, default) if test_params else default