cognite-neat 1.0.13__py3-none-any.whl → 1.0.15__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/_data_model/_analysis.py +65 -30
- cognite/neat/_data_model/validation/dms/_ai_readiness.py +15 -6
- cognite/neat/_data_model/validation/dms/_connections.py +40 -31
- cognite/neat/_data_model/validation/dms/_containers.py +11 -5
- cognite/neat/_data_model/validation/dms/_limits.py +33 -10
- cognite/neat/_data_model/validation/dms/_views.py +2 -4
- cognite/neat/_session/_wrappers.py +6 -2
- cognite/neat/_version.py +1 -1
- {cognite_neat-1.0.13.dist-info → cognite_neat-1.0.15.dist-info}/METADATA +1 -1
- {cognite_neat-1.0.13.dist-info → cognite_neat-1.0.15.dist-info}/RECORD +11 -11
- {cognite_neat-1.0.13.dist-info → cognite_neat-1.0.15.dist-info}/WHEEL +0 -0
|
@@ -55,6 +55,9 @@ class ValidationResources:
|
|
|
55
55
|
# need this shortcut for easier access and also to avoid mypy to complains
|
|
56
56
|
self.merged_data_model = self.merged.data_model[next(iter(self.merged.data_model.keys()))]
|
|
57
57
|
|
|
58
|
+
# For caching of expanded views
|
|
59
|
+
self._expanded_views_cache: dict[ViewReference, ViewRequest] = {}
|
|
60
|
+
|
|
58
61
|
def select_view(
|
|
59
62
|
self, view_ref: ViewReference, property_: str | None = None, source: ResourceSource = "auto"
|
|
60
63
|
) -> ViewRequest | None:
|
|
@@ -139,11 +142,26 @@ class ValidationResources:
|
|
|
139
142
|
Tuple of (check_merged, check_cdf) booleans indicating which sources to check
|
|
140
143
|
"""
|
|
141
144
|
if source == "auto":
|
|
142
|
-
# Auto mode: driven by
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
# Auto mode: driven by data modeling modus (approach)
|
|
146
|
+
# If elements is in the schema space, we check merged, else we check CDF
|
|
147
|
+
|
|
148
|
+
in_schema_space = resource_ref.space == self.merged_data_model.space
|
|
149
|
+
|
|
150
|
+
if self._modus_operandi == "additive":
|
|
151
|
+
# In additive modus, schema space means local additions on top of CDF
|
|
152
|
+
# always check CDF, while do not check merged if resource is not in schema space
|
|
153
|
+
check_merged = in_schema_space
|
|
154
|
+
check_cdf = True
|
|
155
|
+
elif self._modus_operandi == "rebuild":
|
|
156
|
+
# In rebuild modus, schema space means the full desired state is in local schema (i.e., merged)
|
|
157
|
+
# you are not adding to CDF, but replacing it, so never check CDF for schema space resources
|
|
158
|
+
check_merged = in_schema_space
|
|
159
|
+
check_cdf = not in_schema_space
|
|
160
|
+
else:
|
|
161
|
+
raise RuntimeError(
|
|
162
|
+
f"_resolve_resource_sources: Unknown modus_operandi: {self._modus_operandi}. This is a bug!"
|
|
163
|
+
)
|
|
164
|
+
|
|
147
165
|
elif source == "merged":
|
|
148
166
|
check_merged = True
|
|
149
167
|
check_cdf = False
|
|
@@ -193,7 +211,6 @@ class ValidationResources:
|
|
|
193
211
|
ancestors = []
|
|
194
212
|
|
|
195
213
|
# Determine which view definition to use based on space and modus operandi
|
|
196
|
-
|
|
197
214
|
view_definition = self.select_view(view_ref=offspring, source=source)
|
|
198
215
|
|
|
199
216
|
# Base case: no view definition or no implements
|
|
@@ -210,37 +227,55 @@ class ValidationResources:
|
|
|
210
227
|
return ancestors
|
|
211
228
|
|
|
212
229
|
def is_ancestor(self, offspring: ViewReference, ancestor: ViewReference) -> bool:
|
|
213
|
-
return ancestor in self.
|
|
230
|
+
return ancestor in self.view_ancestors(offspring)
|
|
214
231
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
"""Get a mapping of view references to their corresponding properties, both directly defined and inherited
|
|
218
|
-
from ancestor views through implements."""
|
|
232
|
+
def _expand_view(self, view_ref: ViewReference) -> ViewRequest | None:
|
|
233
|
+
"""Expand a view by including properties from its ancestors.
|
|
219
234
|
|
|
220
|
-
|
|
235
|
+
Args:
|
|
236
|
+
view_ref: The view to expand.
|
|
221
237
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
238
|
+
Returns:
|
|
239
|
+
ViewRequest with expanded properties, or None if view not found.
|
|
240
|
+
"""
|
|
241
|
+
view = self.select_view(view_ref)
|
|
242
|
+
|
|
243
|
+
if not view:
|
|
244
|
+
return None
|
|
245
|
+
|
|
246
|
+
# Create a deep copy to avoid mutating the original
|
|
247
|
+
expanded_view = view.model_copy(deep=True)
|
|
248
|
+
|
|
249
|
+
# Get all ancestor properties (oldest to newest)
|
|
250
|
+
ancestor_refs = self.view_ancestors(view_ref)
|
|
251
|
+
ancestor_properties: dict[str, ViewRequestProperty] = {}
|
|
228
252
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if ancestor_view:
|
|
235
|
-
combined_properties.update(ancestor_view.properties)
|
|
253
|
+
# Collect properties from ancestors, overriding with newer ancestors properties
|
|
254
|
+
for ancestor_ref in reversed(ancestor_refs):
|
|
255
|
+
ancestor = self.select_view(ancestor_ref)
|
|
256
|
+
if ancestor and ancestor.properties:
|
|
257
|
+
ancestor_properties.update(ancestor.properties)
|
|
236
258
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
259
|
+
# Merge: ancestor properties first, then override with view's own properties
|
|
260
|
+
if ancestor_properties:
|
|
261
|
+
if not expanded_view.properties:
|
|
262
|
+
expanded_view.properties = {}
|
|
263
|
+
|
|
264
|
+
# Ancestor properties are base, view properties override
|
|
265
|
+
expanded_view.properties = {**ancestor_properties, **expanded_view.properties}
|
|
266
|
+
|
|
267
|
+
return expanded_view
|
|
268
|
+
|
|
269
|
+
def expand_view_properties(self, view_ref: ViewReference) -> ViewRequest | None:
|
|
270
|
+
"""Get a mapping of view references to their corresponding properties, both directly defined and inherited
|
|
271
|
+
from ancestor views through implements."""
|
|
240
272
|
|
|
241
|
-
|
|
273
|
+
if view_ref not in self._expanded_views_cache:
|
|
274
|
+
expanded_view = self._expand_view(view_ref)
|
|
275
|
+
if expanded_view:
|
|
276
|
+
self._expanded_views_cache[view_ref] = expanded_view
|
|
242
277
|
|
|
243
|
-
return
|
|
278
|
+
return self._expanded_views_cache.get(view_ref)
|
|
244
279
|
|
|
245
280
|
@cached_property
|
|
246
281
|
def referenced_containers(self) -> set[ContainerReference]:
|
|
@@ -107,7 +107,7 @@ class ViewMissingName(DataModelValidator):
|
|
|
107
107
|
view = self.validation_resources.select_view(view_ref)
|
|
108
108
|
|
|
109
109
|
if view is None:
|
|
110
|
-
raise RuntimeError(f"
|
|
110
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug.")
|
|
111
111
|
|
|
112
112
|
if not view.name:
|
|
113
113
|
recommendations.append(
|
|
@@ -158,7 +158,7 @@ class ViewMissingDescription(DataModelValidator):
|
|
|
158
158
|
view = self.validation_resources.select_view(view_ref)
|
|
159
159
|
|
|
160
160
|
if view is None:
|
|
161
|
-
raise RuntimeError(f"
|
|
161
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug.")
|
|
162
162
|
|
|
163
163
|
if not view.description:
|
|
164
164
|
recommendations.append(
|
|
@@ -199,7 +199,7 @@ class ViewPropertyMissingName(DataModelValidator):
|
|
|
199
199
|
view = self.validation_resources.select_view(view_ref)
|
|
200
200
|
|
|
201
201
|
if view is None:
|
|
202
|
-
raise RuntimeError(f"
|
|
202
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug.")
|
|
203
203
|
|
|
204
204
|
if not view.properties:
|
|
205
205
|
continue
|
|
@@ -255,7 +255,7 @@ class ViewPropertyMissingDescription(DataModelValidator):
|
|
|
255
255
|
view = self.validation_resources.select_view(view_ref)
|
|
256
256
|
|
|
257
257
|
if view is None:
|
|
258
|
-
raise RuntimeError(f"
|
|
258
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug.")
|
|
259
259
|
|
|
260
260
|
if not view.properties:
|
|
261
261
|
continue
|
|
@@ -296,7 +296,12 @@ class EnumerationMissingName(DataModelValidator):
|
|
|
296
296
|
def run(self) -> list[Recommendation]:
|
|
297
297
|
recommendations: list[Recommendation] = []
|
|
298
298
|
|
|
299
|
-
for container_ref
|
|
299
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
300
|
+
container = self.validation_resources.select_container(container_ref)
|
|
301
|
+
|
|
302
|
+
if not container:
|
|
303
|
+
raise RuntimeError(f"{type(self).__name__}: Container {container_ref!s} not found. This is a bug.")
|
|
304
|
+
|
|
300
305
|
for prop_ref, definition in container.properties.items():
|
|
301
306
|
if not isinstance(definition.type, EnumProperty):
|
|
302
307
|
continue
|
|
@@ -351,7 +356,11 @@ class EnumerationMissingDescription(DataModelValidator):
|
|
|
351
356
|
def run(self) -> list[Recommendation]:
|
|
352
357
|
recommendations: list[Recommendation] = []
|
|
353
358
|
|
|
354
|
-
for container_ref
|
|
359
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
360
|
+
container = self.validation_resources.select_container(container_ref)
|
|
361
|
+
if not container:
|
|
362
|
+
raise RuntimeError(f"{self.__class__.__name__}: Container {container_ref!s} not found. This is a bug.")
|
|
363
|
+
|
|
355
364
|
for prop_ref, definition in container.properties.items():
|
|
356
365
|
if not isinstance(definition.type, EnumProperty):
|
|
357
366
|
continue
|
|
@@ -204,9 +204,11 @@ class ReverseConnectionSourcePropertyMissing(DataModelValidator):
|
|
|
204
204
|
if not source_view:
|
|
205
205
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
206
206
|
|
|
207
|
-
properties
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
# critical to expand view properties to include inherited ones as otherwise we might miss the property
|
|
208
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
209
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
210
|
+
|
|
211
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
210
212
|
errors.append(
|
|
211
213
|
ConsistencyError(
|
|
212
214
|
message=(
|
|
@@ -254,12 +256,13 @@ class ReverseConnectionSourcePropertyWrongType(DataModelValidator):
|
|
|
254
256
|
if not source_view:
|
|
255
257
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
256
258
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
260
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
261
|
+
|
|
262
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
260
263
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
261
264
|
|
|
262
|
-
source_property = properties[through.identifier]
|
|
265
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
263
266
|
|
|
264
267
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
265
268
|
errors.append(
|
|
@@ -308,12 +311,13 @@ class ReverseConnectionContainerMissing(DataModelValidator):
|
|
|
308
311
|
if not source_view:
|
|
309
312
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
310
313
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
315
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
316
|
+
|
|
317
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
314
318
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
315
319
|
|
|
316
|
-
source_property = properties[through.identifier]
|
|
320
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
317
321
|
|
|
318
322
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
319
323
|
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
@@ -372,12 +376,13 @@ class ReverseConnectionContainerPropertyMissing(DataModelValidator):
|
|
|
372
376
|
if not source_view:
|
|
373
377
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
374
378
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
379
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
380
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
381
|
+
|
|
382
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
378
383
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
379
384
|
|
|
380
|
-
source_property = properties[through.identifier]
|
|
385
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
381
386
|
|
|
382
387
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
383
388
|
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
@@ -439,12 +444,13 @@ class ReverseConnectionContainerPropertyWrongType(DataModelValidator):
|
|
|
439
444
|
if not source_view:
|
|
440
445
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
441
446
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
447
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
448
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
449
|
+
|
|
450
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
445
451
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
446
452
|
|
|
447
|
-
source_property = properties[through.identifier]
|
|
453
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
448
454
|
|
|
449
455
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
450
456
|
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
@@ -508,12 +514,13 @@ class ReverseConnectionTargetMissing(DataModelValidator):
|
|
|
508
514
|
if not source_view:
|
|
509
515
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
510
516
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
517
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
518
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
519
|
+
|
|
520
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
514
521
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
515
522
|
|
|
516
|
-
source_property = properties[through.identifier]
|
|
523
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
517
524
|
|
|
518
525
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
519
526
|
continue # Handled by ReverseConnectionSourcePropertyWrongType
|
|
@@ -571,12 +578,13 @@ class ReverseConnectionPointsToAncestor(DataModelValidator):
|
|
|
571
578
|
if not source_view:
|
|
572
579
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
573
580
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
581
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
582
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
583
|
+
|
|
584
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
577
585
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
578
586
|
|
|
579
|
-
source_property = properties[through.identifier]
|
|
587
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
580
588
|
|
|
581
589
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
582
590
|
continue # Handled by other validators
|
|
@@ -637,12 +645,13 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
|
|
|
637
645
|
if not source_view:
|
|
638
646
|
continue # Handled by ReverseConnectionSourceViewMissing
|
|
639
647
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
648
|
+
if not (source_view_expanded := self.validation_resources.expand_view_properties(source_view_ref)):
|
|
649
|
+
raise RuntimeError(f"{type(self).__name__}: View {source_view_ref!s} not found. This is a bug in NEAT.")
|
|
650
|
+
|
|
651
|
+
if not source_view_expanded.properties or through.identifier not in source_view_expanded.properties:
|
|
643
652
|
continue # Handled by ReverseConnectionSourcePropertyMissing
|
|
644
653
|
|
|
645
|
-
source_property = properties[through.identifier]
|
|
654
|
+
source_property = source_view_expanded.properties[through.identifier]
|
|
646
655
|
|
|
647
656
|
if not isinstance(source_property, ViewCorePropertyRequest):
|
|
648
657
|
continue # Handled by other validators
|
|
@@ -44,8 +44,7 @@ class ExternalContainerDoesNotExist(DataModelValidator):
|
|
|
44
44
|
|
|
45
45
|
if not view:
|
|
46
46
|
raise RuntimeError(
|
|
47
|
-
f"
|
|
48
|
-
"not found in local resources. This is a bug in NEAT."
|
|
47
|
+
f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
|
|
49
48
|
)
|
|
50
49
|
|
|
51
50
|
if view.properties is None:
|
|
@@ -107,8 +106,7 @@ class ExternalContainerPropertyDoesNotExist(DataModelValidator):
|
|
|
107
106
|
|
|
108
107
|
if not view:
|
|
109
108
|
raise RuntimeError(
|
|
110
|
-
f"
|
|
111
|
-
"not found in local resources. This is a bug in NEAT."
|
|
109
|
+
f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
|
|
112
110
|
)
|
|
113
111
|
|
|
114
112
|
if view.properties is None:
|
|
@@ -170,7 +168,15 @@ class RequiredContainerDoesNotExist(DataModelValidator):
|
|
|
170
168
|
def run(self) -> list[ConsistencyError]:
|
|
171
169
|
errors: list[ConsistencyError] = []
|
|
172
170
|
|
|
173
|
-
for container_ref
|
|
171
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
172
|
+
container = self.validation_resources.select_container(container_ref)
|
|
173
|
+
|
|
174
|
+
if not container:
|
|
175
|
+
raise RuntimeError(
|
|
176
|
+
f"{type(self).__name__}: Container {container_ref!s} "
|
|
177
|
+
"not found in local resources. This is a bug in NEAT."
|
|
178
|
+
)
|
|
179
|
+
|
|
174
180
|
if not container.constraints:
|
|
175
181
|
continue
|
|
176
182
|
|
|
@@ -86,12 +86,15 @@ class ViewPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
86
86
|
def run(self) -> list[ConsistencyError]:
|
|
87
87
|
errors: list[ConsistencyError] = []
|
|
88
88
|
|
|
89
|
-
for view_ref
|
|
90
|
-
if
|
|
89
|
+
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
90
|
+
if not (view := self.validation_resources.expand_view_properties(view_ref)):
|
|
91
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug in NEAT.")
|
|
92
|
+
|
|
93
|
+
if view.properties and len(view.properties) > self.validation_resources.limits.views.properties:
|
|
91
94
|
errors.append(
|
|
92
95
|
ConsistencyError(
|
|
93
96
|
message=(
|
|
94
|
-
f"View {view_ref!s} has {len(properties)} properties,"
|
|
97
|
+
f"View {view_ref!s} has {len(view.properties)} properties,"
|
|
95
98
|
" which exceeds the limit of "
|
|
96
99
|
f"{self.validation_resources.limits.views.properties} properties per view."
|
|
97
100
|
),
|
|
@@ -99,7 +102,7 @@ class ViewPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
99
102
|
)
|
|
100
103
|
)
|
|
101
104
|
|
|
102
|
-
elif not properties:
|
|
105
|
+
elif not view.properties:
|
|
103
106
|
errors.append(
|
|
104
107
|
ConsistencyError(
|
|
105
108
|
message=(
|
|
@@ -136,12 +139,15 @@ class ViewContainerCountIsOutOfLimits(DataModelValidator):
|
|
|
136
139
|
errors: list[ConsistencyError] = []
|
|
137
140
|
|
|
138
141
|
# Single loop over all views
|
|
139
|
-
for view_ref
|
|
140
|
-
if
|
|
142
|
+
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
143
|
+
if not (view := self.validation_resources.expand_view_properties(view_ref)):
|
|
144
|
+
raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug in NEAT.")
|
|
145
|
+
|
|
146
|
+
if view.properties:
|
|
141
147
|
count = len(
|
|
142
148
|
{
|
|
143
149
|
prop.container
|
|
144
|
-
for prop in properties.values()
|
|
150
|
+
for prop in view.properties.values()
|
|
145
151
|
if (isinstance(prop, ViewCorePropertyRequest) and prop.container)
|
|
146
152
|
}
|
|
147
153
|
)
|
|
@@ -181,7 +187,8 @@ class ViewImplementsCountIsOutOfLimits(DataModelValidator):
|
|
|
181
187
|
errors: list[ConsistencyError] = []
|
|
182
188
|
|
|
183
189
|
# Single loop over all views
|
|
184
|
-
for view_ref
|
|
190
|
+
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
191
|
+
ancestors = self.validation_resources.view_ancestors(view_ref)
|
|
185
192
|
if ancestors and len(ancestors) > self.validation_resources.limits.views.implements:
|
|
186
193
|
errors.append(
|
|
187
194
|
ConsistencyError(
|
|
@@ -220,7 +227,15 @@ class ContainerPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
220
227
|
def run(self) -> list[ConsistencyError]:
|
|
221
228
|
errors: list[ConsistencyError] = []
|
|
222
229
|
# Single loop over all containers
|
|
223
|
-
for container_ref
|
|
230
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
231
|
+
container = self.validation_resources.select_container(container_ref)
|
|
232
|
+
|
|
233
|
+
if not container:
|
|
234
|
+
raise RuntimeError(
|
|
235
|
+
f"{type(self).__name__}: Container {container_ref!s} "
|
|
236
|
+
"not found in local resources. This is a bug in NEAT."
|
|
237
|
+
)
|
|
238
|
+
|
|
224
239
|
if (
|
|
225
240
|
container.properties
|
|
226
241
|
and len(container.properties) > self.validation_resources.limits.containers.properties()
|
|
@@ -277,7 +292,15 @@ class ContainerPropertyListSizeIsOutOfLimits(DataModelValidator):
|
|
|
277
292
|
errors: list[ConsistencyError] = []
|
|
278
293
|
|
|
279
294
|
# Single loop over all containers
|
|
280
|
-
for container_ref
|
|
295
|
+
for container_ref in self.validation_resources.merged.containers:
|
|
296
|
+
container = self.validation_resources.select_container(container_ref)
|
|
297
|
+
|
|
298
|
+
if not container:
|
|
299
|
+
raise RuntimeError(
|
|
300
|
+
f"{type(self).__name__}: Container {container_ref!s} "
|
|
301
|
+
"not found in local resources. This is a bug in NEAT."
|
|
302
|
+
)
|
|
303
|
+
|
|
281
304
|
properties_by_index_type = self.container_property_by_index_type(container)
|
|
282
305
|
|
|
283
306
|
for property_id, property_ in container.properties.items():
|
|
@@ -37,8 +37,7 @@ class ViewToContainerMappingNotPossible(DataModelValidator):
|
|
|
37
37
|
|
|
38
38
|
if not view:
|
|
39
39
|
raise RuntimeError(
|
|
40
|
-
f"
|
|
41
|
-
"not found in local resources. This is a bug in NEAT."
|
|
40
|
+
f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
|
|
42
41
|
)
|
|
43
42
|
|
|
44
43
|
if view.properties is None:
|
|
@@ -109,8 +108,7 @@ class ImplementedViewNotExisting(DataModelValidator):
|
|
|
109
108
|
|
|
110
109
|
if not view:
|
|
111
110
|
raise RuntimeError(
|
|
112
|
-
f"
|
|
113
|
-
"not found in local resources. This is a bug in NEAT."
|
|
111
|
+
f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
|
|
114
112
|
)
|
|
115
113
|
|
|
116
114
|
if view.implements is None:
|
|
@@ -36,10 +36,14 @@ def session_wrapper(cls: type[T_Class]) -> type[T_Class]:
|
|
|
36
36
|
change = self._store.provenance[-1]
|
|
37
37
|
|
|
38
38
|
recommendation_count = (
|
|
39
|
-
len(
|
|
39
|
+
len(recommendations)
|
|
40
|
+
if change.issues and (recommendations := change.issues.by_type().get(Recommendation))
|
|
41
|
+
else 0
|
|
40
42
|
)
|
|
41
43
|
consistency_errors_count = (
|
|
42
|
-
len(
|
|
44
|
+
len(consistency_errors)
|
|
45
|
+
if change.issues and (consistency_errors := change.issues.by_type().get(ConsistencyError))
|
|
46
|
+
else 0
|
|
43
47
|
)
|
|
44
48
|
syntax_errors_count = len(change.errors) if change.errors else 0
|
|
45
49
|
errors_count = consistency_errors_count + syntax_errors_count
|
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "1.0.
|
|
1
|
+
__version__ = "1.0.15"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cognite-neat
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.15
|
|
4
4
|
Summary: Knowledge graph transformation
|
|
5
5
|
Author: Nikola Vasiljevic, Anders Albert
|
|
6
6
|
Author-email: Nikola Vasiljevic <nikola.vasiljevic@cognite.com>, Anders Albert <anders.albert@cognite.com>
|
|
@@ -11,7 +11,7 @@ cognite/neat/_client/statistics_api.py,sha256=HcYb2nNC9M_iaI1xyjjLn2Cz1tcyu7BJea
|
|
|
11
11
|
cognite/neat/_client/views_api.py,sha256=Qzk_wiLtaWszxCQFDBoWCH1yDc4GOEJsVOcL061rcK0,5639
|
|
12
12
|
cognite/neat/_config.py,sha256=Ryxk6_TTFXBclhtnUlPuYFnV--GOVl45D2A9xAGZAms,9703
|
|
13
13
|
cognite/neat/_data_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
cognite/neat/_data_model/_analysis.py,sha256=
|
|
14
|
+
cognite/neat/_data_model/_analysis.py,sha256=x6E6c-T2tq3yGcnDeX7mxih1FSRNs7cGDf75BsIcoFI,16264
|
|
15
15
|
cognite/neat/_data_model/_constants.py,sha256=txKFNRPkCRrIkXbf_bLCYBCMkoE_7nc5LliohzMGwOs,1596
|
|
16
16
|
cognite/neat/_data_model/_identifiers.py,sha256=2l_bCtuE6TVZLCnzV7hhAUTP0kU6ji4QlIK-JhRK1fM,1922
|
|
17
17
|
cognite/neat/_data_model/_shared.py,sha256=H0gFqa8tKFNWuvdat5jL6OwySjCw3aQkLPY3wtb9Wrw,1302
|
|
@@ -71,14 +71,14 @@ cognite/neat/_data_model/models/entities/_identifiers.py,sha256=Ab_cMPbk5b0tKniv
|
|
|
71
71
|
cognite/neat/_data_model/models/entities/_parser.py,sha256=zef_pSDZYMZrJl4IKreFDR577KutfhtN1xpH3Ayjt2o,7669
|
|
72
72
|
cognite/neat/_data_model/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
73
|
cognite/neat/_data_model/validation/dms/__init__.py,sha256=kKD18-Bg_G-w11Cs7Wv_TKV0C_q62Pm2RKLpOz27ar4,2642
|
|
74
|
-
cognite/neat/_data_model/validation/dms/_ai_readiness.py,sha256=
|
|
74
|
+
cognite/neat/_data_model/validation/dms/_ai_readiness.py,sha256=bffMQJ5pqumU5P3KaEdQP67OO5eMKqzN2BAWbUjG6KE,16143
|
|
75
75
|
cognite/neat/_data_model/validation/dms/_base.py,sha256=6MfdpLIh9sdCSCihxxhxJQkPc2-v81SCop57SR5z_ms,786
|
|
76
|
-
cognite/neat/_data_model/validation/dms/_connections.py,sha256
|
|
76
|
+
cognite/neat/_data_model/validation/dms/_connections.py,sha256=-kUXf2_3V50ckxwXRwJoTHsKkS5zxiBKkkkHg8Dm4WI,30353
|
|
77
77
|
cognite/neat/_data_model/validation/dms/_consistency.py,sha256=IKSUoRQfQQcsymviESW9VuTFX7jsZMXfsObeZHPdov4,2435
|
|
78
|
-
cognite/neat/_data_model/validation/dms/_containers.py,sha256=
|
|
79
|
-
cognite/neat/_data_model/validation/dms/_limits.py,sha256=
|
|
78
|
+
cognite/neat/_data_model/validation/dms/_containers.py,sha256=5Lka1Cg-SaP9Ued0cku0leG1Sjx76JQ9XcBZK_dtfuM,8520
|
|
79
|
+
cognite/neat/_data_model/validation/dms/_limits.py,sha256=U7z8sN-kAyJsF5hYHPNBBg25Fvz1F8njhzYVSQOIiOU,14779
|
|
80
80
|
cognite/neat/_data_model/validation/dms/_orchestrator.py,sha256=iNFPgp0KTx2Nvq-XeJ12qO0s7oJKj4kHrZ16dDWe-HQ,2758
|
|
81
|
-
cognite/neat/_data_model/validation/dms/_views.py,sha256=
|
|
81
|
+
cognite/neat/_data_model/validation/dms/_views.py,sha256=Q0x7jdG69-AVc93VrwdZ1_rFHpq-I-OG98puM4lcweE,5068
|
|
82
82
|
cognite/neat/_exceptions.py,sha256=ox-5hXpee4UJlPE7HpuEHV2C96aLbLKo-BhPDoOAzhA,1650
|
|
83
83
|
cognite/neat/_issues.py,sha256=wH1mnkrpBsHUkQMGUHFLUIQWQlfJ_qMfdF7q0d9wNhY,1871
|
|
84
84
|
cognite/neat/_session/__init__.py,sha256=owqW5Mml2DSZx1AvPvwNRTBngfhBNrQ6EH-7CKL7Jp0,61
|
|
@@ -107,7 +107,7 @@ cognite/neat/_session/_usage_analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
|
|
|
107
107
|
cognite/neat/_session/_usage_analytics/_collector.py,sha256=8yVfzt8KFfZ-ldkVjDWazuQbs45Q3r6vWKcZEwU8i18,4734
|
|
108
108
|
cognite/neat/_session/_usage_analytics/_constants.py,sha256=-tVdYrCTMKfuMlbO7AlzC29Nug41ug6uuX9DFuihpJg,561
|
|
109
109
|
cognite/neat/_session/_usage_analytics/_storage.py,sha256=w3mUvmPysww6vM3PZBjg6jzNEsDISl7FJ1j19LNs26E,7779
|
|
110
|
-
cognite/neat/_session/_wrappers.py,sha256=
|
|
110
|
+
cognite/neat/_session/_wrappers.py,sha256=28RjNsRs6317Ml-ZHFytBT7c8z_aMQ-adkQVtrzEC6U,4412
|
|
111
111
|
cognite/neat/_state_machine/__init__.py,sha256=wrtQUHETiLzYM0pFo7JC6pJCiXetHADQbyMu8pU8rQU,195
|
|
112
112
|
cognite/neat/_state_machine/_base.py,sha256=-ZpeAhM6l6N6W70dET25tAzOxaaK5aa474eabwZVzjA,1112
|
|
113
113
|
cognite/neat/_state_machine/_states.py,sha256=nmj4SmunpDYcBsNx8A284xnXGS43wuUuWpMMORha2DE,1170
|
|
@@ -316,9 +316,9 @@ cognite/neat/_v0/session/_template.py,sha256=BNcvrW5y7LWzRM1XFxZkfR1Nc7e8UgjBClH
|
|
|
316
316
|
cognite/neat/_v0/session/_to.py,sha256=AnsRSDDdfFyYwSgi0Z-904X7WdLtPfLlR0x1xsu_jAo,19447
|
|
317
317
|
cognite/neat/_v0/session/_wizard.py,sha256=baPJgXAAF3d1bn4nbIzon1gWfJOeS5T43UXRDJEnD3c,1490
|
|
318
318
|
cognite/neat/_v0/session/exceptions.py,sha256=jv52D-SjxGfgqaHR8vnpzo0SOJETIuwbyffSWAxSDJw,3495
|
|
319
|
-
cognite/neat/_version.py,sha256=
|
|
319
|
+
cognite/neat/_version.py,sha256=268u-66yyUprLq8ofXrWuOM4lnZC4230kYs69ctFk1s,45
|
|
320
320
|
cognite/neat/legacy.py,sha256=eI2ecxOV8ilGHyLZlN54ve_abtoK34oXognkFv3yvF0,219
|
|
321
321
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
322
|
-
cognite_neat-1.0.
|
|
323
|
-
cognite_neat-1.0.
|
|
324
|
-
cognite_neat-1.0.
|
|
322
|
+
cognite_neat-1.0.15.dist-info/WHEEL,sha256=ZyFSCYkV2BrxH6-HRVRg3R9Fo7MALzer9KiPYqNxSbo,79
|
|
323
|
+
cognite_neat-1.0.15.dist-info/METADATA,sha256=cduxycIq6NfXphIiQ4ERvE0zDgsSY9RZjGwPSVx1pO0,6091
|
|
324
|
+
cognite_neat-1.0.15.dist-info/RECORD,,
|
|
File without changes
|