| 166 | self.config = getattr(self.parser.preset, "config") |
| 167 | |
| 168 | def write( |
| 169 | self, |
| 170 | null: str = "N/A", |
| 171 | empty: str = "-", |
| 172 | bool_true: str = "YES", |
| 173 | bool_false: str = "NO", |
| 174 | list_separator: str = ", ", |
| 175 | ) -> None: |
| 176 | self.categories = {} |
| 177 | null = self.config.get("null", null) |
| 178 | empty = self.config.get("empty", empty) |
| 179 | bool_true = self.config.get("bool_true", bool_true) |
| 180 | bool_false = self.config.get("bool_false", bool_false) |
| 181 | for category, config in self.config["categories"].items(): |
| 182 | data = self.parser.categories.get(category, None) |
| 183 | headers = config["headers"] |
| 184 | |
| 185 | if not data: |
| 186 | self.categories[category] = {"headers": headers, "rows": []} |
| 187 | continue |
| 188 | |
| 189 | if not headers: |
| 190 | key = next(iter(data.keys())) |
| 191 | headers = list(data[key].keys()) |
| 192 | |
| 193 | rows = [] |
| 194 | for row in data.values(): |
| 195 | processed_row = [] |
| 196 | for header in headers: |
| 197 | value = row[header] |
| 198 | if value is None: |
| 199 | value = null |
| 200 | elif value == "": |
| 201 | value = empty |
| 202 | elif value is True: |
| 203 | value = bool_true |
| 204 | elif value is False: |
| 205 | value = bool_false |
| 206 | elif isinstance(value, (list, tuple)): |
| 207 | value = list_separator.join([str(v) for v in value]) |
| 208 | processed_row.append(value) |
| 209 | rows.append(processed_row) |
| 210 | |
| 211 | sort = self.config.get("categories", {}).get(category, {}).get("sort", None) |
| 212 | if sort: |
| 213 | |
| 214 | def natural_sort(value): |
| 215 | if isinstance(value, str): |
| 216 | convert = lambda text: int(text) if text.isdigit() else text.lower() |
| 217 | return [convert(c) for c in re.split("([0-9]+)", value)] |
| 218 | return [str(value)] |
| 219 | |
| 220 | # Sort least important keys first, then more important keys. |
| 221 | # https://stackoverflow.com/questions/11476371/sort-by-multiple-keys-using-different-orderings |
| 222 | for sort_data in reversed(sort): |
| 223 | i = headers.index(sort_data["name"]) |
| 224 | reverse = sort_data["order"] == "DESC" |
| 225 | rows = sorted(rows, key=lambda x: natural_sort(x[i]), reverse=reverse) |