cognite-neat 1.0.9__py3-none-any.whl → 1.0.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cognite/neat/__init__.py +2 -2
- cognite/neat/_config.py +14 -2
- cognite/neat/_data_model/_analysis.py +299 -150
- cognite/neat/_data_model/_snapshot.py +133 -0
- cognite/neat/_data_model/deployer/data_classes.py +1 -15
- cognite/neat/_data_model/deployer/deployer.py +2 -27
- cognite/neat/_data_model/models/dms/_references.py +6 -0
- cognite/neat/_data_model/models/dms/_views.py +6 -0
- cognite/neat/_data_model/validation/dms/_ai_readiness.py +44 -36
- cognite/neat/_data_model/validation/dms/_base.py +4 -329
- cognite/neat/_data_model/validation/dms/_connections.py +125 -91
- cognite/neat/_data_model/validation/dms/_consistency.py +12 -11
- cognite/neat/_data_model/validation/dms/_containers.py +57 -38
- cognite/neat/_data_model/validation/dms/_limits.py +43 -118
- cognite/neat/_data_model/validation/dms/_orchestrator.py +30 -186
- cognite/neat/_data_model/validation/dms/_views.py +29 -4
- cognite/neat/_session/_html/templates/deployment.html +1 -1
- cognite/neat/_session/_html/templates/issues.html +1 -1
- cognite/neat/_session/_physical.py +42 -18
- cognite/neat/_session/_session.py +1 -1
- cognite/neat/_session/_wrappers.py +22 -7
- cognite/neat/_store/_store.py +21 -1
- cognite/neat/_version.py +1 -1
- {cognite_neat-1.0.9.dist-info → cognite_neat-1.0.11.dist-info}/METADATA +1 -1
- {cognite_neat-1.0.9.dist-info → cognite_neat-1.0.11.dist-info}/RECORD +26 -25
- {cognite_neat-1.0.9.dist-info → cognite_neat-1.0.11.dist-info}/WHEEL +1 -1
|
@@ -34,33 +34,27 @@ class ConnectionValueTypeUnexisting(DataModelValidator):
|
|
|
34
34
|
issue_type = ConsistencyError
|
|
35
35
|
|
|
36
36
|
def run(self) -> list[ConsistencyError]:
|
|
37
|
-
|
|
37
|
+
errors: list[ConsistencyError] = []
|
|
38
38
|
|
|
39
|
-
for (view, property_), value_type in self.
|
|
39
|
+
for (view, property_), value_type in self.validation_resources.connection_end_node_types.items():
|
|
40
40
|
if value_type is None:
|
|
41
41
|
continue
|
|
42
42
|
|
|
43
|
-
if value_type
|
|
44
|
-
continue
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
self.modus_operandi == "additive" or value_type.space != self.local_resources.data_model_reference.space
|
|
48
|
-
) and value_type in self.cdf_resources.views_by_reference:
|
|
43
|
+
if self.validation_resources.select_view(value_type) is not None:
|
|
49
44
|
continue
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
code=self.code,
|
|
46
|
+
errors.append(
|
|
47
|
+
ConsistencyError(
|
|
48
|
+
message=(
|
|
49
|
+
f"View {view!s} connection {property_!s} has value type {value_type!s} "
|
|
50
|
+
"which is not defined as a view in the data model neither exists in CDF."
|
|
51
|
+
),
|
|
52
|
+
fix="Define necessary view",
|
|
53
|
+
code=self.code,
|
|
54
|
+
)
|
|
61
55
|
)
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
|
|
57
|
+
return errors
|
|
64
58
|
|
|
65
59
|
|
|
66
60
|
class ConnectionValueTypeUndefined(DataModelValidator):
|
|
@@ -84,23 +78,22 @@ class ConnectionValueTypeUndefined(DataModelValidator):
|
|
|
84
78
|
issue_type = Recommendation
|
|
85
79
|
|
|
86
80
|
def run(self) -> list[Recommendation]:
|
|
87
|
-
|
|
81
|
+
recommendations: list[Recommendation] = []
|
|
88
82
|
|
|
89
|
-
for (view, property_), value_type in self.
|
|
83
|
+
for (view, property_), value_type in self.validation_resources.connection_end_node_types.items():
|
|
90
84
|
if not value_type:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
]
|
|
85
|
+
recommendations.append(
|
|
86
|
+
Recommendation(
|
|
87
|
+
message=(
|
|
88
|
+
f"View {view!s} connection {property_!s} is missing value type (end node type)."
|
|
89
|
+
" This yields ambiguous data model definition."
|
|
90
|
+
),
|
|
91
|
+
fix="Define necessary value type",
|
|
92
|
+
code=self.code,
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
return recommendations
|
|
104
97
|
|
|
105
98
|
|
|
106
99
|
@dataclass
|
|
@@ -159,9 +152,9 @@ class ReverseConnectionSourceViewMissing(DataModelValidator):
|
|
|
159
152
|
for (target_view_ref, reverse_prop_name), (
|
|
160
153
|
source_view_ref,
|
|
161
154
|
through,
|
|
162
|
-
) in self.
|
|
155
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
163
156
|
through = _normalize_through_reference(source_view_ref, through)
|
|
164
|
-
source_view = self.
|
|
157
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
165
158
|
|
|
166
159
|
if not source_view:
|
|
167
160
|
errors.append(
|
|
@@ -204,14 +197,16 @@ class ReverseConnectionSourcePropertyMissing(DataModelValidator):
|
|
|
204
197
|
for (target_view_ref, reverse_prop_name), (
|
|
205
198
|
source_view_ref,
|
|
206
199
|
through,
|
|
207
|
-
) in self.
|
|
200
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
208
201
|
through = _normalize_through_reference(source_view_ref, through)
|
|
209
|
-
source_view = self.
|
|
202
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
210
203
|
|
|
211
204
|
if not source_view:
|
|
212
205
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
213
206
|
|
|
214
|
-
|
|
207
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
208
|
+
# we need expanded properties here
|
|
209
|
+
if not properties or through.identifier not in properties:
|
|
215
210
|
errors.append(
|
|
216
211
|
ConsistencyError(
|
|
217
212
|
message=(
|
|
@@ -252,17 +247,20 @@ class ReverseConnectionSourcePropertyWrongType(DataModelValidator):
|
|
|
252
247
|
for (target_view_ref, reverse_prop_name), (
|
|
253
248
|
source_view_ref,
|
|
254
249
|
through,
|
|
255
|
-
) in self.
|
|
250
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
256
251
|
through = _normalize_through_reference(source_view_ref, through)
|
|
257
|
-
source_view = self.
|
|
252
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
258
253
|
|
|
259
|
-
if not source_view
|
|
260
|
-
continue # Handled by
|
|
254
|
+
if not source_view:
|
|
255
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
261
256
|
|
|
262
|
-
|
|
263
|
-
|
|
257
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
258
|
+
# we need expanded properties here
|
|
259
|
+
if not properties or through.identifier not in properties:
|
|
264
260
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
265
261
|
|
|
262
|
+
source_property = properties[through.identifier]
|
|
263
|
+
|
|
266
264
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
267
265
|
errors.append(
|
|
268
266
|
ConsistencyError(
|
|
@@ -303,21 +301,27 @@ class ReverseConnectionContainerMissing(DataModelValidator):
|
|
|
303
301
|
for (target_view_ref, reverse_prop_name), (
|
|
304
302
|
source_view_ref,
|
|
305
303
|
through,
|
|
306
|
-
) in self.
|
|
304
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
307
305
|
through = _normalize_through_reference(source_view_ref, through)
|
|
308
|
-
source_view = self.
|
|
306
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
309
307
|
|
|
310
|
-
if not source_view
|
|
311
|
-
continue # Handled by
|
|
308
|
+
if not source_view:
|
|
309
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
312
310
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
311
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
312
|
+
# we need expanded properties here
|
|
313
|
+
if not properties or through.identifier not in properties:
|
|
314
|
+
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
315
|
+
|
|
316
|
+
source_property = properties[through.identifier]
|
|
317
|
+
|
|
318
|
+
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
319
|
+
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
316
320
|
|
|
317
321
|
container_ref = source_property.container
|
|
318
322
|
container_property_id = source_property.container_property_identifier
|
|
319
323
|
|
|
320
|
-
source_container = self.
|
|
324
|
+
source_container = self.validation_resources.select_container(container_ref, container_property_id)
|
|
321
325
|
if not source_container:
|
|
322
326
|
errors.append(
|
|
323
327
|
ConsistencyError(
|
|
@@ -361,21 +365,27 @@ class ReverseConnectionContainerPropertyMissing(DataModelValidator):
|
|
|
361
365
|
for (target_view_ref, reverse_prop_name), (
|
|
362
366
|
source_view_ref,
|
|
363
367
|
through,
|
|
364
|
-
) in self.
|
|
368
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
365
369
|
through = _normalize_through_reference(source_view_ref, through)
|
|
366
|
-
source_view = self.
|
|
370
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
367
371
|
|
|
368
|
-
if not source_view
|
|
369
|
-
continue # Handled by
|
|
372
|
+
if not source_view:
|
|
373
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
370
374
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
375
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
376
|
+
# we need expanded properties here
|
|
377
|
+
if not properties or through.identifier not in properties:
|
|
378
|
+
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
379
|
+
|
|
380
|
+
source_property = properties[through.identifier]
|
|
381
|
+
|
|
382
|
+
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
383
|
+
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
374
384
|
|
|
375
385
|
container_ref = source_property.container
|
|
376
386
|
container_property_id = source_property.container_property_identifier
|
|
377
387
|
|
|
378
|
-
source_container = self.
|
|
388
|
+
source_container = self.validation_resources.select_container(container_ref, container_property_id)
|
|
379
389
|
if not source_container:
|
|
380
390
|
continue # Handled by ReverseConnectionContainerMissing
|
|
381
391
|
|
|
@@ -422,21 +432,27 @@ class ReverseConnectionContainerPropertyWrongType(DataModelValidator):
|
|
|
422
432
|
for (target_view_ref, reverse_prop_name), (
|
|
423
433
|
source_view_ref,
|
|
424
434
|
through,
|
|
425
|
-
) in self.
|
|
435
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
426
436
|
through = _normalize_through_reference(source_view_ref, through)
|
|
427
|
-
source_view = self.
|
|
437
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
428
438
|
|
|
429
|
-
if not source_view
|
|
430
|
-
continue # Handled by
|
|
439
|
+
if not source_view:
|
|
440
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
431
441
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
442
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
443
|
+
# we need expanded properties here
|
|
444
|
+
if not properties or through.identifier not in properties:
|
|
445
|
+
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
446
|
+
|
|
447
|
+
source_property = properties[through.identifier]
|
|
448
|
+
|
|
449
|
+
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
450
|
+
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
435
451
|
|
|
436
452
|
container_ref = source_property.container
|
|
437
453
|
container_property_id = source_property.container_property_identifier
|
|
438
454
|
|
|
439
|
-
source_container = self.
|
|
455
|
+
source_container = self.validation_resources.select_container(container_ref, container_property_id)
|
|
440
456
|
if not source_container or not source_container.properties:
|
|
441
457
|
continue # Handled by other validators
|
|
442
458
|
|
|
@@ -485,16 +501,22 @@ class ReverseConnectionTargetMissing(DataModelValidator):
|
|
|
485
501
|
for (target_view_ref, reverse_prop_name), (
|
|
486
502
|
source_view_ref,
|
|
487
503
|
through,
|
|
488
|
-
) in self.
|
|
504
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
489
505
|
through = _normalize_through_reference(source_view_ref, through)
|
|
490
|
-
source_view = self.
|
|
506
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
491
507
|
|
|
492
|
-
if not source_view
|
|
493
|
-
continue # Handled by
|
|
508
|
+
if not source_view:
|
|
509
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
494
510
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
511
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
512
|
+
# we need expanded properties here
|
|
513
|
+
if not properties or through.identifier not in properties:
|
|
514
|
+
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
515
|
+
|
|
516
|
+
source_property = properties[through.identifier]
|
|
517
|
+
|
|
518
|
+
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
519
|
+
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
498
520
|
|
|
499
521
|
actual_target_view = source_property.source
|
|
500
522
|
|
|
@@ -542,15 +564,21 @@ class ReverseConnectionPointsToAncestor(DataModelValidator):
|
|
|
542
564
|
for (target_view_ref, reverse_prop_name), (
|
|
543
565
|
source_view_ref,
|
|
544
566
|
through,
|
|
545
|
-
) in self.
|
|
567
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
546
568
|
through = _normalize_through_reference(source_view_ref, through)
|
|
547
|
-
source_view = self.
|
|
569
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
548
570
|
|
|
549
|
-
if not source_view
|
|
550
|
-
continue # Handled by
|
|
571
|
+
if not source_view:
|
|
572
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
573
|
+
|
|
574
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
575
|
+
# we need expanded properties here
|
|
576
|
+
if not properties or through.identifier not in properties:
|
|
577
|
+
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
578
|
+
|
|
579
|
+
source_property = properties[through.identifier]
|
|
551
580
|
|
|
552
|
-
|
|
553
|
-
if not source_property or not isinstance(source_property, ViewCorePropertyRequest):
|
|
581
|
+
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
554
582
|
continue # Handled by other validators
|
|
555
583
|
|
|
556
584
|
actual_target_view = source_property.source
|
|
@@ -558,7 +586,7 @@ class ReverseConnectionPointsToAncestor(DataModelValidator):
|
|
|
558
586
|
if not actual_target_view:
|
|
559
587
|
continue # Handled by ReverseConnectionTargetMissing
|
|
560
588
|
|
|
561
|
-
if self.
|
|
589
|
+
if self.validation_resources.is_ancestor(target_view_ref, actual_target_view):
|
|
562
590
|
recommendations.append(
|
|
563
591
|
Recommendation(
|
|
564
592
|
message=(
|
|
@@ -602,15 +630,21 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
|
|
|
602
630
|
for (target_view_ref, reverse_prop_name), (
|
|
603
631
|
source_view_ref,
|
|
604
632
|
through,
|
|
605
|
-
) in self.
|
|
633
|
+
) in self.validation_resources.reverse_to_direct_mapping.items():
|
|
606
634
|
through = _normalize_through_reference(source_view_ref, through)
|
|
607
|
-
source_view = self.
|
|
635
|
+
source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
|
|
608
636
|
|
|
609
|
-
if not source_view
|
|
610
|
-
continue # Handled by
|
|
637
|
+
if not source_view:
|
|
638
|
+
continue # Handled by ReverseConnectionSourceViewMissing
|
|
611
639
|
|
|
612
|
-
|
|
613
|
-
|
|
640
|
+
properties = self.validation_resources.properties_by_view.get(source_view_ref)
|
|
641
|
+
# we need expanded properties here
|
|
642
|
+
if not properties or through.identifier not in properties:
|
|
643
|
+
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
644
|
+
|
|
645
|
+
source_property = properties[through.identifier]
|
|
646
|
+
|
|
647
|
+
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
614
648
|
continue # Handled by other validators
|
|
615
649
|
|
|
616
650
|
actual_target_view = source_property.source
|
|
@@ -618,7 +652,7 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
|
|
|
618
652
|
if not actual_target_view:
|
|
619
653
|
continue # Handled by ReverseConnectionTargetMissing
|
|
620
654
|
|
|
621
|
-
if self.
|
|
655
|
+
if self.validation_resources.is_ancestor(target_view_ref, actual_target_view):
|
|
622
656
|
continue # Handled by ReverseConnectionTargetAncestor
|
|
623
657
|
|
|
624
658
|
if actual_target_view != target_view_ref:
|
|
@@ -28,22 +28,23 @@ class ViewSpaceVersionInconsistentWithDataModel(DataModelValidator):
|
|
|
28
28
|
def run(self) -> list[Recommendation]:
|
|
29
29
|
recommendations: list[Recommendation] = []
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
if not self.validation_resources.merged_data_model.views:
|
|
32
|
+
return recommendations
|
|
33
|
+
|
|
34
|
+
space = self.validation_resources.merged_data_model.space
|
|
35
|
+
version = self.validation_resources.merged_data_model.version
|
|
36
|
+
|
|
37
|
+
for view_ref in self.validation_resources.merged_data_model.views:
|
|
32
38
|
issue_description = ""
|
|
33
39
|
|
|
34
40
|
if view_ref.space not in COGNITE_SPACES:
|
|
35
|
-
# notify about
|
|
36
|
-
if view_ref.space !=
|
|
37
|
-
issue_description = (
|
|
38
|
-
f"space (view: {view_ref.space}, data model: {self.local_resources.data_model_reference.space})"
|
|
39
|
-
)
|
|
41
|
+
# notify about inconsistent space
|
|
42
|
+
if view_ref.space != space:
|
|
43
|
+
issue_description = f"space (view: {view_ref.space}, data model: {space})"
|
|
40
44
|
|
|
41
45
|
# or version if spaces are same
|
|
42
|
-
elif view_ref.version !=
|
|
43
|
-
issue_description = (
|
|
44
|
-
f"version (view: {view_ref.version}, "
|
|
45
|
-
f"data model: {self.local_resources.data_model_reference.version})"
|
|
46
|
-
)
|
|
46
|
+
elif view_ref.version != version:
|
|
47
|
+
issue_description = f"version (view: {view_ref.version}, data model: {version})"
|
|
47
48
|
|
|
48
49
|
if issue_description:
|
|
49
50
|
recommendations.append(
|
|
@@ -36,16 +36,30 @@ class ExternalContainerDoesNotExist(DataModelValidator):
|
|
|
36
36
|
def run(self) -> list[ConsistencyError]:
|
|
37
37
|
errors: list[ConsistencyError] = []
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
if not self.validation_resources.merged_data_model.views:
|
|
40
|
+
return errors
|
|
41
|
+
|
|
42
|
+
for view_ref in self.validation_resources.merged_data_model.views:
|
|
43
|
+
view = self.validation_resources.select_view(view_ref)
|
|
44
|
+
|
|
45
|
+
if not view:
|
|
46
|
+
raise RuntimeError(
|
|
47
|
+
f"ImplementedViewNotExisting.run: View {view_ref!s} "
|
|
48
|
+
"not found in local resources. This is a bug in NEAT."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if view.properties is None:
|
|
52
|
+
continue
|
|
53
|
+
|
|
40
54
|
for property_ref, property_ in view.properties.items():
|
|
41
55
|
if not isinstance(property_, ViewCorePropertyRequest):
|
|
42
56
|
continue
|
|
43
57
|
|
|
44
|
-
if property_.container.space == self.
|
|
58
|
+
if property_.container.space == self.validation_resources.merged_data_model.space:
|
|
45
59
|
continue
|
|
46
60
|
|
|
47
61
|
# Check existence of container in CDF
|
|
48
|
-
if property_.container not in self.
|
|
62
|
+
if property_.container not in self.validation_resources.cdf.containers:
|
|
49
63
|
errors.append(
|
|
50
64
|
ConsistencyError(
|
|
51
65
|
message=(
|
|
@@ -87,35 +101,47 @@ class ExternalContainerPropertyDoesNotExist(DataModelValidator):
|
|
|
87
101
|
def run(self) -> list[ConsistencyError]:
|
|
88
102
|
errors: list[ConsistencyError] = []
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
for
|
|
92
|
-
|
|
93
|
-
continue
|
|
104
|
+
if self.validation_resources.merged_data_model.views:
|
|
105
|
+
for view_ref in self.validation_resources.merged_data_model.views:
|
|
106
|
+
view = self.validation_resources.select_view(view_ref)
|
|
94
107
|
|
|
95
|
-
if
|
|
96
|
-
|
|
108
|
+
if not view:
|
|
109
|
+
raise RuntimeError(
|
|
110
|
+
f"ImplementedViewNotExisting.run: View {view_ref!s} "
|
|
111
|
+
"not found in local resources. This is a bug in NEAT."
|
|
112
|
+
)
|
|
97
113
|
|
|
98
|
-
|
|
99
|
-
# this check is done in ExternalContainerDoesNotExist
|
|
100
|
-
if property_.container not in self.cdf_resources.containers_by_reference:
|
|
114
|
+
if view.properties is None:
|
|
101
115
|
continue
|
|
102
116
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
for property_ref, property_ in view.properties.items():
|
|
118
|
+
if not isinstance(property_, ViewCorePropertyRequest):
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
if property_.container.space == self.validation_resources.merged_data_model.space:
|
|
122
|
+
continue
|
|
123
|
+
|
|
124
|
+
# Only check property if container exists in CDF
|
|
125
|
+
# this check is done in ExternalContainerDoesNotExist
|
|
126
|
+
if property_.container not in self.validation_resources.cdf.containers:
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
# Check existence of container property in CDF
|
|
130
|
+
if (
|
|
131
|
+
property_.container_property_identifier
|
|
132
|
+
not in self.validation_resources.cdf.containers[property_.container].properties
|
|
133
|
+
):
|
|
134
|
+
errors.append(
|
|
135
|
+
ConsistencyError(
|
|
136
|
+
message=(
|
|
137
|
+
f"View {view_ref!s} property {property_ref!s} maps to "
|
|
138
|
+
f"external container {property_.container!s} which does not have "
|
|
139
|
+
f"property '{property_.container_property_identifier}' in CDF."
|
|
140
|
+
),
|
|
141
|
+
fix="Define necessary container property in CDF",
|
|
142
|
+
code=self.code,
|
|
143
|
+
)
|
|
117
144
|
)
|
|
118
|
-
)
|
|
119
145
|
|
|
120
146
|
return errors
|
|
121
147
|
|
|
@@ -144,26 +170,19 @@ class RequiredContainerDoesNotExist(DataModelValidator):
|
|
|
144
170
|
def run(self) -> list[ConsistencyError]:
|
|
145
171
|
errors: list[ConsistencyError] = []
|
|
146
172
|
|
|
147
|
-
for container_ref, container in self.
|
|
173
|
+
for container_ref, container in self.validation_resources.merged.containers.items():
|
|
148
174
|
if not container.constraints:
|
|
149
175
|
continue
|
|
150
176
|
|
|
151
|
-
for
|
|
177
|
+
for constraint_ref, constraint in cast(dict[str, Constraint], container.constraints).items():
|
|
152
178
|
if not isinstance(constraint, RequiresConstraintDefinition):
|
|
153
179
|
continue
|
|
154
180
|
|
|
155
|
-
|
|
156
|
-
container_exists = (
|
|
157
|
-
constraint.require in self.merged_containers
|
|
158
|
-
if is_local
|
|
159
|
-
else constraint.require in self.cdf_resources.containers_by_reference
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
if not container_exists:
|
|
181
|
+
if not self.validation_resources.select_container(constraint.require):
|
|
163
182
|
errors.append(
|
|
164
183
|
ConsistencyError(
|
|
165
184
|
message=(
|
|
166
|
-
f"Container '{container_ref!s}' constraint '{
|
|
185
|
+
f"Container '{container_ref!s}' constraint '{constraint_ref}' requires container "
|
|
167
186
|
f"'{constraint.require!s}' which does not exist."
|
|
168
187
|
),
|
|
169
188
|
fix="Define necessary container in the data model",
|