Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/import_export/results.py: 39%
90 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from collections import OrderedDict
3from django.core.exceptions import NON_FIELD_ERRORS
4from django.utils.encoding import force_str
5from tablib import Dataset
8class Error:
9 def __init__(self, error, traceback=None, row=None):
10 self.error = error
11 self.traceback = traceback
12 self.row = row
15class RowResult:
16 IMPORT_TYPE_UPDATE = 'update'
17 IMPORT_TYPE_NEW = 'new'
18 IMPORT_TYPE_DELETE = 'delete'
19 IMPORT_TYPE_SKIP = 'skip'
20 IMPORT_TYPE_ERROR = 'error'
21 IMPORT_TYPE_INVALID = 'invalid'
23 valid_import_types = frozenset([
24 IMPORT_TYPE_NEW,
25 IMPORT_TYPE_UPDATE,
26 IMPORT_TYPE_DELETE,
27 IMPORT_TYPE_SKIP,
28 ])
30 def __init__(self):
31 self.errors = []
32 self.validation_error = None
33 self.diff = None
34 self.import_type = None
35 self.row_values = {}
36 self.object_id = None
37 self.object_repr = None
39 def add_instance_info(self, instance):
40 if instance is not None:
41 # Add object info to RowResult (e.g. for LogEntry)
42 self.object_id = getattr(instance, "pk", None)
43 self.object_repr = force_str(instance)
46class InvalidRow:
47 """A row that resulted in one or more ``ValidationError`` being raised during import."""
49 def __init__(self, number, validation_error, values):
50 self.number = number
51 self.error = validation_error
52 self.values = values
53 try:
54 self.error_dict = validation_error.message_dict
55 except AttributeError:
56 self.error_dict = {NON_FIELD_ERRORS: validation_error.messages}
58 @property
59 def field_specific_errors(self):
60 """Returns a dictionary of field-specific validation errors for this row."""
61 return {
62 key: value for key, value in self.error_dict.items()
63 if key != NON_FIELD_ERRORS
64 }
66 @property
67 def non_field_specific_errors(self):
68 """Returns a list of non field-specific validation errors for this row."""
69 return self.error_dict.get(NON_FIELD_ERRORS, [])
71 @property
72 def error_count(self):
73 """Returns the total number of validation errors for this row."""
74 count = 0
75 for error_list in self.error_dict.values():
76 count += len(error_list)
77 return count
80class Result:
81 def __init__(self, *args, **kwargs):
82 super().__init__()
83 self.base_errors = []
84 self.diff_headers = []
85 self.rows = [] # RowResults
86 self.invalid_rows = [] # InvalidRow
87 self.failed_dataset = Dataset()
88 self.totals = OrderedDict([(RowResult.IMPORT_TYPE_NEW, 0),
89 (RowResult.IMPORT_TYPE_UPDATE, 0),
90 (RowResult.IMPORT_TYPE_DELETE, 0),
91 (RowResult.IMPORT_TYPE_SKIP, 0),
92 (RowResult.IMPORT_TYPE_ERROR, 0),
93 (RowResult.IMPORT_TYPE_INVALID, 0)])
94 self.total_rows = 0
96 def valid_rows(self):
97 return [
98 r for r in self.rows
99 if r.import_type in RowResult.valid_import_types
100 ]
102 def append_row_result(self, row_result):
103 self.rows.append(row_result)
105 def append_base_error(self, error):
106 self.base_errors.append(error)
108 def add_dataset_headers(self, headers):
109 headers = list() if not headers else headers
110 self.failed_dataset.headers = headers + ["Error"]
112 def append_failed_row(self, row, error):
113 row_values = [v for (k, v) in row.items()]
114 try:
115 row_values.append(str(error.error))
116 except AttributeError:
117 row_values.append(str(error))
118 self.failed_dataset.append(row_values)
120 def append_invalid_row(self, number, row, validation_error):
121 # NOTE: value order must match diff_headers order, so that row
122 # values and column headers match in the UI when displayed
123 values = tuple(row.get(col, "---") for col in self.diff_headers)
124 self.invalid_rows.append(
125 InvalidRow(number=number, validation_error=validation_error, values=values)
126 )
128 def increment_row_result_total(self, row_result):
129 if row_result.import_type:
130 self.totals[row_result.import_type] += 1
132 def row_errors(self):
133 return [(i + 1, row.errors)
134 for i, row in enumerate(self.rows) if row.errors]
136 def has_errors(self):
137 """Returns a boolean indicating whether the import process resulted in
138 any critical (non-validation) errors for this result."""
139 return bool(self.base_errors or self.row_errors())
141 def has_validation_errors(self):
142 """Returns a boolean indicating whether the import process resulted in
143 any validation errors for this result."""
144 return bool(self.invalid_rows)
146 def __iter__(self):
147 return iter(self.rows)