cognite-neat 0.127.15__py3-none-any.whl → 0.127.17__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/importers/_table_importer/data_classes.py +3 -4
- cognite/neat/_data_model/validation/dms/__init__.py +2 -0
- cognite/neat/_data_model/validation/dms/_base.py +11 -9
- cognite/neat/_data_model/validation/dms/_containers.py +79 -0
- cognite/neat/_data_model/validation/dms/_orchestrator.py +3 -0
- cognite/neat/_version.py +1 -1
- {cognite_neat-0.127.15.dist-info → cognite_neat-0.127.17.dist-info}/METADATA +1 -1
- {cognite_neat-0.127.15.dist-info → cognite_neat-0.127.17.dist-info}/RECORD +10 -9
- {cognite_neat-0.127.15.dist-info → cognite_neat-0.127.17.dist-info}/WHEEL +0 -0
- {cognite_neat-0.127.15.dist-info → cognite_neat-0.127.17.dist-info}/licenses/LICENSE +0 -0
|
@@ -180,16 +180,15 @@ class DMSContainer(TableObj):
|
|
|
180
180
|
return self
|
|
181
181
|
|
|
182
182
|
for constraint in self.constraint:
|
|
183
|
-
# Skip if already in correct format
|
|
184
|
-
if constraint.prefix
|
|
183
|
+
# Skip if already in correct format or being wrong but not legacy
|
|
184
|
+
if constraint.prefix == "requires" or constraint.properties:
|
|
185
185
|
continue
|
|
186
186
|
|
|
187
|
-
#
|
|
187
|
+
# This part handles legacy constraints
|
|
188
188
|
if not constraint.prefix:
|
|
189
189
|
constraint.prefix = "requires"
|
|
190
190
|
constraint.properties = {"require": constraint.suffix}
|
|
191
191
|
|
|
192
|
-
# Handle legacy format with space:external_id in prefix/suffix
|
|
193
192
|
else:
|
|
194
193
|
container_space = constraint.prefix
|
|
195
194
|
container_external_id = constraint.suffix
|
|
@@ -13,6 +13,7 @@ from ._connections import (
|
|
|
13
13
|
ReverseConnectionTargetMissing,
|
|
14
14
|
)
|
|
15
15
|
from ._consistency import ViewSpaceVersionInconsistentWithDataModel
|
|
16
|
+
from ._containers import ExternalContainerDoesNotExist
|
|
16
17
|
from ._limits import (
|
|
17
18
|
ContainerPropertyCountIsOutOfLimits,
|
|
18
19
|
ContainerPropertyListSizeIsOutOfLimits,
|
|
@@ -34,6 +35,7 @@ __all__ = [
|
|
|
34
35
|
"DataModelMissingName",
|
|
35
36
|
"DataModelViewCountIsOutOfLimits",
|
|
36
37
|
"DmsDataModelValidation",
|
|
38
|
+
"ExternalContainerDoesNotExist",
|
|
37
39
|
"ImplementedViewNotExisting",
|
|
38
40
|
"ReverseConnectionContainerMissing",
|
|
39
41
|
"ReverseConnectionContainerPropertyMissing",
|
|
@@ -275,23 +275,25 @@ class DataModelValidator(ABC):
|
|
|
275
275
|
return self.local_resources.containers_by_reference
|
|
276
276
|
|
|
277
277
|
merged_containers: dict[ContainerReference, ContainerRequest] = {}
|
|
278
|
-
# Merge local
|
|
279
|
-
for
|
|
280
|
-
cdf_container = self.cdf_resources.containers_by_reference.get(
|
|
281
|
-
local_container = self.local_resources.containers_by_reference.get(
|
|
278
|
+
# Merge local containers, combining properties if container exists in both
|
|
279
|
+
for container_ref in self.container_references:
|
|
280
|
+
cdf_container = self.cdf_resources.containers_by_reference.get(container_ref)
|
|
281
|
+
local_container = self.local_resources.containers_by_reference.get(container_ref)
|
|
282
282
|
|
|
283
283
|
if not cdf_container and not local_container:
|
|
284
|
-
raise RuntimeError(
|
|
284
|
+
raise RuntimeError(
|
|
285
|
+
f"Container {container_ref!s} not found in either local or CDF resources. This is a bug!"
|
|
286
|
+
)
|
|
285
287
|
|
|
286
|
-
merged_containers[
|
|
288
|
+
merged_containers[container_ref] = cast(ContainerRequest, (cdf_container or local_container)).model_copy(
|
|
287
289
|
deep=True
|
|
288
290
|
)
|
|
289
291
|
|
|
290
292
|
if local_container and local_container.properties:
|
|
291
|
-
if not merged_containers[
|
|
292
|
-
merged_containers[
|
|
293
|
+
if not merged_containers[container_ref].properties:
|
|
294
|
+
merged_containers[container_ref].properties = local_container.properties
|
|
293
295
|
else:
|
|
294
|
-
merged_containers[
|
|
296
|
+
merged_containers[container_ref].properties.update(local_container.properties)
|
|
295
297
|
|
|
296
298
|
return merged_containers
|
|
297
299
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Validators for checking containers in the data model."""
|
|
2
|
+
|
|
3
|
+
from cognite.neat._data_model.models.dms._view_property import ViewCorePropertyRequest
|
|
4
|
+
from cognite.neat._data_model.validation.dms._base import DataModelValidator
|
|
5
|
+
from cognite.neat._issues import ConsistencyError
|
|
6
|
+
|
|
7
|
+
BASE_CODE = "NEAT-DMS-CONTAINER"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ExternalContainerDoesNotExist(DataModelValidator):
|
|
11
|
+
"""
|
|
12
|
+
Validates that any container or container property referenced by a view property, when the
|
|
13
|
+
referenced container does not belong to the data model's space, exists in CDF.
|
|
14
|
+
|
|
15
|
+
## What it does
|
|
16
|
+
For each view property that maps to a container in a different space than the data model,
|
|
17
|
+
this validator checks that:
|
|
18
|
+
- the referenced external container exists in CDF, and
|
|
19
|
+
- that the referenced container property also exists in that external container.
|
|
20
|
+
|
|
21
|
+
## Why is this bad?
|
|
22
|
+
If a view property references a container or container property that does not exist in CDF,
|
|
23
|
+
the data model cannot be deployed. The affected view property will not function, and the
|
|
24
|
+
deployment of the entire data model will fail.
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
View `my_space:WindTurbine` has a property `location` that maps to container
|
|
28
|
+
`other_space:WindTurbineContainer`, where `other_space` differs from `my_space`. If that
|
|
29
|
+
container does not exist in CDF, the model cannot be deployed.
|
|
30
|
+
|
|
31
|
+
Similarly, if a view property references `other_space:WindTurbineContainer` and its property
|
|
32
|
+
`gpsCoordinates`, and `gpsCoordinates` does not exist in that container in CDF, deployment
|
|
33
|
+
will also fail.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
code = f"{BASE_CODE}-001"
|
|
37
|
+
|
|
38
|
+
def run(self) -> list[ConsistencyError]:
|
|
39
|
+
errors: list[ConsistencyError] = []
|
|
40
|
+
|
|
41
|
+
for view_ref, view in self.merged_views.items():
|
|
42
|
+
for property_ref, property_ in view.properties.items():
|
|
43
|
+
if not isinstance(property_, ViewCorePropertyRequest):
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
if property_.container.space == self.local_resources.data_model_reference.space:
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
# Check existence of container in CDF
|
|
50
|
+
elif property_.container not in self.cdf_resources.containers_by_reference:
|
|
51
|
+
errors.append(
|
|
52
|
+
ConsistencyError(
|
|
53
|
+
message=(
|
|
54
|
+
f"View {view_ref!s} property {property_ref!s} maps to "
|
|
55
|
+
f"external container {property_.container!s} which does not exist in CDF."
|
|
56
|
+
),
|
|
57
|
+
fix="Define necessary container in CDF",
|
|
58
|
+
code=self.code,
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Check existence of container property in CDF
|
|
63
|
+
elif (
|
|
64
|
+
property_.container_property_identifier
|
|
65
|
+
not in self.cdf_resources.containers_by_reference[property_.container].properties
|
|
66
|
+
):
|
|
67
|
+
errors.append(
|
|
68
|
+
ConsistencyError(
|
|
69
|
+
message=(
|
|
70
|
+
f"View {view_ref!s} property {property_ref!s} maps to "
|
|
71
|
+
f"external container {property_.container!s} which does not have "
|
|
72
|
+
f"property '{property_.container_property_identifier}' in CDF."
|
|
73
|
+
),
|
|
74
|
+
fix="Define necessary container property in CDF",
|
|
75
|
+
code=self.code,
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return errors
|
|
@@ -35,6 +35,7 @@ from ._connections import (
|
|
|
35
35
|
ReverseConnectionTargetMissing,
|
|
36
36
|
)
|
|
37
37
|
from ._consistency import ViewSpaceVersionInconsistentWithDataModel
|
|
38
|
+
from ._containers import ExternalContainerDoesNotExist
|
|
38
39
|
from ._views import ImplementedViewNotExisting, ViewToContainerMappingNotPossible
|
|
39
40
|
|
|
40
41
|
|
|
@@ -113,6 +114,8 @@ class DmsDataModelValidation(OnSuccessIssuesChecker):
|
|
|
113
114
|
# Views
|
|
114
115
|
ViewToContainerMappingNotPossible(local_resources, cdf_resources, self._modus_operandi),
|
|
115
116
|
ImplementedViewNotExisting(local_resources, cdf_resources, self._modus_operandi),
|
|
117
|
+
# Containers
|
|
118
|
+
ExternalContainerDoesNotExist(local_resources, cdf_resources, self._modus_operandi),
|
|
116
119
|
# Consistency
|
|
117
120
|
ViewSpaceVersionInconsistentWithDataModel(local_resources, cdf_resources, self._modus_operandi),
|
|
118
121
|
# Connections
|
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.127.
|
|
1
|
+
__version__ = "0.127.17"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cognite-neat
|
|
3
|
-
Version: 0.127.
|
|
3
|
+
Version: 0.127.17
|
|
4
4
|
Summary: Knowledge graph transformation
|
|
5
5
|
Project-URL: Documentation, https://cognite-neat.readthedocs-hosted.com/
|
|
6
6
|
Project-URL: Homepage, https://cognite-neat.readthedocs-hosted.com/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
cognite/neat/__init__.py,sha256=Lo4DbjDOwnhCYUoAgPp5RG1fDdF7OlnomalTe7n1ydw,211
|
|
2
2
|
cognite/neat/_exceptions.py,sha256=ox-5hXpee4UJlPE7HpuEHV2C96aLbLKo-BhPDoOAzhA,1650
|
|
3
3
|
cognite/neat/_issues.py,sha256=wH1mnkrpBsHUkQMGUHFLUIQWQlfJ_qMfdF7q0d9wNhY,1871
|
|
4
|
-
cognite/neat/_version.py,sha256=
|
|
4
|
+
cognite/neat/_version.py,sha256=LjfnB6yr-MAZtYMhY0G634kZSP7d49DCRuq6vzSYrzM,47
|
|
5
5
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
cognite/neat/v1.py,sha256=owqW5Mml2DSZx1AvPvwNRTBngfhBNrQ6EH-7CKL7Jp0,61
|
|
7
7
|
cognite/neat/_client/__init__.py,sha256=75Bh7eGhaN4sOt3ZcRzHl7pXaheu1z27kmTHeaI05vo,114
|
|
@@ -38,7 +38,7 @@ cognite/neat/_data_model/importers/__init__.py,sha256=dHnKnC_AXk42z6wzEHK15dxIOh
|
|
|
38
38
|
cognite/neat/_data_model/importers/_api_importer.py,sha256=H8Ow3Tt7utuAuBhC6s7yWvhGqunHAtE0r0XRsVAr6IE,7280
|
|
39
39
|
cognite/neat/_data_model/importers/_base.py,sha256=NRB0FcEBj4GaethU68nRffBfTedBBA866A3zfJNfmiQ,433
|
|
40
40
|
cognite/neat/_data_model/importers/_table_importer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
|
-
cognite/neat/_data_model/importers/_table_importer/data_classes.py,sha256=
|
|
41
|
+
cognite/neat/_data_model/importers/_table_importer/data_classes.py,sha256=5gFeAjAYFlzOBb9cfKZWeih5psKynpJwPMNel7h6cO8,9496
|
|
42
42
|
cognite/neat/_data_model/importers/_table_importer/importer.py,sha256=lQ4_Gpv0haEwQEDYZJaxtR9dL6Y0ys9jbjFfWxH6s2o,8870
|
|
43
43
|
cognite/neat/_data_model/importers/_table_importer/reader.py,sha256=v7_PWuOtUQwRTTkZRw4z37G2IF9BtrMozmnnaM9avKE,40759
|
|
44
44
|
cognite/neat/_data_model/importers/_table_importer/source.py,sha256=h7u5ur5oetmvBs3wgj7Ody5uPF21QwxeAceoIhJ5qzo,3300
|
|
@@ -72,13 +72,14 @@ cognite/neat/_data_model/models/entities/_data_types.py,sha256=DfdEWGek7gODro-_0
|
|
|
72
72
|
cognite/neat/_data_model/models/entities/_identifiers.py,sha256=uBiK4ot3V0b_LGXuJ7bfha6AEcFI3p2letr1z2iSvig,1923
|
|
73
73
|
cognite/neat/_data_model/models/entities/_parser.py,sha256=zef_pSDZYMZrJl4IKreFDR577KutfhtN1xpH3Ayjt2o,7669
|
|
74
74
|
cognite/neat/_data_model/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
cognite/neat/_data_model/validation/dms/__init__.py,sha256=
|
|
75
|
+
cognite/neat/_data_model/validation/dms/__init__.py,sha256=EOGdTYOgDkFBmMe6haQ24fuC3fhEJwbfVD7qtJ_Lwac,2188
|
|
76
76
|
cognite/neat/_data_model/validation/dms/_ai_readiness.py,sha256=SI46roGc2pbZQwY-6tuSWyS7uMbg2mIzXcVA3NPRCk4,6742
|
|
77
|
-
cognite/neat/_data_model/validation/dms/_base.py,sha256=
|
|
77
|
+
cognite/neat/_data_model/validation/dms/_base.py,sha256=y95k6HWGxX_EnnyuV2ooftgiyC-fwJaaHW28oEf9oBs,13113
|
|
78
78
|
cognite/neat/_data_model/validation/dms/_connections.py,sha256=goIcsGV4yYb-d9ltXg4eM5qxt8iErIIxtkiKJXZUYyM,26937
|
|
79
79
|
cognite/neat/_data_model/validation/dms/_consistency.py,sha256=K0mfAwwpW6zQXGDEldrA7Lgqk-giV_Y-gUKyb8Dw47k,2445
|
|
80
|
+
cognite/neat/_data_model/validation/dms/_containers.py,sha256=62-AfweC9ZaHJkryeQ3N-3FiicnyBMnz3PcVsIXIUkU,3601
|
|
80
81
|
cognite/neat/_data_model/validation/dms/_limits.py,sha256=LVxF1qmeEdUVVAPmywCgxWJ9BR7Ai6nI4X1ylJ7pv8I,15982
|
|
81
|
-
cognite/neat/_data_model/validation/dms/_orchestrator.py,sha256=
|
|
82
|
+
cognite/neat/_data_model/validation/dms/_orchestrator.py,sha256=sJpJJR6JfGBGC0ADQl23-KeemHziGTkTapVemds4gnc,10048
|
|
82
83
|
cognite/neat/_data_model/validation/dms/_views.py,sha256=3bHEEbFKTR_QH_tiJYHppQsZ9ruApv-kdyfehEjIlCU,4198
|
|
83
84
|
cognite/neat/_session/__init__.py,sha256=owqW5Mml2DSZx1AvPvwNRTBngfhBNrQ6EH-7CKL7Jp0,61
|
|
84
85
|
cognite/neat/_session/_issues.py,sha256=M_tYwYiHvvYToaVHCqeSIn4oAO0RZuVtxzd5W52Tn8s,2558
|
|
@@ -310,7 +311,7 @@ cognite/neat/v0/session/engine/__init__.py,sha256=D3MxUorEs6-NtgoICqtZ8PISQrjrr4
|
|
|
310
311
|
cognite/neat/v0/session/engine/_import.py,sha256=1QxA2_EK613lXYAHKQbZyw2yjo5P9XuiX4Z6_6-WMNQ,169
|
|
311
312
|
cognite/neat/v0/session/engine/_interface.py,sha256=3W-cYr493c_mW3P5O6MKN1xEQg3cA7NHR_ev3zdF9Vk,533
|
|
312
313
|
cognite/neat/v0/session/engine/_load.py,sha256=u0x7vuQCRoNcPt25KJBJRn8sJabonYK4vtSZpiTdP4k,5201
|
|
313
|
-
cognite_neat-0.127.
|
|
314
|
-
cognite_neat-0.127.
|
|
315
|
-
cognite_neat-0.127.
|
|
316
|
-
cognite_neat-0.127.
|
|
314
|
+
cognite_neat-0.127.17.dist-info/METADATA,sha256=xB9AlUyFe41UJQFX_lcgH8MKm0mJ4XCKzMOMqUOABAg,9150
|
|
315
|
+
cognite_neat-0.127.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
316
|
+
cognite_neat-0.127.17.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
|
|
317
|
+
cognite_neat-0.127.17.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|