cognite-neat 0.127.29__py3-none-any.whl → 0.127.31__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.
@@ -323,7 +323,7 @@ class DataTypeDiffer(ItemDiffer[PropertyTypeDefinition]):
323
323
  if current.collation != new.collation:
324
324
  changes.append(
325
325
  ChangedField(
326
- item_severity=SeverityType.WARNING,
326
+ item_severity=SeverityType.BREAKING,
327
327
  field_path=self._get_path("collation"),
328
328
  current_value=current.collation,
329
329
  new_value=new.collation,
@@ -220,7 +220,7 @@ class ViewPropertyDiffer(ObjectDiffer[ViewPropertyDefinition]):
220
220
  changes.append(
221
221
  ChangedField(
222
222
  field_path=self._get_path(f"{identifier}.edgeSource"),
223
- item_severity=SeverityType.WARNING,
223
+ item_severity=SeverityType.BREAKING,
224
224
  new_value=new.edge_source,
225
225
  current_value=current.edge_source,
226
226
  )
@@ -229,7 +229,7 @@ class ViewPropertyDiffer(ObjectDiffer[ViewPropertyDefinition]):
229
229
  changes.append(
230
230
  ChangedField(
231
231
  field_path=self._get_path(f"{identifier}.direction"),
232
- item_severity=SeverityType.WARNING,
232
+ item_severity=SeverityType.BREAKING,
233
233
  new_value=new.direction,
234
234
  current_value=current.direction,
235
235
  )
@@ -1,6 +1,8 @@
1
1
  from ._ai_readiness import (
2
2
  DataModelMissingDescription,
3
3
  DataModelMissingName,
4
+ EnumerationMissingDescription,
5
+ EnumerationMissingName,
4
6
  ViewMissingDescription,
5
7
  ViewMissingName,
6
8
  ViewPropertyMissingDescription,
@@ -46,6 +48,8 @@ __all__ = [
46
48
  "DataModelMissingName",
47
49
  "DataModelViewCountIsOutOfLimits",
48
50
  "DmsDataModelValidation",
51
+ "EnumerationMissingDescription",
52
+ "EnumerationMissingName",
49
53
  "ExternalContainerDoesNotExist",
50
54
  "ExternalContainerPropertyDoesNotExist",
51
55
  "ImplementedViewNotExisting",
@@ -1,5 +1,6 @@
1
1
  """Validators for checking if data model is AI-ready."""
2
2
 
3
+ from cognite.neat._data_model.models.dms._data_types import EnumProperty
3
4
  from cognite.neat._data_model.validation.dms._base import DataModelValidator
4
5
  from cognite.neat._issues import Recommendation
5
6
 
@@ -256,3 +257,108 @@ class ViewPropertyMissingDescription(DataModelValidator):
256
257
  )
257
258
 
258
259
  return recommendations
260
+
261
+
262
+ class EnumerationMissingName(DataModelValidator):
263
+ """Validates that an enumeration has a human-readable name.
264
+
265
+ ## What it does
266
+ Validates that each enumeration value in the data model has a human-readable name.
267
+
268
+ ## Why is this bad?
269
+ A missing name makes it harder for users (humans or machines) to understand the purpose of the enumeration value.
270
+ This is important as enumeration values are often technical codes or abbreviations, and a clear name improves
271
+ usability, maintainability, searchability, and AI-readiness.
272
+
273
+ ## Example
274
+ An enumeration value with id "NOM" in a wind turbine operational mode property has no name. Users may find it
275
+ difficult to understand what this value represents. Adding name "Normal Operation" would increase clarity
276
+ and usability.
277
+ """
278
+
279
+ code = f"{BASE_CODE}-007"
280
+ issue_type = Recommendation
281
+
282
+ def run(self) -> list[Recommendation]:
283
+ recommendations: list[Recommendation] = []
284
+
285
+ for container_ref, container in self.local_resources.containers_by_reference.items():
286
+ if container_ref.space != self.local_resources.data_model_reference.space:
287
+ continue
288
+
289
+ for prop_ref, definition in container.properties.items():
290
+ if not isinstance(definition.type, EnumProperty):
291
+ continue
292
+
293
+ for value, enum_def in definition.type.values.items():
294
+ if not enum_def.name:
295
+ recommendations.append(
296
+ Recommendation(
297
+ message=(
298
+ f"Enumeration value {value!r} in property {prop_ref!s} of container "
299
+ f"{container_ref!s} is missing a human-readable name."
300
+ ),
301
+ fix="Add a clear and concise name to the enumeration value.",
302
+ code=self.code,
303
+ )
304
+ )
305
+
306
+ return recommendations
307
+
308
+
309
+ class EnumerationMissingDescription(DataModelValidator):
310
+ """Validates that an enumeration value has a human-readable description.
311
+
312
+ ## What it does
313
+ Validates that each enumeration value in the data model has a human-readable description.
314
+
315
+ ## Why is this bad?
316
+ A missing description makes it harder for users (humans or machines) to understand the meaning and context
317
+ of the enumeration value. The description can provide important information about when and how the value
318
+ should be used, especially when enumeration values are technical codes or abbreviations.
319
+
320
+ ## Example
321
+ An enumeration value "NOM" in a wind turbine operational mode property has no description. Users may find it
322
+ difficult to understand what this value represents without additional context. Even with a name like
323
+ "Normal Operation", the description is valuable as it can clarify specifics:
324
+
325
+ Option 1 — Basic definition
326
+ The turbine is operating normally and generating power according to its power curve.
327
+
328
+ Option 2 — Detailed operational context
329
+ The turbine is in normal operation mode, actively generating power with all systems functioning within
330
+ specified parameters and connected to the grid.
331
+
332
+ Option 3 — Contrasting with other modes
333
+ Standard operating mode where the turbine follows the power curve and responds to grid commands,
334
+ as opposed to maintenance mode or fault conditions.
335
+ """
336
+
337
+ code = f"{BASE_CODE}-008"
338
+ issue_type = Recommendation
339
+
340
+ def run(self) -> list[Recommendation]:
341
+ recommendations: list[Recommendation] = []
342
+
343
+ for container_ref, container in self.local_resources.containers_by_reference.items():
344
+ if container_ref.space != self.local_resources.data_model_reference.space:
345
+ continue
346
+
347
+ for prop_ref, definition in container.properties.items():
348
+ if not isinstance(definition.type, EnumProperty):
349
+ continue
350
+
351
+ for value, enum_def in definition.type.values.items():
352
+ if not enum_def.description:
353
+ recommendations.append(
354
+ Recommendation(
355
+ message=(
356
+ f"Enumeration value {value!r} in property {prop_ref!s} of container "
357
+ f"{container_ref!s} is missing a human-readable description."
358
+ ),
359
+ fix="Add a clear and concise description to the enumeration value.",
360
+ code=self.code,
361
+ )
362
+ )
363
+
364
+ return recommendations
@@ -23,6 +23,8 @@ from cognite.neat._utils.useful_types import ModusOperandi
23
23
  from ._ai_readiness import (
24
24
  DataModelMissingDescription,
25
25
  DataModelMissingName,
26
+ EnumerationMissingDescription,
27
+ EnumerationMissingName,
26
28
  ViewMissingDescription,
27
29
  ViewMissingName,
28
30
  ViewPropertyMissingDescription,
@@ -152,6 +154,8 @@ class DmsDataModelValidation(OnSuccessIssuesChecker):
152
154
  ViewMissingDescription(local_resources, cdf_resources, self._modus_operandi),
153
155
  ViewPropertyMissingName(local_resources, cdf_resources, self._modus_operandi),
154
156
  ViewPropertyMissingDescription(local_resources, cdf_resources, self._modus_operandi),
157
+ EnumerationMissingName(local_resources, cdf_resources, self._modus_operandi),
158
+ EnumerationMissingDescription(local_resources, cdf_resources, self._modus_operandi),
155
159
  ]
156
160
 
157
161
  # Run validators
cognite/neat/_version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.127.29"
1
+ __version__ = "0.127.31"
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.29
3
+ Version: 0.127.31
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/
@@ -2,7 +2,7 @@ cognite/neat/__init__.py,sha256=Lo4DbjDOwnhCYUoAgPp5RG1fDdF7OlnomalTe7n1ydw,211
2
2
  cognite/neat/_config.py,sha256=W42Lj5PNR9X1is9vIPHLHvkl_rpU5PCrDuQI4zSNTJQ,6359
3
3
  cognite/neat/_exceptions.py,sha256=ox-5hXpee4UJlPE7HpuEHV2C96aLbLKo-BhPDoOAzhA,1650
4
4
  cognite/neat/_issues.py,sha256=wH1mnkrpBsHUkQMGUHFLUIQWQlfJ_qMfdF7q0d9wNhY,1871
5
- cognite/neat/_version.py,sha256=HnkgU0oEwuWFxHjFpJFKDNKAV0Zn342c-qMWtztHfKE,47
5
+ cognite/neat/_version.py,sha256=rvkcySAmEggTDqAglgVEXmb2SsDZO3WaXGVcdNwHKNU,47
6
6
  cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  cognite/neat/v1.py,sha256=owqW5Mml2DSZx1AvPvwNRTBngfhBNrQ6EH-7CKL7Jp0,61
8
8
  cognite/neat/_client/__init__.py,sha256=75Bh7eGhaN4sOt3ZcRzHl7pXaheu1z27kmTHeaI05vo,114
@@ -22,10 +22,10 @@ cognite/neat/_data_model/_identifiers.py,sha256=a0LcQ_h0NffxSKTCrzCDpYkrlaUTk-D_
22
22
  cognite/neat/_data_model/_shared.py,sha256=H0gFqa8tKFNWuvdat5jL6OwySjCw3aQkLPY3wtb9Wrw,1302
23
23
  cognite/neat/_data_model/deployer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  cognite/neat/_data_model/deployer/_differ.py,sha256=1ircRBCoaFooSzMTmTZBTORHeAhDa8YtDEnVwBo6TUI,4742
25
- cognite/neat/_data_model/deployer/_differ_container.py,sha256=7iKQVxCtwjOMlydzX8U2Vs09pTiF-SflQoE_FsMCWN4,14664
25
+ cognite/neat/_data_model/deployer/_differ_container.py,sha256=mcy7PhUOfnvAxnZWNoeNRmiXa8ovIn0W6YoqfzVYyiQ,14665
26
26
  cognite/neat/_data_model/deployer/_differ_data_model.py,sha256=iA7Xp-7NRvzZJXLLpJaLebkKKpv_VCBKPX6f-RU9wBk,1864
27
27
  cognite/neat/_data_model/deployer/_differ_space.py,sha256=J_AaqiseLpwQsOkKc7gmho4U2oSWAGVeEdQNepZiWw0,343
28
- cognite/neat/_data_model/deployer/_differ_view.py,sha256=Gho1XAR7S5G41JPj_4E2rkYzuOQYid3AlsyIwvXAzlM,11410
28
+ cognite/neat/_data_model/deployer/_differ_view.py,sha256=g1xHwsoxFUaTOTtQa19nntKF3rxFzc2FxpKKFAUN_NE,11412
29
29
  cognite/neat/_data_model/deployer/data_classes.py,sha256=ZNSBFNhq46FfERKwC3Zu2TU1RFDdFsnaUzTtztgWdDY,23050
30
30
  cognite/neat/_data_model/deployer/deployer.py,sha256=_d3A2JnrVD4sjBNJIkXbwtTQOW5fc7QWrQBdwBfN8fs,18277
31
31
  cognite/neat/_data_model/exporters/__init__.py,sha256=AskjmB_0Vqib4kN84bWt8-M8nO42QypFf-l-E8oA5W8,482
@@ -74,14 +74,14 @@ cognite/neat/_data_model/models/entities/_data_types.py,sha256=DfdEWGek7gODro-_0
74
74
  cognite/neat/_data_model/models/entities/_identifiers.py,sha256=uBiK4ot3V0b_LGXuJ7bfha6AEcFI3p2letr1z2iSvig,1923
75
75
  cognite/neat/_data_model/models/entities/_parser.py,sha256=zef_pSDZYMZrJl4IKreFDR577KutfhtN1xpH3Ayjt2o,7669
76
76
  cognite/neat/_data_model/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
- cognite/neat/_data_model/validation/dms/__init__.py,sha256=Ps26r8bY4sLPsceaS6CpgS-s6JxN_zKbiteF5RrQYYw,2512
78
- cognite/neat/_data_model/validation/dms/_ai_readiness.py,sha256=yKT9KHS4iD7ijKBjjAGbREKWDGunBuDTl9FCX0RiW2Q,10717
77
+ cognite/neat/_data_model/validation/dms/__init__.py,sha256=kKD18-Bg_G-w11Cs7Wv_TKV0C_q62Pm2RKLpOz27ar4,2642
78
+ cognite/neat/_data_model/validation/dms/_ai_readiness.py,sha256=hFrnRzBBf143ejLHRk3BpylzrVpxUX537BouOlv4PFE,15552
79
79
  cognite/neat/_data_model/validation/dms/_base.py,sha256=3Lqs8pzMQZznxhUr8esEe9H7F2wM3EKEl2H64GLS5OA,13344
80
80
  cognite/neat/_data_model/validation/dms/_connections.py,sha256=6ea8WZNqYT9SPluwXvg0mgDJpzZMqpPC5xonbdLrT4E,27305
81
81
  cognite/neat/_data_model/validation/dms/_consistency.py,sha256=uJ6coAVupD3WfeeXxoCIebM8WSnR78GXBXIBnN59aao,2477
82
82
  cognite/neat/_data_model/validation/dms/_containers.py,sha256=UuvzrBBw45F5f9uzCh97lW4t7m7XIIT1I9FnzzYUYv4,7533
83
83
  cognite/neat/_data_model/validation/dms/_limits.py,sha256=UDJ3oY2Xp96Zw2QpsGM4MQ6gZCrDuoKhhuEY2uQJLP4,16186
84
- cognite/neat/_data_model/validation/dms/_orchestrator.py,sha256=0KpXMWlofpELCE3QXQh6SDyP3IoATPrR1412HJzAN6w,10811
84
+ cognite/neat/_data_model/validation/dms/_orchestrator.py,sha256=XrozA27fbzWCuCQKLx70jMaeABedKHTHs8vg-hqx3_w,11061
85
85
  cognite/neat/_data_model/validation/dms/_views.py,sha256=M4egIa7UAMGtZlqzIxx6ZzL4e_qo8GbDGh7vs9wywD8,4266
86
86
  cognite/neat/_session/__init__.py,sha256=owqW5Mml2DSZx1AvPvwNRTBngfhBNrQ6EH-7CKL7Jp0,61
87
87
  cognite/neat/_session/_issues.py,sha256=E8UQeSJURg2dm4MF1pfD9dp-heSRT7pgQZgKlD1-FGs,2723
@@ -313,7 +313,7 @@ cognite/neat/v0/session/engine/__init__.py,sha256=D3MxUorEs6-NtgoICqtZ8PISQrjrr4
313
313
  cognite/neat/v0/session/engine/_import.py,sha256=1QxA2_EK613lXYAHKQbZyw2yjo5P9XuiX4Z6_6-WMNQ,169
314
314
  cognite/neat/v0/session/engine/_interface.py,sha256=3W-cYr493c_mW3P5O6MKN1xEQg3cA7NHR_ev3zdF9Vk,533
315
315
  cognite/neat/v0/session/engine/_load.py,sha256=u0x7vuQCRoNcPt25KJBJRn8sJabonYK4vtSZpiTdP4k,5201
316
- cognite_neat-0.127.29.dist-info/METADATA,sha256=BODhl8sBHt2YtVcTIr7NK7Pcew1A68onQGB63HaKYDo,9150
317
- cognite_neat-0.127.29.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
318
- cognite_neat-0.127.29.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
319
- cognite_neat-0.127.29.dist-info/RECORD,,
316
+ cognite_neat-0.127.31.dist-info/METADATA,sha256=M2giADSPBb8V9B1ejRjCNgGcYL8hZCdPoyg3Ddwrt9M,9150
317
+ cognite_neat-0.127.31.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
318
+ cognite_neat-0.127.31.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
319
+ cognite_neat-0.127.31.dist-info/RECORD,,