| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 1 | import os | 
 | 2 |  | 
 | 3 | from cfg_checker.common import file_utils as fu | 
 | 4 | from cfg_checker.common import logger, logger_cli | 
 | 5 | from cfg_checker.common.config_file import ConfigFile | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 6 | from cfg_checker.common.exception import ErrorMappingException | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 7 | from cfg_checker.common.settings import pkg_dir | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 8 |  | 
 | 9 |  | 
 | 10 | class ErrorIndex(object): | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 11 |     # 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 | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 19 |     _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 |  | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 32 |         # 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 |  | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 88 |     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'] | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 99 |         _data = ["    {}: {}".format(_k, _v) for _k, _v in _d.iteritems()] | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 100 |         # format message | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 101 |         _msg = "### {}:\n    Description: {}\n{}".format( | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 102 |             _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 |  | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 161 |     def get_summary(self, print_zeros=True, as_list=False): | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 162 |         # create summary with counts per error type | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 163 |         _list = "\n{:=^8s}\n{:^8s}\n{:=^8s}".format( | 
 | 164 |             "=", | 
 | 165 |             "Totals", | 
 | 166 |             "=" | 
 | 167 |         ).splitlines() | 
 | 168 |  | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 169 |         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 |  | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 189 |         _total_errors = self.get_errors_total() | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 190 |  | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 191 |         _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) | 
| Alex | 3ebc563 | 2019-04-18 16:47:18 -0500 | [diff] [blame] | 197 |  | 
| Alex | b151fbe | 2019-04-22 16:53:30 -0500 | [diff] [blame] | 198 |     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 | 
 | 203 |             for _idx in range(1, self._index - 1): | 
 | 204 |                 _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) |