blob: 1f962eb8cec7069c57e037d558eeb9b3b44cfd3e [file] [log] [blame]
Alexb151fbe2019-04-22 16:53:30 -05001import os
2
3from cfg_checker.common import file_utils as fu
4from cfg_checker.common import logger, logger_cli
5from cfg_checker.common.config_file import ConfigFile
Alex3ebc5632019-04-18 16:47:18 -05006from cfg_checker.common.exception import ErrorMappingException
Alexb151fbe2019-04-22 16:53:30 -05007from cfg_checker.common.settings import pkg_dir
Alex3ebc5632019-04-18 16:47:18 -05008
9
10class ErrorIndex(object):
Alexb151fbe2019-04-22 16:53:30 -050011 # logs folder filenames
12 _error_logs_folder_name = ".cfgerrors"
13 _conf_filename = "conf"
14 # config file object
15 conf = None
16 # iteration counter
17 _iteration = 0
18 # local vars for codes
Alex3ebc5632019-04-18 16:47:18 -050019 _area_code = ""
20 _delimiter = ""
21 _index = 0
22 _errors = {}
23 _types = {
24 0: "Unknown error"
25 }
26
27 def __init__(self, area_code, delimiter='-'):
28 self._area_code = area_code
29 self._delimiter = delimiter
30 self._index += 1
31
Alexb151fbe2019-04-22 16:53:30 -050032 # init the error log storage folder
33 _folder = os.path.join(pkg_dir, self._error_logs_folder_name)
34 self._conf_filename = os.path.join(
35 _folder,
36 self._conf_filename
37 )
38
39 if not os.path.exists(_folder):
40 # it is not exists, create it
41 os.mkdir(_folder)
42 logger_cli.debug(
43 "... error logs folder '{}' created".format(_folder)
44 )
45 else:
46 logger_cli.debug(
47 "... error logs folder is at '{}'".format(_folder)
48 )
49 if not os.path.exists(self._conf_filename):
50 # put file with init values
51 self.conf = ConfigFile(self._area_code.lower())
52 self.conf.set_value('iteration', self._iteration)
53 self.conf.save_config(filepath=self._conf_filename)
54 logger_cli.debug(
55 "... create new config file '{}'".format(
56 self._conf_filename
57 )
58 )
59 else:
60 # it exists, try to load latest run
61 self.conf = ConfigFile(
62 self._area_code.lower(),
63 filepath=self._conf_filename
64 )
65 # it is loaded, update iteration from file
66 self._iteration = self.conf.get_value('iteration', value_type=int)
67 self._iteration += 1
68 logger_cli.debug(" ... starting iteration {}".format(self._iteration))
69
70 def save_iteration_data(self):
71 # save error log
72 _filename = "-".join([self._area_code.lower(), "errors"])
73 _filename += "." + str(self._iteration)
74 _log_filename = os.path.join(
75 pkg_dir,
76 self._error_logs_folder_name,
77 _filename
78 )
79 fu.write_lines_to_file(_log_filename, self.get_errors(as_list=True))
80 fu.append_line_to_file(_log_filename, "")
81 fu.append_lines_to_file(_log_filename, self.get_summary(as_list=True))
82 logger_cli.debug("... saved errors to '{}'".format(_log_filename))
83
84 # save last iteration number
85 self.conf.set_value('iteration', self._iteration)
86 self.conf.save_config()
87
Alex3ebc5632019-04-18 16:47:18 -050088 def _format_error_code(self, index):
89 _t = "{:02d}".format(self._errors[index]['type'])
90 _i = "{:04d}".format(index)
91 _fmt = self._delimiter.join([self._area_code, _t, _i])
92 return _fmt
93
94 def _format_error(self, index):
95 # error code
96 _code = self._format_error_code(index)
97 # prepare data as string list
98 _d = self._errors[index]['data']
Alexb151fbe2019-04-22 16:53:30 -050099 _data = [" {}: {}".format(_k, _v) for _k, _v in _d.iteritems()]
Alex3ebc5632019-04-18 16:47:18 -0500100 # format message
Alexb151fbe2019-04-22 16:53:30 -0500101 _msg = "### {}:\n Description: {}\n{}".format(
Alex3ebc5632019-04-18 16:47:18 -0500102 _code,
103 self._get_error_type_text(self._errors[index]['type']),
104 "\n".join(_data)
105 )
106 return _msg
107
108 def _get_error_type_text(self, err_type):
109 if err_type not in self._types:
110 raise ErrorMappingException(
111 "type code {} not found".format(err_type)
112 )
113 else:
114 return self._types[err_type]
115
116 def get_error_code(self, index):
117 if index in self._errors.keys():
118 return self._format_error(index)
119 else:
120 raise ErrorMappingException(
121 "no error found for index {}".format(index)
122 )
123
124 def add_error_type(self, err_type, message):
125 if err_type in self._types:
126 raise ErrorMappingException(
127 "type code {} reserved for {}".format(
128 err_type,
129 self._types[err_type]
130 )
131 )
132 else:
133 self._types[err_type] = message
134
135 def add_error(self, err_type, **kwargs):
136 # check error type
137 if err_type not in self._types.keys():
138 logger.error(
139 "Error type not listed: '{}'; unknown used".format(err_type)
140 )
141 err_type = 0
142 _err = {
143 "type": err_type,
144 "data": kwargs
145 }
146 self._errors[self._index] = _err
147 self._index += 1
148
149 def get_errors_total(self):
150 return self._index-1
151
152 def get_indices(self):
153 return self._errors.keys()
154
155 def get_error(self, index):
156 if index in self._errors.keys():
157 return self._format_error(index)
158 else:
159 return "Unknown error index of {}".format(index)
160
Alexb151fbe2019-04-22 16:53:30 -0500161 def get_summary(self, print_zeros=True, as_list=False):
Alex3ebc5632019-04-18 16:47:18 -0500162 # create summary with counts per error type
Alexb151fbe2019-04-22 16:53:30 -0500163 _list = "\n{:=^8s}\n{:^8s}\n{:=^8s}".format(
164 "=",
165 "Totals",
166 "="
167 ).splitlines()
168
Alex3ebc5632019-04-18 16:47:18 -0500169 for _type in self._types.keys():
170 _len = len(
171 filter(
172 lambda i: self._errors[i]['type'] == _type,
173 self._errors
174 )
175 )
176 if _len:
177 _num_str = "{:5d}".format(_len)
178 elif print_zeros:
179 _num_str = "{:>5s}".format("-")
180 else:
181 continue
182 _list.append(
183 "{}: {}".format(
184 _num_str,
185 self._types[_type]
186 )
187 )
188
Alexb151fbe2019-04-22 16:53:30 -0500189 _total_errors = self.get_errors_total()
Alex3ebc5632019-04-18 16:47:18 -0500190
Alexb151fbe2019-04-22 16:53:30 -0500191 _list.append('-'*20)
192 _list.append("{:5d} total errors found\n".format(_total_errors))
193 if as_list:
194 return _list
195 else:
196 return "\n".join(_list)
Alex3ebc5632019-04-18 16:47:18 -0500197
Alexb151fbe2019-04-22 16:53:30 -0500198 def get_errors(self, as_list=False):
199 _list = ["# Errors"]
200 # Detailed errors
201 if self.get_errors_total() > 0:
202 # create list of strings with error messages
Alexbab1efe2019-04-23 18:51:23 -0500203 for _idx in range(1, self._index):
Alexb151fbe2019-04-22 16:53:30 -0500204 _list.append(self._format_error(_idx))
205 _list.append("\n")
206 else:
207 _list.append("-> No errors")
208
209 if as_list:
210 return _list
211 else:
212 return "\n".join(_list)