cognite-neat 1.0.10__py3-none-any.whl → 1.0.12__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.
@@ -34,33 +34,27 @@ class ConnectionValueTypeUnexisting(DataModelValidator):
34
34
  issue_type = ConsistencyError
35
35
 
36
36
  def run(self) -> list[ConsistencyError]:
37
- undefined_value_types = []
37
+ errors: list[ConsistencyError] = []
38
38
 
39
- for (view, property_), value_type in self.local_resources.connection_end_node_types.items():
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 in self.local_resources.views_by_reference:
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
- undefined_value_types.append((view, property_, value_type))
52
-
53
- return [
54
- ConsistencyError(
55
- message=(
56
- f"View {view!s} connection {property_!s} has value type {value_type!s} "
57
- "which is not defined as a view in the data model neither exists in CDF."
58
- ),
59
- fix="Define necessary view",
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
- for (view, property_, value_type) in undefined_value_types
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
- missing_value_types = []
81
+ recommendations: list[Recommendation] = []
88
82
 
89
- for (view, property_), value_type in self.local_resources.connection_end_node_types.items():
83
+ for (view, property_), value_type in self.validation_resources.connection_end_node_types.items():
90
84
  if not value_type:
91
- missing_value_types.append((view, property_))
92
-
93
- return [
94
- Recommendation(
95
- message=(
96
- f"View {view!s} connection {property_!s} is missing value type (end node type)."
97
- " This yields ambiguous data model definition."
98
- ),
99
- fix="Define necessary value type",
100
- code=self.code,
101
- )
102
- for (view, property_) in missing_value_types
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.local_resources.reverse_to_direct_mapping.items():
155
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
163
156
  through = _normalize_through_reference(source_view_ref, through)
164
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
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.local_resources.reverse_to_direct_mapping.items():
200
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
208
201
  through = _normalize_through_reference(source_view_ref, through)
209
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
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
- if not source_view.properties or through.identifier not in source_view.properties:
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.local_resources.reverse_to_direct_mapping.items():
250
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
256
251
  through = _normalize_through_reference(source_view_ref, through)
257
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
252
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
258
253
 
259
- if not source_view or not source_view.properties:
260
- continue # Handled by other validators
254
+ if not source_view:
255
+ continue # Handled by ReverseConnectionSourceViewMissing
261
256
 
262
- source_property = source_view.properties.get(through.identifier)
263
- if not source_property:
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.local_resources.reverse_to_direct_mapping.items():
304
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
307
305
  through = _normalize_through_reference(source_view_ref, through)
308
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
306
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
309
307
 
310
- if not source_view or not source_view.properties:
311
- continue # Handled by other validators
308
+ if not source_view:
309
+ continue # Handled by ReverseConnectionSourceViewMissing
312
310
 
313
- source_property = source_view.properties.get(through.identifier)
314
- if not source_property or not isinstance(source_property, ViewCorePropertyRequest):
315
- continue # Handled by other validators
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._select_container_with_property(container_ref, container_property_id)
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.local_resources.reverse_to_direct_mapping.items():
368
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
365
369
  through = _normalize_through_reference(source_view_ref, through)
366
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
370
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
367
371
 
368
- if not source_view or not source_view.properties:
369
- continue # Handled by other validators
372
+ if not source_view:
373
+ continue # Handled by ReverseConnectionSourceViewMissing
370
374
 
371
- source_property = source_view.properties.get(through.identifier)
372
- if not source_property or not isinstance(source_property, ViewCorePropertyRequest):
373
- continue # Handled by other validators
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._select_container_with_property(container_ref, container_property_id)
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.local_resources.reverse_to_direct_mapping.items():
435
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
426
436
  through = _normalize_through_reference(source_view_ref, through)
427
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
437
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
428
438
 
429
- if not source_view or not source_view.properties:
430
- continue # Handled by other validators
439
+ if not source_view:
440
+ continue # Handled by ReverseConnectionSourceViewMissing
431
441
 
432
- source_property = source_view.properties.get(through.identifier)
433
- if not source_property or not isinstance(source_property, ViewCorePropertyRequest):
434
- continue # Handled by other validators
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._select_container_with_property(container_ref, container_property_id)
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.local_resources.reverse_to_direct_mapping.items():
504
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
489
505
  through = _normalize_through_reference(source_view_ref, through)
490
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
506
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
491
507
 
492
- if not source_view or not source_view.properties:
493
- continue # Handled by other validators
508
+ if not source_view:
509
+ continue # Handled by ReverseConnectionSourceViewMissing
494
510
 
495
- source_property = source_view.properties.get(through.identifier)
496
- if not source_property or not isinstance(source_property, ViewCorePropertyRequest):
497
- continue # Handled by other validators
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.local_resources.reverse_to_direct_mapping.items():
567
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
546
568
  through = _normalize_through_reference(source_view_ref, through)
547
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
569
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
548
570
 
549
- if not source_view or not source_view.properties:
550
- continue # Handled by other validators
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
- source_property = source_view.properties.get(through.identifier)
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._is_ancestor_of_target(actual_target_view, target_view_ref):
589
+ if self.validation_resources.is_ancestor(target_view_ref, actual_target_view):
562
590
  recommendations.append(
563
591
  Recommendation(
564
592
  message=(
@@ -594,23 +622,29 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
594
622
  """
595
623
 
596
624
  code = f"{BASE_CODE}-REVERSE-009"
597
- issue_type = ConsistencyError
625
+ issue_type = Recommendation
598
626
 
599
- def run(self) -> list[ConsistencyError]:
600
- errors: list[ConsistencyError] = []
627
+ def run(self) -> list[Recommendation]:
628
+ recommendations: list[Recommendation] = []
601
629
 
602
630
  for (target_view_ref, reverse_prop_name), (
603
631
  source_view_ref,
604
632
  through,
605
- ) in self.local_resources.reverse_to_direct_mapping.items():
633
+ ) in self.validation_resources.reverse_to_direct_mapping.items():
606
634
  through = _normalize_through_reference(source_view_ref, through)
607
- source_view = self._select_view_with_property(source_view_ref, through.identifier)
635
+ source_view = self.validation_resources.select_view(source_view_ref, through.identifier)
608
636
 
609
- if not source_view or not source_view.properties:
610
- continue # Handled by other validators
637
+ if not source_view:
638
+ continue # Handled by ReverseConnectionSourceViewMissing
611
639
 
612
- source_property = source_view.properties.get(through.identifier)
613
- if not source_property or not isinstance(source_property, ViewCorePropertyRequest):
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,12 +652,12 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
618
652
  if not actual_target_view:
619
653
  continue # Handled by ReverseConnectionTargetMissing
620
654
 
621
- if self._is_ancestor_of_target(actual_target_view, target_view_ref):
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:
625
- errors.append(
626
- ConsistencyError(
659
+ recommendations.append(
660
+ Recommendation(
627
661
  message=(
628
662
  f"The reverse connection '{reverse_prop_name}' in view {target_view_ref!s} "
629
663
  f"expects its corresponding direct connection in view {source_view_ref!s} "
@@ -635,4 +669,4 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
635
669
  )
636
670
  )
637
671
 
638
- return errors
672
+ return recommendations
@@ -28,22 +28,23 @@ class ViewSpaceVersionInconsistentWithDataModel(DataModelValidator):
28
28
  def run(self) -> list[Recommendation]:
29
29
  recommendations: list[Recommendation] = []
30
30
 
31
- for view_ref in self.local_resources.views_by_reference:
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 inconsisten space
36
- if view_ref.space != self.local_resources.data_model_reference.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 != self.local_resources.data_model_reference.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
- for view_ref, view in self.merged_views.items():
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.local_resources.data_model_reference.space:
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.cdf_resources.containers_by_reference:
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
- for view_ref, view in self.merged_views.items():
91
- for property_ref, property_ in view.properties.items():
92
- if not isinstance(property_, ViewCorePropertyRequest):
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 property_.container.space == self.local_resources.data_model_reference.space:
96
- continue
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
- # Only check property if container exists in CDF
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
- # Check existence of container property in CDF
104
- if (
105
- property_.container_property_identifier
106
- not in self.cdf_resources.containers_by_reference[property_.container].properties
107
- ):
108
- errors.append(
109
- ConsistencyError(
110
- message=(
111
- f"View {view_ref!s} property {property_ref!s} maps to "
112
- f"external container {property_.container!s} which does not have "
113
- f"property '{property_.container_property_identifier}' in CDF."
114
- ),
115
- fix="Define necessary container property in CDF",
116
- code=self.code,
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.local_resources.containers_by_reference.items():
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 external_id, constraint in cast(dict[str, Constraint], container.constraints).items():
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
- is_local = constraint.require.space == self.local_resources.data_model_reference.space
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 '{external_id}' requires container "
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",