Merge "Change PTL informatin in INFO"
[bottlenecks.git] / testsuites / vstf / vstf_scripts / vstf / controller / settings / settings.py
1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import json
11 import re
12 import os
13 import copy
14 import logging
15 import sys
16
17 LOG = logging.getLogger(__name__)
18
19
20 def object2dict(obj):
21     # convert object to a dict
22     dic = {'__class__': obj.__class__.__name__, '__module__': obj.__module__}
23     dic.update(obj.__dict__)
24     return dic
25
26
27 def dict2object(dic):
28     # convert dict to object
29     if '__class__' in dic:
30         class_name = dic.pop('__class__')
31         module_name = dic.pop('__module__')
32         module = __import__(module_name)
33         class_ = getattr(module, class_name)
34         args = dict((key.encode('ascii'), value)
35                     for key, value in dic.items())  # get args
36         inst = class_(**args)  # create new instance
37     else:
38         inst = dic
39     return inst
40
41
42 def filter_comments(filename, flags="//"):
43     result = []
44     with open(filename, "r") as ifile:
45         lines = ifile.readlines()
46         for data in lines:
47             data = re.sub("%s.*$" % (flags), '', data)
48             data = re.sub("^\s*$", '', data)
49             if data:
50                 result.append(data)
51     LOG.debug(result)
52     return ''.join(result)
53
54
55 class BaseSettings(object):
56
57     def _load(self, fullname):
58         data = filter_comments(fullname)
59         LOG.debug(fullname)
60         LOG.debug(data)
61         jparams = None
62         if data:
63             jparams = json.loads(data)
64         return jparams
65
66     def _sub(self, ldata, rdata):
67         if isinstance(ldata, list) and isinstance(rdata, list):
68             data = []
69             if ldata:
70                 for litem in ldata:
71                     if rdata:
72                         for ritem in rdata:
73                             if isinstance(
74                                     litem,
75                                     dict) or isinstance(
76                                     litem,
77                                     list):
78                                 tmp = self._sub(litem, ritem)
79                             else:
80                                 tmp = ritem
81                             if tmp and tmp not in data:
82                                 data.append(tmp)
83                     else:
84                         data.append(litem)
85
86             else:
87                 data = rdata
88
89         elif isinstance(ldata, dict) and isinstance(rdata, dict):
90             data = {}
91             rdata_bak = copy.deepcopy(rdata)
92             for rkey, rvalue in rdata_bak.items():
93                 if rkey not in ldata:
94                     rdata_bak.pop(rkey)
95             for lkey, lvalue in ldata.items():
96                 if lkey in rdata:
97                     if isinstance(lvalue, dict) or isinstance(lvalue, list):
98                         data[lkey] = self._sub(lvalue, rdata[lkey])
99                     else:
100                         data[lkey] = rdata[lkey]
101                 else:
102                     if rdata_bak:
103                         data[lkey] = lvalue
104         else:
105             data = rdata
106
107         return data
108
109     def _save(self, data, filename):
110         if os.path.exists(filename):
111             os.remove(filename)
112         with open(filename, 'w') as ofile:
113             content = json.dumps(
114                 data,
115                 sort_keys=True,
116                 indent=4,
117                 separators=(
118                     ',',
119                     ':'))
120             ofile.write(content)
121
122
123 class DefaultSettings(BaseSettings):
124
125     def __init__(self, path):
126         self._default = os.path.join(path, 'default')
127         self._user = os.path.join(path, 'user')
128
129     def load(self, filename):
130         dfile = os.path.join(self._default, filename)
131         if os.path.exists(dfile):
132             ddata = self._load(dfile)
133             data = ddata
134         else:
135             err = "default file is missing : %s" % (dfile)
136             LOG.error(err)
137             raise Exception(err)
138         ufile = os.path.join(self._user, filename)
139         if os.path.exists(ufile):
140             udata = self._load(ufile)
141             if udata:
142                 data = self._sub(ddata, udata)
143         else:
144             LOG.info("no user file :%s" % (ufile))
145         return data
146
147     def save(self, data, filename):
148         ufile = os.path.join(self._user, filename)
149         self._save(data, ufile)
150
151
152 class SingleSettings(BaseSettings):
153
154     def __init__(self, path):
155         self._path = path
156
157     def load(self, filename):
158         pfile = os.path.join(self._path, filename)
159         if os.path.exists(pfile):
160             ddata = self._load(pfile)
161             data = ddata
162         else:
163             err = "settings file is missing : %s" % (pfile)
164             LOG.error(err)
165             raise Exception(err)
166         return data
167
168     def save(self, data, filename):
169         pfile = os.path.join(self._path, filename)
170         self._save(data, pfile)
171
172 SETS_DEFAULT = "Default"
173 SETS_SINGLE = "Single"
174 SETTINGS = [SETS_SINGLE, SETS_DEFAULT]
175
176
177 class Settings(object):
178
179     def __init__(self, path, filename, mode=SETS_SINGLE):
180         if mode not in SETTINGS:
181             raise Exception("error Settings mode : %s" % (mode))
182         cls_name = mode + "Settings"
183         thismodule = sys.modules[__name__]
184         cls = getattr(thismodule, cls_name)
185         self._settings = cls(path)
186         self._filename = filename
187         self._fset = self._settings.load(filename)
188         self._mset = copy.deepcopy(self._fset)
189         self._register_func()
190
191     def reset(self):
192         self._fset = self._settings.load(self._filename)
193         self._mset = copy.deepcopy(self._fset)
194
195     @property
196     def settings(self):
197         return self._mset
198
199     def _setting_file(self, func_name, mset, fset, key, check=None):
200         def infunc(value):
201             if hasattr(check, '__call__'):
202                 check(value)
203             if isinstance(fset, dict):
204                 mset[key] = copy.deepcopy(value)
205                 fset[key] = copy.deepcopy(value)
206             elif isinstance(fset, list):
207                 del (mset[:])
208                 del (fset[:])
209                 mset.extend(copy.deepcopy(value))
210                 fset.extend(copy.deepcopy(value))
211             self._settings.save(self._fset, self._filename)
212             infunc.__name__ = func_name
213             LOG.debug(self._mset)
214             LOG.debug(self._fset)
215
216         return infunc
217
218     def _setting_memory(self, func_name, mset, key, check=None):
219         def infunc(value):
220             if hasattr(check, '__call__'):
221                 check(value)
222             if isinstance(mset, dict):
223                 mset[key] = copy.deepcopy(value)
224             elif isinstance(mset, list):
225                 for i in range(len(mset)):
226                     mset.pop()
227                 mset.extend(copy.deepcopy(value))
228
229             infunc.__name__ = func_name
230             LOG.debug(self._mset)
231             LOG.debug(self._fset)
232
233         return infunc
234
235     def _adding_file(self, func_name, mset, fset, key, check=None):
236         def infunc(value):
237             if hasattr(check, '__call__'):
238                 check(value)
239             if key:
240                 mset[key].append(copy.deepcopy(value))
241                 fset[key].append(copy.deepcopy(value))
242             else:
243                 mset.append(copy.deepcopy(value))
244                 fset.append(copy.deepcopy(value))
245
246             self._settings.save(self._fset, self._filename)
247             infunc.__name__ = func_name
248             LOG.debug(self._mset)
249             LOG.debug(self._fset)
250
251         return infunc
252
253     def _adding_memory(self, func_name, mset, key, check=None):
254         def infunc(value):
255             if hasattr(check, '__call__'):
256                 check(value)
257             if key:
258                 mset[key].append(copy.deepcopy(value))
259             else:
260                 mset.append(copy.deepcopy(value))
261             infunc.__name__ = func_name
262             LOG.debug(self._mset)
263             LOG.debug(self._fset)
264
265         return infunc
266
267     def _register_func(self):
268         if isinstance(self._fset, dict):
269             items = set(
270                 self._fset.keys()
271             )
272             for item in items:
273                 item = item.encode()
274                 func_name = "set_%s" % item
275                 setattr(
276                     self,
277                     func_name,
278                     self._setting_file(
279                         func_name,
280                         self._mset,
281                         self._fset,
282                         item))
283                 func_name = "mset_%s" % item
284                 setattr(
285                     self,
286                     func_name,
287                     self._setting_memory(
288                         func_name,
289                         self._mset,
290                         item))
291         elif isinstance(self._fset, list):
292             func_name = "set"
293             setattr(
294                 self,
295                 func_name,
296                 self._setting_file(
297                     func_name,
298                     self._mset,
299                     self._fset,
300                     None))
301             func_name = "mset"
302             setattr(
303                 self,
304                 func_name,
305                 self._setting_memory(
306                     func_name,
307                     self._mset,
308                     None))
309             func_name = "add"
310             setattr(
311                 self,
312                 func_name,
313                 self._adding_file(
314                     func_name,
315                     self._mset,
316                     self._fset,
317                     None))
318             func_name = "madd"
319             setattr(
320                 self,
321                 func_name,
322                 self._adding_memory(
323                     func_name,
324                     self._mset,
325                     None))
326
327
328 def unit_test():
329     from vstf.common.log import setup_logging
330     setup_logging(
331         level=logging.DEBUG,
332         log_file="/var/log/vstf-settings.log",
333         clevel=logging.INFO)
334
335     path = '/etc/vstf'
336     setting = DefaultSettings(path)
337     filename = 'reporters.mail.mail-settings'
338     data = setting.load(filename)
339
340     setting.save(data, filename)
341     LOG.info(type(data))
342     LOG.info(data)
343
344
345 if __name__ == '__main__':
346     unit_test()