27
27
28
28
class ZGWImportError (Exception ):
29
29
@classmethod
30
- def extract_error_data (cls , exc : Exception , jsonl : str ):
31
- exc_source = type (exc .__context__ )
32
- data = json .loads (jsonl ) if jsonl else {}
30
+ def extract_error_data (
31
+ cls , exception : Exception | None = None , jsonl : str | None = None
32
+ ):
33
+ data = json .loads (jsonl ) if jsonl is not None else {}
33
34
source_config = apps .get_model (data ["model" ])
34
35
35
- # error type
36
- if exc_source is CatalogusConfig .DoesNotExist or source_config .DoesNotExist :
37
- error_type = ObjectDoesNotExist
38
- if exc_source is source_config .MultipleObjectsReturned :
39
- error_type = MultipleObjectsReturned
36
+ error_type = None
37
+ if exception :
38
+ exc_source = type (exception .__context__ )
39
+ if exc_source is CatalogusConfig .DoesNotExist or source_config .DoesNotExist :
40
+ error_type = ObjectDoesNotExist
41
+ if exc_source is source_config .MultipleObjectsReturned :
42
+ error_type = MultipleObjectsReturned
40
43
41
44
# metadata about source_config
42
45
items = []
@@ -60,8 +63,6 @@ def extract_error_data(cls, exc: Exception, jsonl: str):
60
63
items = [
61
64
f"omschrijving = { fields ['omschrijving' ]!r} " ,
62
65
f"ZaakTypeConfig identificatie = { fields ['zaaktype_config' ][0 ]!r} " ,
63
- f"Catalogus domein = { fields ['zaaktype_config' ][1 ]!r} " ,
64
- f"Catalogus rsin = { fields ['zaaktype_config' ][2 ]!r} " ,
65
66
]
66
67
67
68
return {
@@ -71,8 +72,8 @@ def extract_error_data(cls, exc: Exception, jsonl: str):
71
72
}
72
73
73
74
@classmethod
74
- def from_exception_and_jsonl (cls , exception : Exception , jsonl : str ) -> Self :
75
- error_data = cls .extract_error_data (exception , jsonl )
75
+ def from_exception_and_jsonl (cls , jsonl : str , exception : Exception ) -> Self :
76
+ error_data = cls .extract_error_data (exception = exception , jsonl = jsonl )
76
77
77
78
error_template = (
78
79
"%(source_config_name)s not found in target environment: %(info)s"
@@ -82,16 +83,26 @@ def from_exception_and_jsonl(cls, exception: Exception, jsonl: str) -> Self:
82
83
83
84
return cls (error_template % error_data )
84
85
86
+ @classmethod
87
+ def from_jsonl (cls , jsonl : str ) -> Self :
88
+ error_data = cls .extract_error_data (jsonl = jsonl )
89
+ error_template = (
90
+ "%(source_config_name)s was processed multiple times because it contains "
91
+ "duplicate natural keys: %(info)s"
92
+ )
93
+ return cls (error_template % error_data )
94
+
85
95
86
96
def check_catalogus_config_exists (source_config : CatalogusConfig , jsonl : str ):
87
97
try :
88
98
CatalogusConfig .objects .get_by_natural_key (
89
99
domein = source_config .domein , rsin = source_config .rsin
90
100
)
91
- except CatalogusConfig .MultipleObjectsReturned as exc :
92
- raise ZGWImportError .from_exception_and_jsonl (exc , jsonl )
93
- except CatalogusConfig .DoesNotExist as exc :
94
- raise ZGWImportError .from_exception_and_jsonl (exc , jsonl )
101
+ except (
102
+ CatalogusConfig .DoesNotExist ,
103
+ CatalogusConfig .MultipleObjectsReturned ,
104
+ ) as exc :
105
+ raise ZGWImportError .from_exception_and_jsonl (exception = exc , jsonl = jsonl )
95
106
96
107
97
108
def _update_config (source , target , exclude_fields ):
@@ -113,10 +124,13 @@ def _update_zaaktype_config(source_config: ZaakTypeConfig, jsonl: str):
113
124
catalogus_domein = source_config .catalogus .domein ,
114
125
catalogus_rsin = source_config .catalogus .rsin ,
115
126
)
116
- except ZaakTypeConfig .MultipleObjectsReturned as exc :
117
- raise ZGWImportError .from_exception_and_jsonl (exc , jsonl )
118
- except (CatalogusConfig .DoesNotExist , ZaakTypeConfig .DoesNotExist ) as exc :
119
- raise ZGWImportError .from_exception_and_jsonl (exc , jsonl )
127
+ except (
128
+ CatalogusConfig .DoesNotExist ,
129
+ CatalogusConfig .MultipleObjectsReturned ,
130
+ ZaakTypeConfig .DoesNotExist ,
131
+ ZaakTypeConfig .MultipleObjectsReturned ,
132
+ ) as exc :
133
+ raise ZGWImportError .from_exception_and_jsonl (exception = exc , jsonl = jsonl )
120
134
else :
121
135
exclude_fields = [
122
136
"id" ,
@@ -146,7 +160,7 @@ def _update_nested_zgw_config(
146
160
catalogus_rsin = catalogus_rsin ,
147
161
)
148
162
except (source_config .DoesNotExist , source_config .MultipleObjectsReturned ) as exc :
149
- raise ZGWImportError .from_exception_and_jsonl (exc , jsonl )
163
+ raise ZGWImportError .from_exception_and_jsonl (exception = exc , jsonl = jsonl )
150
164
else :
151
165
_update_config (source_config , target , exclude_fields )
152
166
@@ -320,6 +334,7 @@ def from_jsonl_stream_or_string(cls, stream_or_string: IO | str) -> Self:
320
334
321
335
rows_successfully_processed = 0
322
336
import_errors = []
337
+ natural_keys_seen = set ()
323
338
for line in cls ._lines_iter_from_jsonl_stream_or_string (stream_or_string ):
324
339
try :
325
340
(deserialized_object ,) = serializers .deserialize (
@@ -329,11 +344,17 @@ def from_jsonl_stream_or_string(cls, stream_or_string: IO | str) -> Self:
329
344
use_natural_foreign_keys = True ,
330
345
)
331
346
except DeserializationError as exc :
332
- error = ZGWImportError .from_exception_and_jsonl (exc , line )
347
+ error = ZGWImportError .from_exception_and_jsonl (
348
+ exception = exc , jsonl = line
349
+ )
333
350
logger .error (error )
334
351
import_errors .append (error )
335
352
else :
336
353
source_config = deserialized_object .object
354
+ if (natural_key := source_config .natural_key ()) in natural_keys_seen :
355
+ import_errors .append (ZGWImportError .from_jsonl (line ))
356
+ continue
357
+ natural_keys_seen .add (natural_key )
337
358
try :
338
359
match source_config :
339
360
case CatalogusConfig ():
0 commit comments