cognite-neat 1.0.31__py3-none-any.whl → 1.0.33__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/_client/data_classes.py +32 -0
- cognite/neat/_client/statistics_api.py +28 -1
- cognite/neat/_data_model/_analysis.py +3 -0
- cognite/neat/_data_model/_constants.py +4 -0
- cognite/neat/_data_model/deployer/_differ_container.py +1 -1
- cognite/neat/_data_model/deployer/data_classes.py +15 -16
- cognite/neat/_data_model/deployer/deployer.py +40 -13
- cognite/neat/_data_model/models/dms/_http.py +10 -1
- cognite/neat/_data_model/models/dms/_references.py +38 -4
- cognite/neat/_data_model/{validation/dms → rules}/_base.py +11 -5
- cognite/neat/_data_model/rules/cdf/__init__.py +3 -0
- cognite/neat/_data_model/rules/cdf/_base.py +5 -0
- cognite/neat/_data_model/rules/cdf/_orchestrator.py +56 -0
- cognite/neat/_data_model/rules/cdf/_spaces.py +47 -0
- cognite/neat/_data_model/{validation → rules}/dms/__init__.py +2 -2
- cognite/neat/_data_model/{validation → rules}/dms/_ai_readiness.py +17 -17
- cognite/neat/_data_model/rules/dms/_base.py +5 -0
- cognite/neat/_data_model/{validation → rules}/dms/_connections.py +23 -23
- cognite/neat/_data_model/{validation → rules}/dms/_consistency.py +3 -3
- cognite/neat/_data_model/{validation → rules}/dms/_containers.py +9 -9
- cognite/neat/_data_model/{validation → rules}/dms/_limits.py +14 -14
- cognite/neat/_data_model/{validation → rules}/dms/_orchestrator.py +7 -7
- cognite/neat/_data_model/{validation → rules}/dms/_performance.py +7 -7
- cognite/neat/_data_model/{validation → rules}/dms/_views.py +7 -7
- cognite/neat/_session/_cdf.py +15 -1
- cognite/neat/_session/_physical.py +6 -6
- cognite/neat/_session/_wrappers.py +1 -1
- cognite/neat/_state_machine/_states.py +1 -1
- cognite/neat/_store/_store.py +19 -1
- cognite/neat/_version.py +1 -1
- {cognite_neat-1.0.31.dist-info → cognite_neat-1.0.33.dist-info}/METADATA +1 -1
- {cognite_neat-1.0.31.dist-info → cognite_neat-1.0.33.dist-info}/RECORD +34 -29
- {cognite_neat-1.0.31.dist-info → cognite_neat-1.0.33.dist-info}/WHEEL +1 -1
- /cognite/neat/_data_model/{validation → rules}/__init__.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Validators for checking if data model is AI-ready."""
|
|
2
2
|
|
|
3
3
|
from cognite.neat._data_model.models.dms._data_types import EnumProperty
|
|
4
|
-
from cognite.neat._data_model.
|
|
4
|
+
from cognite.neat._data_model.rules.dms._base import DataModelRule
|
|
5
5
|
from cognite.neat._issues import Recommendation
|
|
6
6
|
|
|
7
7
|
BASE_CODE = "NEAT-DMS-AI-READINESS"
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class DataModelMissingName(
|
|
10
|
+
class DataModelMissingName(DataModelRule):
|
|
11
11
|
"""Validates that data model has a human-readable name.
|
|
12
12
|
|
|
13
13
|
## What it does
|
|
@@ -26,7 +26,7 @@ class DataModelMissingName(DataModelValidator):
|
|
|
26
26
|
code = f"{BASE_CODE}-001"
|
|
27
27
|
issue_type = Recommendation
|
|
28
28
|
|
|
29
|
-
def
|
|
29
|
+
def validate(self) -> list[Recommendation]:
|
|
30
30
|
recommendations: list[Recommendation] = []
|
|
31
31
|
|
|
32
32
|
if not self.validation_resources.merged_data_model.name:
|
|
@@ -41,7 +41,7 @@ class DataModelMissingName(DataModelValidator):
|
|
|
41
41
|
return recommendations
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
class DataModelMissingDescription(
|
|
44
|
+
class DataModelMissingDescription(DataModelRule):
|
|
45
45
|
"""Validates that data model has a human-readable description.
|
|
46
46
|
|
|
47
47
|
## What it does
|
|
@@ -65,7 +65,7 @@ class DataModelMissingDescription(DataModelValidator):
|
|
|
65
65
|
code = f"{BASE_CODE}-002"
|
|
66
66
|
issue_type = Recommendation
|
|
67
67
|
|
|
68
|
-
def
|
|
68
|
+
def validate(self) -> list[Recommendation]:
|
|
69
69
|
recommendations: list[Recommendation] = []
|
|
70
70
|
|
|
71
71
|
if not self.validation_resources.merged_data_model.description:
|
|
@@ -80,7 +80,7 @@ class DataModelMissingDescription(DataModelValidator):
|
|
|
80
80
|
return recommendations
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
class ViewMissingName(
|
|
83
|
+
class ViewMissingName(DataModelRule):
|
|
84
84
|
"""Validates that a View has a human-readable name.
|
|
85
85
|
|
|
86
86
|
## What it does
|
|
@@ -100,7 +100,7 @@ class ViewMissingName(DataModelValidator):
|
|
|
100
100
|
code = f"{BASE_CODE}-003"
|
|
101
101
|
issue_type = Recommendation
|
|
102
102
|
|
|
103
|
-
def
|
|
103
|
+
def validate(self) -> list[Recommendation]:
|
|
104
104
|
recommendations: list[Recommendation] = []
|
|
105
105
|
|
|
106
106
|
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
@@ -121,7 +121,7 @@ class ViewMissingName(DataModelValidator):
|
|
|
121
121
|
return recommendations
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
class ViewMissingDescription(
|
|
124
|
+
class ViewMissingDescription(DataModelRule):
|
|
125
125
|
"""Validates that a View has a human-readable description.
|
|
126
126
|
|
|
127
127
|
## What it does
|
|
@@ -151,7 +151,7 @@ class ViewMissingDescription(DataModelValidator):
|
|
|
151
151
|
code = f"{BASE_CODE}-004"
|
|
152
152
|
issue_type = Recommendation
|
|
153
153
|
|
|
154
|
-
def
|
|
154
|
+
def validate(self) -> list[Recommendation]:
|
|
155
155
|
recommendations: list[Recommendation] = []
|
|
156
156
|
|
|
157
157
|
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
@@ -172,7 +172,7 @@ class ViewMissingDescription(DataModelValidator):
|
|
|
172
172
|
return recommendations
|
|
173
173
|
|
|
174
174
|
|
|
175
|
-
class ViewPropertyMissingName(
|
|
175
|
+
class ViewPropertyMissingName(DataModelRule):
|
|
176
176
|
"""Validates that a view property has a human-readable name.
|
|
177
177
|
|
|
178
178
|
## What it does
|
|
@@ -192,7 +192,7 @@ class ViewPropertyMissingName(DataModelValidator):
|
|
|
192
192
|
code = f"{BASE_CODE}-005"
|
|
193
193
|
issue_type = Recommendation
|
|
194
194
|
|
|
195
|
-
def
|
|
195
|
+
def validate(self) -> list[Recommendation]:
|
|
196
196
|
recommendations: list[Recommendation] = []
|
|
197
197
|
|
|
198
198
|
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
@@ -217,7 +217,7 @@ class ViewPropertyMissingName(DataModelValidator):
|
|
|
217
217
|
return recommendations
|
|
218
218
|
|
|
219
219
|
|
|
220
|
-
class ViewPropertyMissingDescription(
|
|
220
|
+
class ViewPropertyMissingDescription(DataModelRule):
|
|
221
221
|
"""Validates that a View property has a human-readable description.
|
|
222
222
|
|
|
223
223
|
## What it does
|
|
@@ -248,7 +248,7 @@ class ViewPropertyMissingDescription(DataModelValidator):
|
|
|
248
248
|
code = f"{BASE_CODE}-006"
|
|
249
249
|
issue_type = Recommendation
|
|
250
250
|
|
|
251
|
-
def
|
|
251
|
+
def validate(self) -> list[Recommendation]:
|
|
252
252
|
recommendations: list[Recommendation] = []
|
|
253
253
|
|
|
254
254
|
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
@@ -273,7 +273,7 @@ class ViewPropertyMissingDescription(DataModelValidator):
|
|
|
273
273
|
return recommendations
|
|
274
274
|
|
|
275
275
|
|
|
276
|
-
class EnumerationMissingName(
|
|
276
|
+
class EnumerationMissingName(DataModelRule):
|
|
277
277
|
"""Validates that an enumeration has a human-readable name.
|
|
278
278
|
|
|
279
279
|
## What it does
|
|
@@ -293,7 +293,7 @@ class EnumerationMissingName(DataModelValidator):
|
|
|
293
293
|
code = f"{BASE_CODE}-007"
|
|
294
294
|
issue_type = Recommendation
|
|
295
295
|
|
|
296
|
-
def
|
|
296
|
+
def validate(self) -> list[Recommendation]:
|
|
297
297
|
recommendations: list[Recommendation] = []
|
|
298
298
|
|
|
299
299
|
for container_ref in self.validation_resources.merged.containers:
|
|
@@ -322,7 +322,7 @@ class EnumerationMissingName(DataModelValidator):
|
|
|
322
322
|
return recommendations
|
|
323
323
|
|
|
324
324
|
|
|
325
|
-
class EnumerationMissingDescription(
|
|
325
|
+
class EnumerationMissingDescription(DataModelRule):
|
|
326
326
|
"""Validates that an enumeration value has a human-readable description.
|
|
327
327
|
|
|
328
328
|
## What it does
|
|
@@ -353,7 +353,7 @@ class EnumerationMissingDescription(DataModelValidator):
|
|
|
353
353
|
code = f"{BASE_CODE}-008"
|
|
354
354
|
issue_type = Recommendation
|
|
355
355
|
|
|
356
|
-
def
|
|
356
|
+
def validate(self) -> list[Recommendation]:
|
|
357
357
|
recommendations: list[Recommendation] = []
|
|
358
358
|
|
|
359
359
|
for container_ref in self.validation_resources.merged.containers:
|
|
@@ -9,13 +9,13 @@ from cognite.neat._data_model.models.dms._references import (
|
|
|
9
9
|
ViewReference,
|
|
10
10
|
)
|
|
11
11
|
from cognite.neat._data_model.models.dms._view_property import ViewCorePropertyRequest
|
|
12
|
-
from cognite.neat._data_model.
|
|
12
|
+
from cognite.neat._data_model.rules.dms._base import DataModelRule
|
|
13
13
|
from cognite.neat._issues import ConsistencyError, Recommendation
|
|
14
14
|
|
|
15
15
|
BASE_CODE = "NEAT-DMS-CONNECTIONS"
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class ConnectionValueTypeUnexisting(
|
|
18
|
+
class ConnectionValueTypeUnexisting(DataModelRule):
|
|
19
19
|
"""Validates that connection value types exist.
|
|
20
20
|
|
|
21
21
|
## What it does
|
|
@@ -33,7 +33,7 @@ class ConnectionValueTypeUnexisting(DataModelValidator):
|
|
|
33
33
|
code = f"{BASE_CODE}-001"
|
|
34
34
|
issue_type = ConsistencyError
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def validate(self) -> list[ConsistencyError]:
|
|
37
37
|
errors: list[ConsistencyError] = []
|
|
38
38
|
|
|
39
39
|
for (view, property_), value_type in self.validation_resources.connection_end_node_types.items():
|
|
@@ -57,7 +57,7 @@ class ConnectionValueTypeUnexisting(DataModelValidator):
|
|
|
57
57
|
return errors
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
class ConnectionValueTypeUndefined(
|
|
60
|
+
class ConnectionValueTypeUndefined(DataModelRule):
|
|
61
61
|
"""Validates that connection value types are not None, i.e. undefined.
|
|
62
62
|
|
|
63
63
|
## What it does
|
|
@@ -77,7 +77,7 @@ class ConnectionValueTypeUndefined(DataModelValidator):
|
|
|
77
77
|
code = f"{BASE_CODE}-002"
|
|
78
78
|
issue_type = Recommendation
|
|
79
79
|
|
|
80
|
-
def
|
|
80
|
+
def validate(self) -> list[Recommendation]:
|
|
81
81
|
recommendations: list[Recommendation] = []
|
|
82
82
|
|
|
83
83
|
for (view, property_), value_type in self.validation_resources.connection_end_node_types.items():
|
|
@@ -128,7 +128,7 @@ def _normalize_through_reference(
|
|
|
128
128
|
return through
|
|
129
129
|
|
|
130
130
|
|
|
131
|
-
class ReverseConnectionSourceViewMissing(
|
|
131
|
+
class ReverseConnectionSourceViewMissing(DataModelRule):
|
|
132
132
|
"""Validates that source view referenced in reverse connection exist.
|
|
133
133
|
|
|
134
134
|
## What it does
|
|
@@ -146,7 +146,7 @@ class ReverseConnectionSourceViewMissing(DataModelValidator):
|
|
|
146
146
|
code = f"{BASE_CODE}-REVERSE-001"
|
|
147
147
|
issue_type = ConsistencyError
|
|
148
148
|
|
|
149
|
-
def
|
|
149
|
+
def validate(self) -> list[ConsistencyError]:
|
|
150
150
|
errors: list[ConsistencyError] = []
|
|
151
151
|
|
|
152
152
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -172,7 +172,7 @@ class ReverseConnectionSourceViewMissing(DataModelValidator):
|
|
|
172
172
|
return errors
|
|
173
173
|
|
|
174
174
|
|
|
175
|
-
class ReverseConnectionSourcePropertyMissing(
|
|
175
|
+
class ReverseConnectionSourcePropertyMissing(DataModelRule):
|
|
176
176
|
"""Validates that source property referenced in reverse connections exist.
|
|
177
177
|
|
|
178
178
|
## What it does
|
|
@@ -191,7 +191,7 @@ class ReverseConnectionSourcePropertyMissing(DataModelValidator):
|
|
|
191
191
|
code = f"{BASE_CODE}-REVERSE-002"
|
|
192
192
|
issue_type = ConsistencyError
|
|
193
193
|
|
|
194
|
-
def
|
|
194
|
+
def validate(self) -> list[ConsistencyError]:
|
|
195
195
|
errors: list[ConsistencyError] = []
|
|
196
196
|
|
|
197
197
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -224,7 +224,7 @@ class ReverseConnectionSourcePropertyMissing(DataModelValidator):
|
|
|
224
224
|
return errors
|
|
225
225
|
|
|
226
226
|
|
|
227
|
-
class ReverseConnectionSourcePropertyWrongType(
|
|
227
|
+
class ReverseConnectionSourcePropertyWrongType(DataModelRule):
|
|
228
228
|
"""Validates that source property for the reverse connections is a direct relation.
|
|
229
229
|
|
|
230
230
|
## What it does
|
|
@@ -243,7 +243,7 @@ class ReverseConnectionSourcePropertyWrongType(DataModelValidator):
|
|
|
243
243
|
code = f"{BASE_CODE}-REVERSE-003"
|
|
244
244
|
issue_type = ConsistencyError
|
|
245
245
|
|
|
246
|
-
def
|
|
246
|
+
def validate(self) -> list[ConsistencyError]:
|
|
247
247
|
errors: list[ConsistencyError] = []
|
|
248
248
|
|
|
249
249
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -280,7 +280,7 @@ class ReverseConnectionSourcePropertyWrongType(DataModelValidator):
|
|
|
280
280
|
return errors
|
|
281
281
|
|
|
282
282
|
|
|
283
|
-
class ReverseConnectionContainerMissing(
|
|
283
|
+
class ReverseConnectionContainerMissing(DataModelRule):
|
|
284
284
|
"""Validates that the container referenced by the reverse connection source properties exist.
|
|
285
285
|
|
|
286
286
|
## What it does
|
|
@@ -298,7 +298,7 @@ class ReverseConnectionContainerMissing(DataModelValidator):
|
|
|
298
298
|
code = f"{BASE_CODE}-REVERSE-004"
|
|
299
299
|
issue_type = ConsistencyError
|
|
300
300
|
|
|
301
|
-
def
|
|
301
|
+
def validate(self) -> list[ConsistencyError]:
|
|
302
302
|
errors: list[ConsistencyError] = []
|
|
303
303
|
|
|
304
304
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -344,7 +344,7 @@ class ReverseConnectionContainerMissing(DataModelValidator):
|
|
|
344
344
|
return errors
|
|
345
345
|
|
|
346
346
|
|
|
347
|
-
class ReverseConnectionContainerPropertyMissing(
|
|
347
|
+
class ReverseConnectionContainerPropertyMissing(DataModelRule):
|
|
348
348
|
"""Validates that container property referenced by the reverse connections exists.
|
|
349
349
|
|
|
350
350
|
## What it does
|
|
@@ -363,7 +363,7 @@ class ReverseConnectionContainerPropertyMissing(DataModelValidator):
|
|
|
363
363
|
code = f"{BASE_CODE}-REVERSE-005"
|
|
364
364
|
issue_type = ConsistencyError
|
|
365
365
|
|
|
366
|
-
def
|
|
366
|
+
def validate(self) -> list[ConsistencyError]:
|
|
367
367
|
errors: list[ConsistencyError] = []
|
|
368
368
|
|
|
369
369
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -412,7 +412,7 @@ class ReverseConnectionContainerPropertyMissing(DataModelValidator):
|
|
|
412
412
|
return errors
|
|
413
413
|
|
|
414
414
|
|
|
415
|
-
class ReverseConnectionContainerPropertyWrongType(
|
|
415
|
+
class ReverseConnectionContainerPropertyWrongType(DataModelRule):
|
|
416
416
|
"""Validates that the container property used in reverse connection is the direct relations.
|
|
417
417
|
|
|
418
418
|
## What it does
|
|
@@ -431,7 +431,7 @@ class ReverseConnectionContainerPropertyWrongType(DataModelValidator):
|
|
|
431
431
|
code = f"{BASE_CODE}-REVERSE-006"
|
|
432
432
|
issue_type = ConsistencyError
|
|
433
433
|
|
|
434
|
-
def
|
|
434
|
+
def validate(self) -> list[ConsistencyError]:
|
|
435
435
|
errors: list[ConsistencyError] = []
|
|
436
436
|
|
|
437
437
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -483,7 +483,7 @@ class ReverseConnectionContainerPropertyWrongType(DataModelValidator):
|
|
|
483
483
|
return errors
|
|
484
484
|
|
|
485
485
|
|
|
486
|
-
class ReverseConnectionTargetMissing(
|
|
486
|
+
class ReverseConnectionTargetMissing(DataModelRule):
|
|
487
487
|
"""Validates that the direct connection in reverse connection pair have target views specified.
|
|
488
488
|
|
|
489
489
|
## What it does
|
|
@@ -501,7 +501,7 @@ class ReverseConnectionTargetMissing(DataModelValidator):
|
|
|
501
501
|
code = f"{BASE_CODE}-REVERSE-007"
|
|
502
502
|
issue_type = Recommendation
|
|
503
503
|
|
|
504
|
-
def
|
|
504
|
+
def validate(self) -> list[Recommendation]:
|
|
505
505
|
recommendations: list[Recommendation] = []
|
|
506
506
|
|
|
507
507
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -546,7 +546,7 @@ class ReverseConnectionTargetMissing(DataModelValidator):
|
|
|
546
546
|
return recommendations
|
|
547
547
|
|
|
548
548
|
|
|
549
|
-
class ReverseConnectionPointsToAncestor(
|
|
549
|
+
class ReverseConnectionPointsToAncestor(DataModelRule):
|
|
550
550
|
"""Validates that direct connections point to specific views rather than ancestors.
|
|
551
551
|
|
|
552
552
|
## What it does
|
|
@@ -565,7 +565,7 @@ class ReverseConnectionPointsToAncestor(DataModelValidator):
|
|
|
565
565
|
code = f"{BASE_CODE}-REVERSE-008"
|
|
566
566
|
issue_type = Recommendation
|
|
567
567
|
|
|
568
|
-
def
|
|
568
|
+
def validate(self) -> list[Recommendation]:
|
|
569
569
|
recommendations: list[Recommendation] = []
|
|
570
570
|
|
|
571
571
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -613,7 +613,7 @@ class ReverseConnectionPointsToAncestor(DataModelValidator):
|
|
|
613
613
|
return recommendations
|
|
614
614
|
|
|
615
615
|
|
|
616
|
-
class ReverseConnectionTargetMismatch(
|
|
616
|
+
class ReverseConnectionTargetMismatch(DataModelRule):
|
|
617
617
|
"""Validates that direct connections point to the correct target views.
|
|
618
618
|
|
|
619
619
|
## What it does
|
|
@@ -632,7 +632,7 @@ class ReverseConnectionTargetMismatch(DataModelValidator):
|
|
|
632
632
|
code = f"{BASE_CODE}-REVERSE-009"
|
|
633
633
|
issue_type = Recommendation
|
|
634
634
|
|
|
635
|
-
def
|
|
635
|
+
def validate(self) -> list[Recommendation]:
|
|
636
636
|
recommendations: list[Recommendation] = []
|
|
637
637
|
|
|
638
638
|
for (target_view_ref, reverse_prop_name), (
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Validators checking for consistency issues in data model."""
|
|
2
2
|
|
|
3
3
|
from cognite.neat._data_model._constants import COGNITE_SPACES
|
|
4
|
-
from cognite.neat._data_model.
|
|
4
|
+
from cognite.neat._data_model.rules.dms._base import DataModelRule
|
|
5
5
|
from cognite.neat._issues import Recommendation
|
|
6
6
|
|
|
7
7
|
BASE_CODE = "NEAT-DMS-CONSISTENCY"
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class ViewSpaceVersionInconsistentWithDataModel(
|
|
10
|
+
class ViewSpaceVersionInconsistentWithDataModel(DataModelRule):
|
|
11
11
|
"""Validates that views have consistent space and version with the data model.
|
|
12
12
|
|
|
13
13
|
## What it does
|
|
@@ -25,7 +25,7 @@ class ViewSpaceVersionInconsistentWithDataModel(DataModelValidator):
|
|
|
25
25
|
code = f"{BASE_CODE}-001"
|
|
26
26
|
issue_type = Recommendation
|
|
27
27
|
|
|
28
|
-
def
|
|
28
|
+
def validate(self) -> list[Recommendation]:
|
|
29
29
|
recommendations: list[Recommendation] = []
|
|
30
30
|
|
|
31
31
|
if not self.validation_resources.merged_data_model.views:
|
|
@@ -4,13 +4,13 @@ from pyparsing import cast
|
|
|
4
4
|
|
|
5
5
|
from cognite.neat._data_model.models.dms._constraints import Constraint, RequiresConstraintDefinition
|
|
6
6
|
from cognite.neat._data_model.models.dms._view_property import ViewCorePropertyRequest
|
|
7
|
-
from cognite.neat._data_model.
|
|
7
|
+
from cognite.neat._data_model.rules.dms._base import DataModelRule
|
|
8
8
|
from cognite.neat._issues import ConsistencyError
|
|
9
9
|
|
|
10
10
|
BASE_CODE = "NEAT-DMS-CONTAINER"
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class ExternalContainerDoesNotExist(
|
|
13
|
+
class ExternalContainerDoesNotExist(DataModelRule):
|
|
14
14
|
"""
|
|
15
15
|
Validates that any container referenced by a view property, when the
|
|
16
16
|
referenced container does not belong to the data model's space, exists in CDF.
|
|
@@ -33,7 +33,7 @@ class ExternalContainerDoesNotExist(DataModelValidator):
|
|
|
33
33
|
code = f"{BASE_CODE}-001"
|
|
34
34
|
issue_type = ConsistencyError
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def validate(self) -> list[ConsistencyError]:
|
|
37
37
|
errors: list[ConsistencyError] = []
|
|
38
38
|
|
|
39
39
|
if not self.validation_resources.merged_data_model.views:
|
|
@@ -73,7 +73,7 @@ class ExternalContainerDoesNotExist(DataModelValidator):
|
|
|
73
73
|
return errors
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
class ExternalContainerPropertyDoesNotExist(
|
|
76
|
+
class ExternalContainerPropertyDoesNotExist(DataModelRule):
|
|
77
77
|
"""
|
|
78
78
|
Validates that any container property referenced by a view property, when the
|
|
79
79
|
referenced container does not belong to the data model's space, exists in CDF.
|
|
@@ -97,7 +97,7 @@ class ExternalContainerPropertyDoesNotExist(DataModelValidator):
|
|
|
97
97
|
code = f"{BASE_CODE}-002"
|
|
98
98
|
issue_type = ConsistencyError
|
|
99
99
|
|
|
100
|
-
def
|
|
100
|
+
def validate(self) -> list[ConsistencyError]:
|
|
101
101
|
errors: list[ConsistencyError] = []
|
|
102
102
|
|
|
103
103
|
if self.validation_resources.merged_data_model.views:
|
|
@@ -144,7 +144,7 @@ class ExternalContainerPropertyDoesNotExist(DataModelValidator):
|
|
|
144
144
|
return errors
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
class RequiredContainerDoesNotExist(
|
|
147
|
+
class RequiredContainerDoesNotExist(DataModelRule):
|
|
148
148
|
"""
|
|
149
149
|
Validates that any container required by another container exists in the data model.
|
|
150
150
|
|
|
@@ -165,7 +165,7 @@ class RequiredContainerDoesNotExist(DataModelValidator):
|
|
|
165
165
|
code = f"{BASE_CODE}-003"
|
|
166
166
|
issue_type = ConsistencyError
|
|
167
167
|
|
|
168
|
-
def
|
|
168
|
+
def validate(self) -> list[ConsistencyError]:
|
|
169
169
|
errors: list[ConsistencyError] = []
|
|
170
170
|
|
|
171
171
|
for container_ref in self.validation_resources.merged.containers:
|
|
@@ -199,7 +199,7 @@ class RequiredContainerDoesNotExist(DataModelValidator):
|
|
|
199
199
|
return errors
|
|
200
200
|
|
|
201
201
|
|
|
202
|
-
class RequiresConstraintCycle(
|
|
202
|
+
class RequiresConstraintCycle(DataModelRule):
|
|
203
203
|
"""
|
|
204
204
|
Validates that requires constraints between containers do not form cycles.
|
|
205
205
|
|
|
@@ -221,7 +221,7 @@ class RequiresConstraintCycle(DataModelValidator):
|
|
|
221
221
|
issue_type = ConsistencyError
|
|
222
222
|
alpha = True # Still in development
|
|
223
223
|
|
|
224
|
-
def
|
|
224
|
+
def validate(self) -> list[ConsistencyError]:
|
|
225
225
|
errors: list[ConsistencyError] = []
|
|
226
226
|
optimal_edges = self.validation_resources.oriented_mst_edges
|
|
227
227
|
|
|
@@ -8,15 +8,15 @@ from cognite.neat._data_model.models.dms._indexes import BtreeIndex, InvertedInd
|
|
|
8
8
|
from cognite.neat._data_model.models.dms._view_property import (
|
|
9
9
|
ViewCorePropertyRequest,
|
|
10
10
|
)
|
|
11
|
-
from cognite.neat._data_model.
|
|
12
|
-
|
|
11
|
+
from cognite.neat._data_model.rules.dms._base import (
|
|
12
|
+
DataModelRule,
|
|
13
13
|
)
|
|
14
14
|
from cognite.neat._issues import ConsistencyError, Recommendation
|
|
15
15
|
|
|
16
16
|
BASE_CODE = "NEAT-DMS-LIMITS"
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class DataModelViewCountIsOutOfLimits(
|
|
19
|
+
class DataModelViewCountIsOutOfLimits(DataModelRule):
|
|
20
20
|
"""Validates that the data model does not exceed the maximum number of views.
|
|
21
21
|
|
|
22
22
|
## What it does
|
|
@@ -36,7 +36,7 @@ class DataModelViewCountIsOutOfLimits(DataModelValidator):
|
|
|
36
36
|
code = f"{BASE_CODE}-DATA-MODEL-001"
|
|
37
37
|
issue_type = ConsistencyError
|
|
38
38
|
|
|
39
|
-
def
|
|
39
|
+
def validate(self) -> list[ConsistencyError]:
|
|
40
40
|
errors: list[ConsistencyError] = []
|
|
41
41
|
|
|
42
42
|
if self.validation_resources.merged_data_model.views is None:
|
|
@@ -66,7 +66,7 @@ class DataModelViewCountIsOutOfLimits(DataModelValidator):
|
|
|
66
66
|
### View level limits
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
class ViewPropertyCountIsOutOfLimits(
|
|
69
|
+
class ViewPropertyCountIsOutOfLimits(DataModelRule):
|
|
70
70
|
"""Validates that a view does not exceed the maximum number of properties.
|
|
71
71
|
|
|
72
72
|
## What it does
|
|
@@ -83,7 +83,7 @@ class ViewPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
83
83
|
code = f"{BASE_CODE}-VIEW-001"
|
|
84
84
|
issue_type = ConsistencyError
|
|
85
85
|
|
|
86
|
-
def
|
|
86
|
+
def validate(self) -> list[ConsistencyError]:
|
|
87
87
|
errors: list[ConsistencyError] = []
|
|
88
88
|
|
|
89
89
|
for view_ref in self.validation_resources.merged_data_model.views or []:
|
|
@@ -117,7 +117,7 @@ class ViewPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
117
117
|
return errors
|
|
118
118
|
|
|
119
119
|
|
|
120
|
-
class ViewContainerCountIsOutOfLimits(
|
|
120
|
+
class ViewContainerCountIsOutOfLimits(DataModelRule):
|
|
121
121
|
"""Validates that a view does not reference too many containers.
|
|
122
122
|
|
|
123
123
|
## What it does
|
|
@@ -135,7 +135,7 @@ class ViewContainerCountIsOutOfLimits(DataModelValidator):
|
|
|
135
135
|
code = f"{BASE_CODE}-VIEW-002"
|
|
136
136
|
issue_type = Recommendation
|
|
137
137
|
|
|
138
|
-
def
|
|
138
|
+
def validate(self) -> list[Recommendation]:
|
|
139
139
|
recommendations: list[Recommendation] = []
|
|
140
140
|
|
|
141
141
|
# Single loop over all views
|
|
@@ -166,7 +166,7 @@ class ViewContainerCountIsOutOfLimits(DataModelValidator):
|
|
|
166
166
|
return recommendations
|
|
167
167
|
|
|
168
168
|
|
|
169
|
-
class ViewImplementsCountIsOutOfLimits(
|
|
169
|
+
class ViewImplementsCountIsOutOfLimits(DataModelRule):
|
|
170
170
|
"""Validates that a view does not implement too many other views.
|
|
171
171
|
|
|
172
172
|
## What it does
|
|
@@ -183,7 +183,7 @@ class ViewImplementsCountIsOutOfLimits(DataModelValidator):
|
|
|
183
183
|
code = f"{BASE_CODE}-VIEW-003"
|
|
184
184
|
issue_type = ConsistencyError
|
|
185
185
|
|
|
186
|
-
def
|
|
186
|
+
def validate(self) -> list[ConsistencyError]:
|
|
187
187
|
errors: list[ConsistencyError] = []
|
|
188
188
|
|
|
189
189
|
# Single loop over all views
|
|
@@ -206,7 +206,7 @@ class ViewImplementsCountIsOutOfLimits(DataModelValidator):
|
|
|
206
206
|
### Container level limits
|
|
207
207
|
|
|
208
208
|
|
|
209
|
-
class ContainerPropertyCountIsOutOfLimits(
|
|
209
|
+
class ContainerPropertyCountIsOutOfLimits(DataModelRule):
|
|
210
210
|
"""Validates that a container does not exceed the maximum number of properties.
|
|
211
211
|
|
|
212
212
|
## What it does
|
|
@@ -224,7 +224,7 @@ class ContainerPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
224
224
|
code = f"{BASE_CODE}-CONTAINER-001"
|
|
225
225
|
issue_type = ConsistencyError
|
|
226
226
|
|
|
227
|
-
def
|
|
227
|
+
def validate(self) -> list[ConsistencyError]:
|
|
228
228
|
errors: list[ConsistencyError] = []
|
|
229
229
|
# Single loop over all containers
|
|
230
230
|
for container_ref in self.validation_resources.merged.containers:
|
|
@@ -263,7 +263,7 @@ class ContainerPropertyCountIsOutOfLimits(DataModelValidator):
|
|
|
263
263
|
return errors
|
|
264
264
|
|
|
265
265
|
|
|
266
|
-
class ContainerPropertyListSizeIsOutOfLimits(
|
|
266
|
+
class ContainerPropertyListSizeIsOutOfLimits(DataModelRule):
|
|
267
267
|
"""Validates that container property list sizes do not exceed CDF limits.
|
|
268
268
|
|
|
269
269
|
## What it does
|
|
@@ -288,7 +288,7 @@ class ContainerPropertyListSizeIsOutOfLimits(DataModelValidator):
|
|
|
288
288
|
code = f"{BASE_CODE}-CONTAINER-002"
|
|
289
289
|
issue_type = ConsistencyError
|
|
290
290
|
|
|
291
|
-
def
|
|
291
|
+
def validate(self) -> list[ConsistencyError]:
|
|
292
292
|
errors: list[ConsistencyError] = []
|
|
293
293
|
|
|
294
294
|
# Single loop over all containers
|
|
@@ -6,14 +6,14 @@ from cognite.neat._data_model._shared import OnSuccessIssuesChecker
|
|
|
6
6
|
from cognite.neat._data_model._snapshot import SchemaSnapshot
|
|
7
7
|
from cognite.neat._data_model.models.dms._limits import SchemaLimits
|
|
8
8
|
from cognite.neat._data_model.models.dms._schema import RequestSchema
|
|
9
|
+
from cognite.neat._data_model.rules.dms._base import DataModelRule
|
|
9
10
|
from cognite.neat._utils.auxiliary import get_concrete_subclasses
|
|
10
11
|
from cognite.neat._utils.useful_types import ModusOperandi
|
|
11
12
|
|
|
12
|
-
from ._base import DataModelValidator
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
class DmsDataModelRulesOrchestrator(OnSuccessIssuesChecker):
|
|
15
|
+
"""DMS Data Model rules orchestrator, used to execute DMS data model rules on a single data model represented
|
|
16
|
+
as RequestSchema."""
|
|
17
17
|
|
|
18
18
|
def __init__(
|
|
19
19
|
self,
|
|
@@ -37,8 +37,8 @@ class DmsDataModelValidation(OnSuccessIssuesChecker):
|
|
|
37
37
|
validation_resources = self._gather_validation_resources(request_schema)
|
|
38
38
|
|
|
39
39
|
# Initialize all validators
|
|
40
|
-
validators: list[
|
|
41
|
-
validator(validation_resources) for validator in get_concrete_subclasses(
|
|
40
|
+
validators: list[DataModelRule] = [
|
|
41
|
+
validator(validation_resources) for validator in get_concrete_subclasses(DataModelRule)
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
# Run validators
|
|
@@ -46,7 +46,7 @@ class DmsDataModelValidation(OnSuccessIssuesChecker):
|
|
|
46
46
|
if validator.alpha and not self._enable_alpha_validators:
|
|
47
47
|
continue
|
|
48
48
|
if self._can_run_validator(validator.code, validator.issue_type):
|
|
49
|
-
self._issues.extend(validator.
|
|
49
|
+
self._issues.extend(validator.validate())
|
|
50
50
|
|
|
51
51
|
self._has_run = True
|
|
52
52
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from cognite.neat._data_model._analysis import RequiresChangeStatus
|
|
4
4
|
from cognite.neat._data_model._constants import COGNITE_SPACES
|
|
5
|
-
from cognite.neat._data_model.
|
|
5
|
+
from cognite.neat._data_model.rules.dms._base import DataModelRule
|
|
6
6
|
from cognite.neat._issues import Recommendation
|
|
7
7
|
|
|
8
8
|
BASE_CODE = "NEAT-DMS-PERFORMANCE"
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class MissingRequiresConstraint(
|
|
11
|
+
class MissingRequiresConstraint(DataModelRule):
|
|
12
12
|
"""
|
|
13
13
|
Recommends adding requires constraints to optimize query performance.
|
|
14
14
|
|
|
@@ -31,7 +31,7 @@ class MissingRequiresConstraint(DataModelValidator):
|
|
|
31
31
|
issue_type = Recommendation
|
|
32
32
|
alpha = True
|
|
33
33
|
|
|
34
|
-
def
|
|
34
|
+
def validate(self) -> list[Recommendation]:
|
|
35
35
|
recommendations: list[Recommendation] = []
|
|
36
36
|
|
|
37
37
|
for view_ref in self.validation_resources.merged.views:
|
|
@@ -75,7 +75,7 @@ class MissingRequiresConstraint(DataModelValidator):
|
|
|
75
75
|
return recommendations
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
class SuboptimalRequiresConstraint(
|
|
78
|
+
class SuboptimalRequiresConstraint(DataModelRule):
|
|
79
79
|
"""
|
|
80
80
|
Recommends removing requires constraints that are not optimal.
|
|
81
81
|
|
|
@@ -100,7 +100,7 @@ class SuboptimalRequiresConstraint(DataModelValidator):
|
|
|
100
100
|
issue_type = Recommendation
|
|
101
101
|
alpha = True
|
|
102
102
|
|
|
103
|
-
def
|
|
103
|
+
def validate(self) -> list[Recommendation]:
|
|
104
104
|
recommendations: list[Recommendation] = []
|
|
105
105
|
|
|
106
106
|
for view_ref in self.validation_resources.merged.views:
|
|
@@ -125,7 +125,7 @@ class SuboptimalRequiresConstraint(DataModelValidator):
|
|
|
125
125
|
return recommendations
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
class UnresolvableQueryPerformance(
|
|
128
|
+
class UnresolvableQueryPerformance(DataModelRule):
|
|
129
129
|
"""
|
|
130
130
|
Identifies views with query performance issues that cannot be resolved.
|
|
131
131
|
This is likely to be caused by unintended modeling choices.
|
|
@@ -158,7 +158,7 @@ class UnresolvableQueryPerformance(DataModelValidator):
|
|
|
158
158
|
issue_type = Recommendation
|
|
159
159
|
alpha = True
|
|
160
160
|
|
|
161
|
-
def
|
|
161
|
+
def validate(self) -> list[Recommendation]:
|
|
162
162
|
recommendations: list[Recommendation] = []
|
|
163
163
|
|
|
164
164
|
for view_ref in self.validation_resources.merged.views:
|