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.
@@ -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 in ["requires", "uniqueness"]:
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
- # Handle missing prefix - default to "requires"
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 views, combining properties if view exists in both
279
- for view_ref in self.container_references:
280
- cdf_container = self.cdf_resources.containers_by_reference.get(view_ref)
281
- local_container = self.local_resources.containers_by_reference.get(view_ref)
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(f"Container {view_ref!s} not found in either local or CDF resources. This is a bug!")
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[view_ref] = cast(ContainerRequest, (cdf_container or local_container)).model_copy(
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[view_ref].properties:
292
- merged_containers[view_ref].properties = local_container.properties
293
+ if not merged_containers[container_ref].properties:
294
+ merged_containers[container_ref].properties = local_container.properties
293
295
  else:
294
- merged_containers[view_ref].properties.update(local_container.properties)
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.15"
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.15
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=TkopLCNlwlXxpTUuKeSgUFDJgQhM3EsmaUXt1_UL7Ek,47
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=z5Gx6Ii4xl9tGp1evnB4pn9i3zPMmWPUifFQGR4StDg,9541
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=6bCjHBd0_E21A5W-VuHhLQ_u-xxvkcpYTPtzuA9pJd0,2096
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=9sKDuofVPODWLyXuj20cOK8vQb8yexcN80W2Q5s0xdM,13025
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=fjh-9SIJlMNbIGip2p7TqrlVS7Fmu_rjmdpRujJ28yM,9871
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.15.dist-info/METADATA,sha256=ms4xb3WULkx1g1nDQ22rSTaUhhB3DXWMtXd6BFLxo08,9150
314
- cognite_neat-0.127.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
315
- cognite_neat-0.127.15.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
316
- cognite_neat-0.127.15.dist-info/RECORD,,
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,,