|
| 1 | +"""Validation output reports.""" |
| 2 | +import sys |
| 3 | +from datetime import date, datetime |
| 4 | +from typing import List, Tuple |
| 5 | + |
| 6 | +class ValidationReport: |
| 7 | + """Class for reporting the results of validation.""" |
| 8 | + def __init__(self, errors_to_suppress: List[Tuple[str]]): |
| 9 | + """Initialize a ValidationReport. |
| 10 | + Parameters |
| 11 | + ---------- |
| 12 | + errors_to_suppress: List[Tuple[str]] |
| 13 | + List of error identifications to ignore. |
| 14 | +
|
| 15 | + Attributes |
| 16 | + ---------- |
| 17 | + errors_to_suppress: List[Tuple[str]] |
| 18 | + See above |
| 19 | + num_suppressed: int |
| 20 | + Number of errors suppressed |
| 21 | + total_checks: int |
| 22 | + Number of validation checks performed |
| 23 | + raised_errors: List[Exception] |
| 24 | + Errors raised from validation failures |
| 25 | + raised_warnings: List[Exception] |
| 26 | + Warnings raised from validation execution |
| 27 | + unsuppressed_errors: List[Exception] |
| 28 | + Errors raised from validation failures not found in `self.errors_to_suppress` |
| 29 | + """ |
| 30 | + self.errors_to_suppress = errors_to_suppress.copy() |
| 31 | + self.num_suppressed = 0 |
| 32 | + self.total_checks = 0 |
| 33 | + self.raised_errors = [] |
| 34 | + self.raised_warnings = [] |
| 35 | + self.unsuppressed_errors = [] |
| 36 | + |
| 37 | + def add_raised_error(self, error): |
| 38 | + """Add an error to the report. |
| 39 | + Parameters |
| 40 | + ---------- |
| 41 | + error: Exception |
| 42 | + Error raised in validation |
| 43 | +
|
| 44 | + Returns |
| 45 | + ------- |
| 46 | + None |
| 47 | + """ |
| 48 | + self.raised_errors.append(error) |
| 49 | + # Convert any dates in check_data_id to strings for the purpose of comparing |
| 50 | + # to manually suppressed errors. |
| 51 | + raised_check_id = tuple([ |
| 52 | + item.strftime("%Y-%m-%d") if isinstance(item, (date, datetime)) |
| 53 | + else item for item in error.check_data_id]) |
| 54 | + |
| 55 | + if raised_check_id in self.errors_to_suppress: |
| 56 | + self.errors_to_suppress.remove(raised_check_id) |
| 57 | + self.num_suppressed += 1 |
| 58 | + else: |
| 59 | + self.unsuppressed_errors.append(error) |
| 60 | + |
| 61 | + def increment_total_checks(self): |
| 62 | + """Records a check.""" |
| 63 | + self.total_checks += 1 |
| 64 | + |
| 65 | + def add_raised_warning(self, warning): |
| 66 | + """Add a warning to the report. |
| 67 | + Parameters |
| 68 | + ---------- |
| 69 | + warning: Warning |
| 70 | + Warning raised in validation |
| 71 | +
|
| 72 | + Returns |
| 73 | + ------- |
| 74 | + None |
| 75 | + """ |
| 76 | + self.raised_warnings.append(warning) |
| 77 | + |
| 78 | + def __str__(self): |
| 79 | + """String representation of report.""" |
| 80 | + out_str = f"{self.total_checks} checks run\n" |
| 81 | + out_str += f"{len(self.unsuppressed_errors)} checks failed\n" |
| 82 | + out_str += f"{self.num_suppressed} checks suppressed\n" |
| 83 | + out_str += f"{len(self.raised_warnings)} warnings\n" |
| 84 | + for message in self.unsuppressed_errors: |
| 85 | + out_str += f"{message}\n" |
| 86 | + for message in self.raised_warnings: |
| 87 | + out_str += f"{message}\n" |
| 88 | + return out_str |
| 89 | + |
| 90 | + def print_and_exit(self): |
| 91 | + """ |
| 92 | + Print results and, if any not-suppressed exceptions were raised, exit with non-zero status. |
| 93 | + """ |
| 94 | + print(self) |
| 95 | + if len(self.unsuppressed_errors) != 0: |
| 96 | + sys.exit(1) |
| 97 | + else: |
| 98 | + sys.exit(0) |
0 commit comments