cognite-neat 0.75.7__py3-none-any.whl → 0.75.9__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.

Potentially problematic release.


This version of cognite-neat might be problematic. Click here for more details.

Files changed (103) hide show
  1. cognite/neat/_version.py +1 -1
  2. cognite/neat/app/api/configuration.py +4 -9
  3. cognite/neat/app/api/routers/configuration.py +2 -1
  4. cognite/neat/app/api/routers/crud.py +5 -5
  5. cognite/neat/app/api/routers/data_exploration.py +3 -1
  6. cognite/neat/app/api/routers/rules.py +3 -3
  7. cognite/neat/app/api/routers/workflows.py +3 -3
  8. cognite/neat/app/ui/neat-app/build/asset-manifest.json +3 -3
  9. cognite/neat/app/ui/neat-app/build/index.html +1 -1
  10. cognite/neat/app/ui/neat-app/build/static/js/{main.4345d42f.js → main.ec7f72e2.js} +3 -3
  11. cognite/neat/app/ui/neat-app/build/static/js/{main.4345d42f.js.map → main.ec7f72e2.js.map} +1 -1
  12. cognite/neat/config.py +147 -12
  13. cognite/neat/constants.py +1 -0
  14. cognite/neat/graph/exceptions.py +1 -2
  15. cognite/neat/graph/extractors/_mock_graph_generator.py +6 -5
  16. cognite/neat/legacy/graph/exceptions.py +1 -2
  17. cognite/neat/legacy/graph/extractors/_mock_graph_generator.py +1 -2
  18. cognite/neat/legacy/graph/loaders/_asset_loader.py +8 -13
  19. cognite/neat/legacy/graph/loaders/_base.py +2 -4
  20. cognite/neat/legacy/graph/loaders/_exceptions.py +1 -3
  21. cognite/neat/legacy/graph/loaders/core/rdf_to_assets.py +4 -8
  22. cognite/neat/legacy/graph/loaders/core/rdf_to_relationships.py +2 -4
  23. cognite/neat/legacy/graph/loaders/rdf_to_dms.py +2 -4
  24. cognite/neat/legacy/graph/loaders/validator.py +1 -1
  25. cognite/neat/legacy/graph/transformations/transformer.py +1 -2
  26. cognite/neat/legacy/rules/exporters/_rules2dms.py +1 -2
  27. cognite/neat/legacy/rules/exporters/_validation.py +4 -8
  28. cognite/neat/legacy/rules/importers/_base.py +0 -4
  29. cognite/neat/legacy/rules/importers/_dms2rules.py +0 -2
  30. cognite/neat/legacy/rules/models/rdfpath.py +1 -2
  31. cognite/neat/legacy/workflows/examples/Export_DMS/workflow.yaml +89 -0
  32. cognite/neat/legacy/workflows/examples/Export_Rules_to_Ontology/workflow.yaml +152 -0
  33. cognite/neat/legacy/workflows/examples/Extract_DEXPI_Graph_and_Export_Rules/workflow.yaml +139 -0
  34. cognite/neat/legacy/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +270 -0
  35. cognite/neat/legacy/workflows/examples/Import_DMS/workflow.yaml +65 -0
  36. cognite/neat/legacy/workflows/examples/Ontology_to_Data_Model/workflow.yaml +116 -0
  37. cognite/neat/legacy/workflows/examples/Validate_Rules/workflow.yaml +67 -0
  38. cognite/neat/legacy/workflows/examples/Validate_Solution_Model/workflow.yaml +64 -0
  39. cognite/neat/legacy/workflows/examples/Visualize_Data_Model_Using_Mock_Graph/workflow.yaml +95 -0
  40. cognite/neat/legacy/workflows/examples/Visualize_Semantic_Data_Model/workflow.yaml +111 -0
  41. cognite/neat/rules/analysis/_base.py +1 -1
  42. cognite/neat/rules/analysis/_information_rules.py +4 -4
  43. cognite/neat/rules/exporters/_rules2excel.py +2 -2
  44. cognite/neat/rules/exporters/_rules2ontology.py +20 -17
  45. cognite/neat/rules/exporters/_validation.py +8 -10
  46. cognite/neat/rules/importers/_base.py +2 -4
  47. cognite/neat/rules/importers/_dms2rules.py +16 -19
  48. cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +21 -19
  49. cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +2 -4
  50. cognite/neat/rules/importers/_dtdl2rules/spec.py +3 -5
  51. cognite/neat/rules/importers/_owl2rules/_owl2rules.py +4 -6
  52. cognite/neat/rules/importers/_spreadsheet2rules.py +10 -9
  53. cognite/neat/rules/importers/_yaml2rules.py +10 -6
  54. cognite/neat/rules/issues/dms.py +3 -5
  55. cognite/neat/rules/issues/formatters.py +3 -1
  56. cognite/neat/rules/models/data_types.py +54 -31
  57. cognite/neat/rules/models/entities.py +184 -42
  58. cognite/neat/rules/models/rdfpath.py +112 -13
  59. cognite/neat/rules/models/rules/_base.py +2 -2
  60. cognite/neat/rules/models/rules/_dms_architect_rules.py +119 -189
  61. cognite/neat/rules/models/rules/_dms_rules_write.py +344 -0
  62. cognite/neat/rules/models/rules/_dms_schema.py +3 -3
  63. cognite/neat/rules/models/rules/_domain_rules.py +6 -3
  64. cognite/neat/rules/models/rules/_information_rules.py +68 -61
  65. cognite/neat/rules/models/rules/_types/__init__.py +0 -47
  66. cognite/neat/rules/models/rules/_types/_base.py +1 -309
  67. cognite/neat/rules/models/rules/_types/_field.py +0 -225
  68. cognite/neat/utils/cdf_loaders/_data_modeling.py +3 -1
  69. cognite/neat/utils/cdf_loaders/_ingestion.py +2 -4
  70. cognite/neat/utils/spreadsheet.py +2 -4
  71. cognite/neat/utils/utils.py +2 -4
  72. cognite/neat/workflows/base.py +5 -5
  73. cognite/neat/workflows/manager.py +32 -22
  74. cognite/neat/workflows/model.py +3 -3
  75. cognite/neat/workflows/steps/lib/__init__.py +0 -7
  76. cognite/neat/workflows/steps/lib/current/__init__.py +6 -0
  77. cognite/neat/workflows/steps/lib/{rules_exporter.py → current/rules_exporter.py} +8 -8
  78. cognite/neat/workflows/steps/lib/{rules_importer.py → current/rules_importer.py} +7 -7
  79. cognite/neat/workflows/steps/lib/io/__init__.py +1 -0
  80. cognite/neat/workflows/steps/lib/{v1 → legacy}/graph_contextualization.py +2 -2
  81. cognite/neat/workflows/steps/lib/{v1 → legacy}/graph_extractor.py +9 -9
  82. cognite/neat/workflows/steps/lib/{v1 → legacy}/graph_loader.py +9 -9
  83. cognite/neat/workflows/steps/lib/{v1 → legacy}/graph_store.py +4 -4
  84. cognite/neat/workflows/steps/lib/{v1 → legacy}/graph_transformer.py +2 -2
  85. cognite/neat/workflows/steps/lib/{v1 → legacy}/rules_exporter.py +15 -17
  86. cognite/neat/workflows/steps/lib/{v1 → legacy}/rules_importer.py +7 -7
  87. cognite/neat/workflows/steps/step_model.py +5 -9
  88. cognite/neat/workflows/steps_registry.py +20 -11
  89. {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.9.dist-info}/METADATA +1 -1
  90. {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.9.dist-info}/RECORD +100 -90
  91. cognite/neat/app/api/data_classes/configuration.py +0 -121
  92. cognite/neat/rules/models/_entity.py +0 -142
  93. cognite/neat/rules/models/rules/_types/_value.py +0 -159
  94. /cognite/neat/app/ui/neat-app/build/static/js/{main.4345d42f.js.LICENSE.txt → main.ec7f72e2.js.LICENSE.txt} +0 -0
  95. /cognite/neat/workflows/steps/lib/{graph_extractor.py → current/graph_extractor.py} +0 -0
  96. /cognite/neat/workflows/steps/lib/{graph_loader.py → current/graph_loader.py} +0 -0
  97. /cognite/neat/workflows/steps/lib/{graph_store.py → current/graph_store.py} +0 -0
  98. /cognite/neat/workflows/steps/lib/{rules_validator.py → current/rules_validator.py} +0 -0
  99. /cognite/neat/workflows/steps/lib/{io_steps.py → io/io_steps.py} +0 -0
  100. /cognite/neat/workflows/steps/lib/{v1 → legacy}/__init__.py +0 -0
  101. {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.9.dist-info}/LICENSE +0 -0
  102. {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.9.dist-info}/WHEEL +0 -0
  103. {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.9.dist-info}/entry_points.txt +0 -0
@@ -13,6 +13,25 @@ from rdflib import Namespace
13
13
  import cognite.neat.rules.issues.spreadsheet
14
14
  from cognite.neat.constants import PREFIXES
15
15
  from cognite.neat.rules import exceptions
16
+ from cognite.neat.rules.models.data_types import DataType
17
+ from cognite.neat.rules.models.entities import (
18
+ ClassEntity,
19
+ ContainerEntity,
20
+ DMSUnknownEntity,
21
+ Entity,
22
+ EntityTypes,
23
+ ParentClassEntity,
24
+ ParentEntityList,
25
+ ReferenceEntity,
26
+ Undefined,
27
+ Unknown,
28
+ UnknownEntity,
29
+ URLEntity,
30
+ ViewEntity,
31
+ ViewPropertyEntity,
32
+ _UndefinedType,
33
+ _UnknownType,
34
+ )
16
35
  from cognite.neat.rules.models.rdfpath import (
17
36
  AllReferences,
18
37
  Hop,
@@ -37,26 +56,12 @@ from ._base import (
37
56
  )
38
57
  from ._domain_rules import DomainRules
39
58
  from ._types import (
40
- ClassEntity,
41
- ContainerEntity,
42
- Entity,
43
- EntityTypes,
44
59
  NamespaceType,
45
- ParentClassEntity,
46
- ParentClassType,
47
60
  PrefixType,
48
61
  PropertyType,
49
- ReferenceEntity,
50
- ReferenceType,
51
- SemanticValueType,
52
62
  StrListType,
53
- Undefined,
54
63
  VersionType,
55
- ViewEntity,
56
- ViewPropEntity,
57
- XSDValueType,
58
64
  )
59
- from ._types._base import Unknown
60
65
 
61
66
  if TYPE_CHECKING:
62
67
  from ._dms_architect_rules import DMSProperty, DMSRules
@@ -118,8 +123,8 @@ class InformationClass(SheetEntity):
118
123
  match_type: The match type of the resource being described and the source entity.
119
124
  """
120
125
 
121
- parent: ParentClassType = Field(alias="Parent Class", default=None)
122
- reference: ReferenceType = Field(alias="Reference", default=None)
126
+ parent: ParentEntityList | None = Field(alias="Parent Class", default=None)
127
+ reference: URLEntity | ReferenceEntity | None = Field(alias="Reference", default=None, union_mode="left_to_right")
123
128
  match_type: MatchType | None = Field(alias="Match Type", default=None)
124
129
  comment: str | None = Field(alias="Comment", default=None)
125
130
 
@@ -146,11 +151,11 @@ class InformationProperty(SheetEntity):
146
151
  """
147
152
 
148
153
  property_: PropertyType = Field(alias="Property")
149
- value_type: SemanticValueType = Field(alias="Value Type")
154
+ value_type: DataType | ClassEntity | UnknownEntity = Field(alias="Value Type", union_mode="left_to_right")
150
155
  min_count: int | None = Field(alias="Min Count", default=None)
151
156
  max_count: int | float | None = Field(alias="Max Count", default=None)
152
157
  default: Any | None = Field(alias="Default", default=None)
153
- reference: ReferenceType = Field(alias="Reference", default=None)
158
+ reference: URLEntity | ReferenceEntity | None = Field(alias="Reference", default=None, union_mode="left_to_right")
154
159
  match_type: MatchType | None = Field(alias="Match Type", default=None)
155
160
  rule_type: str | TransformationRuleType | None = Field(alias="Rule Type", default=None)
156
161
  rule: str | AllReferences | SingleProperty | Hop | RawLookup | SPARQLQuery | Traversal | None = Field(
@@ -223,9 +228,9 @@ class InformationProperty(SheetEntity):
223
228
  @property
224
229
  def type_(self) -> EntityTypes:
225
230
  """Type of property based on value type. Either data (attribute) or object (edge) property."""
226
- if self.value_type.type_ == EntityTypes.xsd_value_type:
231
+ if isinstance(self.value_type, DataType):
227
232
  return EntityTypes.data_property
228
- elif self.value_type.type_ == EntityTypes.class_:
233
+ elif isinstance(self.value_type, ClassEntity):
229
234
  return EntityTypes.object_property
230
235
  else:
231
236
  return EntityTypes.undefined
@@ -258,7 +263,7 @@ class InformationRules(RuleModel):
258
263
  def update_entities_prefix(self) -> Self:
259
264
  # update expected_value_types
260
265
  for property_ in self.properties:
261
- if property_.value_type.prefix is Undefined and property_.value_type.suffix is not Unknown:
266
+ if isinstance(property_.value_type, ClassEntity) and property_.value_type.prefix is Undefined:
262
267
  property_.value_type.prefix = self.metadata.prefix
263
268
  if property_.class_.prefix is Undefined:
264
269
  property_.class_.prefix = self.metadata.prefix
@@ -267,7 +272,7 @@ class InformationRules(RuleModel):
267
272
  for class_ in self.classes:
268
273
  if class_.parent:
269
274
  for parent in cast(list[ParentClassEntity], class_.parent):
270
- if parent.prefix is Undefined:
275
+ if not isinstance(parent.prefix, str):
271
276
  parent.prefix = self.metadata.prefix
272
277
  if class_.class_.prefix is Undefined:
273
278
  class_.class_.prefix = self.metadata.prefix
@@ -279,15 +284,15 @@ class InformationRules(RuleModel):
279
284
  # update expected_value_types
280
285
 
281
286
  if self.metadata.schema_ == SchemaCompleteness.complete:
282
- defined_classes = {class_.class_.versioned_id for class_ in self.classes}
283
- referred_classes = {property_.class_.versioned_id for property_ in self.properties} | {
284
- parent.versioned_id for class_ in self.classes for parent in class_.parent or []
287
+ defined_classes = {str(class_.class_) for class_ in self.classes}
288
+ referred_classes = {str(property_.class_) for property_ in self.properties} | {
289
+ str(parent) for class_ in self.classes for parent in class_.parent or []
285
290
  }
286
291
  referred_types = {
287
- property_.value_type.versioned_id
292
+ str(property_.value_type)
288
293
  for property_ in self.properties
289
- if property_.type_ == EntityTypes.object_property
290
- and not (isinstance(property_.value_type, Entity) and property_.value_type.suffix is Unknown)
294
+ if isinstance(property_.value_type, Entity)
295
+ and not isinstance(property_.value_type.suffix, _UnknownType)
291
296
  }
292
297
  if not referred_classes.issubset(defined_classes) or not referred_types.issubset(defined_classes):
293
298
  missing_classes = referred_classes.difference(defined_classes).union(
@@ -300,7 +305,7 @@ class InformationRules(RuleModel):
300
305
  @model_validator(mode="after")
301
306
  def validate_class_has_properties_or_parent(self) -> Self:
302
307
  defined_classes = {class_.class_ for class_ in self.classes if class_.reference is None}
303
- referred_classes = {property_.class_ for property_ in self.properties}
308
+ referred_classes = {property_.class_ for property_ in self.properties if property_.class_.suffix is not Unknown}
304
309
  has_parent_classes = {class_.class_ for class_ in self.classes if class_.parent}
305
310
  missing_classes = defined_classes.difference(referred_classes) - has_parent_classes
306
311
  if missing_classes:
@@ -357,15 +362,21 @@ class InformationRules(RuleModel):
357
362
  new_self = self.model_copy(deep=True)
358
363
  for prop in new_self.properties:
359
364
  prop.reference = ReferenceEntity(
360
- prefix=prop.class_.prefix,
365
+ prefix=prop.class_.prefix
366
+ if not isinstance(prop.class_.prefix, _UndefinedType)
367
+ else self.metadata.prefix,
361
368
  suffix=prop.class_.suffix,
362
369
  version=prop.class_.version,
363
- property_=prop.property_,
370
+ property=prop.property_,
364
371
  )
365
372
 
366
373
  for cls_ in new_self.classes:
367
374
  cls_.reference = ReferenceEntity(
368
- prefix=cls_.class_.prefix, suffix=cls_.class_.suffix, version=cls_.class_.version
375
+ prefix=cls_.class_.prefix
376
+ if not isinstance(cls_.class_.prefix, _UndefinedType)
377
+ else self.metadata.prefix,
378
+ suffix=cls_.class_.suffix,
379
+ version=cls_.class_.version,
369
380
  )
370
381
 
371
382
  return new_self
@@ -382,7 +393,8 @@ class _InformationRulesConverter:
382
393
  from ._dms_architect_rules import DMSContainer, DMSMetadata, DMSProperty, DMSRules, DMSView
383
394
 
384
395
  info_metadata = self.information.metadata
385
-
396
+ default_version = info_metadata.version
397
+ default_space = self._to_space(info_metadata.prefix)
386
398
  space = self._to_space(info_metadata.prefix)
387
399
 
388
400
  metadata = DMSMetadata(
@@ -398,13 +410,15 @@ class _InformationRulesConverter:
398
410
 
399
411
  properties_by_class: dict[str, list[DMSProperty]] = defaultdict(list)
400
412
  for prop in self.information.properties:
401
- properties_by_class[prop.class_.versioned_id].append(self._as_dms_property(prop))
413
+ properties_by_class[prop.class_.versioned_id].append(
414
+ self._as_dms_property(prop, default_space, default_version)
415
+ )
402
416
 
403
417
  views: list[DMSView] = [
404
418
  DMSView(
405
419
  class_=cls_.class_,
406
420
  name=cls_.name,
407
- view=ViewPropEntity(prefix=cls_.class_.prefix, suffix=cls_.class_.suffix, version=cls_.class_.version),
421
+ view=cls_.class_.as_view_entity(default_space, default_version),
408
422
  description=cls_.description,
409
423
  reference=cls_.reference,
410
424
  implements=self._get_view_implements(cls_, info_metadata),
@@ -416,7 +430,7 @@ class _InformationRulesConverter:
416
430
  for class_ in self.information.classes:
417
431
  properties: list[DMSProperty] = properties_by_class.get(class_.class_.versioned_id, [])
418
432
  if not properties or all(
419
- isinstance(prop.value_type, ViewPropEntity) and prop.relation != "direct" for prop in properties
433
+ isinstance(prop.value_type, ViewPropertyEntity) and prop.relation != "direct" for prop in properties
420
434
  ):
421
435
  classes_without_properties.add(class_.class_.versioned_id)
422
436
 
@@ -428,13 +442,10 @@ class _InformationRulesConverter:
428
442
  DMSContainer(
429
443
  class_=class_.class_,
430
444
  name=class_.name,
431
- container=ContainerEntity(prefix=class_.class_.prefix, suffix=class_.class_.suffix),
445
+ container=class_.class_.as_container_entity(default_space),
432
446
  description=class_.description,
433
447
  constraint=[
434
- ContainerEntity(
435
- prefix=parent.prefix,
436
- suffix=parent.suffix,
437
- )
448
+ parent.as_container_entity(default_space)
438
449
  for parent in class_.parent or []
439
450
  if parent.versioned_id not in classes_without_properties
440
451
  ]
@@ -453,23 +464,24 @@ class _InformationRulesConverter:
453
464
  )
454
465
 
455
466
  @classmethod
456
- def _as_dms_property(cls, prop: InformationProperty) -> "DMSProperty":
467
+ def _as_dms_property(cls, prop: InformationProperty, default_space: str, default_version: str) -> "DMSProperty":
457
468
  """This creates the first"""
458
469
 
459
470
  from ._dms_architect_rules import DMSProperty
460
471
 
461
472
  # returns property type, which can be ObjectProperty or DatatypeProperty
462
- if isinstance(prop.value_type, XSDValueType):
463
- value_type = cast(XSDValueType, prop.value_type).dms._type.casefold() # type: ignore[attr-defined]
473
+ value_type: DataType | ViewEntity | ViewPropertyEntity | DMSUnknownEntity
474
+ if isinstance(prop.value_type, DataType):
475
+ value_type = prop.value_type
476
+ elif isinstance(prop.value_type, UnknownEntity):
477
+ value_type = DMSUnknownEntity()
464
478
  elif isinstance(prop.value_type, ClassEntity):
465
- value_type = ViewPropEntity(
466
- prefix=prop.value_type.prefix, suffix=prop.value_type.suffix, version=prop.value_type.version
467
- )
479
+ value_type = prop.value_type.as_view_entity(default_space, default_version)
468
480
  else:
469
481
  raise ValueError(f"Unsupported value type: {prop.value_type.type_}")
470
482
 
471
483
  relation: Literal["direct", "multiedge"] | None = None
472
- if isinstance(value_type, ViewPropEntity):
484
+ if isinstance(value_type, ViewEntity | ViewPropertyEntity):
473
485
  relation = "multiedge" if prop.is_list else "direct"
474
486
 
475
487
  container: ContainerEntity | None = None
@@ -481,9 +493,9 @@ class _InformationRulesConverter:
481
493
  nullable = None
482
494
  elif relation == "direct":
483
495
  nullable = True
484
- container, container_property = cls._get_container(prop)
496
+ container, container_property = cls._get_container(prop, default_space)
485
497
  else:
486
- container, container_property = cls._get_container(prop)
498
+ container, container_property = cls._get_container(prop, default_space)
487
499
 
488
500
  return DMSProperty(
489
501
  class_=prop.class_,
@@ -497,7 +509,7 @@ class _InformationRulesConverter:
497
509
  reference=prop.reference,
498
510
  container=container,
499
511
  container_property=container_property,
500
- view=ViewPropEntity(prefix=prop.class_.prefix, suffix=prop.class_.suffix, version=prop.class_.version),
512
+ view=prop.class_.as_view_entity(default_space, default_version),
501
513
  view_property=prop.property_,
502
514
  )
503
515
 
@@ -513,29 +525,24 @@ class _InformationRulesConverter:
513
525
  return prefix
514
526
 
515
527
  @classmethod
516
- def _get_container(cls, prop: InformationProperty) -> tuple[ContainerEntity, str]:
528
+ def _get_container(cls, prop: InformationProperty, default_space: str) -> tuple[ContainerEntity, str]:
517
529
  if isinstance(prop.reference, ReferenceEntity):
518
530
  return (
519
- ContainerEntity(prefix=prop.reference.prefix, suffix=prop.reference.suffix),
531
+ prop.reference.as_container_entity(default_space),
520
532
  prop.reference.property_ or prop.property_,
521
533
  )
522
534
  else:
523
- return ContainerEntity(prefix=prop.class_.prefix, suffix=prop.class_.suffix), prop.property_
535
+ return prop.class_.as_container_entity(default_space), prop.property_
524
536
 
525
537
  @classmethod
526
538
  def _get_view_implements(cls, cls_: InformationClass, metadata: InformationMetadata) -> list[ViewEntity]:
527
539
  if isinstance(cls_.reference, ReferenceEntity) and cls_.reference.prefix != metadata.prefix:
528
540
  # We use the reference for implements if it is in a different namespace
529
541
  implements = [
530
- ViewEntity(prefix=cls_.reference.prefix, suffix=cls_.reference.suffix, version=cls_.reference.version)
542
+ cls_.reference.as_view_entity(metadata.prefix, metadata.version),
531
543
  ]
532
544
  else:
533
545
  implements = []
534
546
 
535
- implements.extend(
536
- [
537
- ViewEntity(prefix=parent.prefix, suffix=parent.suffix, version=parent.version)
538
- for parent in cls_.parent or []
539
- ]
540
- )
547
+ implements.extend([parent.as_view_entity(metadata.prefix, metadata.version) for parent in cls_.parent or []])
541
548
  return implements
@@ -1,66 +1,19 @@
1
- from ._base import (
2
- ClassEntity,
3
- ContainerEntity,
4
- DataModelEntity,
5
- Entity,
6
- EntityTypes,
7
- ParentClassEntity,
8
- ReferenceEntity,
9
- Undefined,
10
- Unknown,
11
- ViewEntity,
12
- ViewPropEntity,
13
- )
14
1
  from ._field import (
15
- CdfValueType,
16
- ClassType,
17
- ContainerListType,
18
- ContainerType,
19
2
  ExternalIdType,
20
3
  NamespaceType,
21
- ParentClassType,
22
4
  PrefixType,
23
5
  PropertyType,
24
- ReferenceType,
25
- SemanticValueType,
26
6
  StrListType,
27
7
  StrOrListType,
28
8
  VersionType,
29
- ViewListType,
30
- ViewType,
31
9
  )
32
- from ._value import DMS_VALUE_TYPE_MAPPINGS, XSD_VALUE_TYPE_MAPPINGS, DMSValueType, XSDValueType
33
10
 
34
11
  __all__ = [
35
- "Undefined",
36
- "Unknown",
37
- "Entity",
38
- "EntityTypes",
39
- "ClassEntity",
40
- "ParentClassEntity",
41
- "ContainerEntity",
42
- "ViewEntity",
43
- "ViewPropEntity",
44
- "ReferenceEntity",
45
- "DataModelEntity",
46
- "XSDValueType",
47
- "DMSValueType",
48
- "XSD_VALUE_TYPE_MAPPINGS",
49
- "DMS_VALUE_TYPE_MAPPINGS",
50
12
  "StrOrListType",
51
13
  "StrListType",
52
14
  "NamespaceType",
53
15
  "PrefixType",
54
16
  "ExternalIdType",
55
17
  "VersionType",
56
- "ParentClassType",
57
- "ClassType",
58
18
  "PropertyType",
59
- "SemanticValueType",
60
- "CdfValueType",
61
- "ReferenceType",
62
- "ContainerType",
63
- "ViewType",
64
- "ContainerListType",
65
- "ViewListType",
66
19
  ]
@@ -1,51 +1,6 @@
1
- import re
2
- import sys
3
- from typing import Any, ClassVar, Literal, cast, overload
4
-
5
- from cognite.client.data_classes.data_modeling import ContainerId, DataModelId, PropertyId, ViewId
6
-
7
- from cognite.neat.rules.models._entity import (
8
- ENTITY_ID_REGEX_COMPILED,
9
- PREFIX_REGEX,
10
- PROPERTY_REGEX,
11
- SUFFIX_REGEX,
12
- VERSION_REGEX,
13
- VERSIONED_ENTITY_REGEX_COMPILED,
14
- Entity,
15
- EntityTypes,
16
- Undefined,
17
- Unknown,
18
- )
19
- from cognite.neat.rules.models.rdfpath import (
20
- SINGLE_PROPERTY_REGEX_COMPILED,
21
- AllReferences,
22
- RDFPath,
23
- SingleProperty,
24
- TransformationRuleType,
25
- parse_rule,
26
- )
27
-
28
- if sys.version_info >= (3, 11):
29
- from typing import Self
30
- else:
31
- from typing_extensions import Self
32
-
33
- # mypy: ignore-errors
34
- VERSION_ID_REGEX = rf"\(version=(?P<version>{VERSION_REGEX})\)"
35
-
36
-
37
- PROPERTY_ENTITY_REGEX_COMPILED = re.compile(
38
- rf"^((?P<prefix>{PREFIX_REGEX}):)?(?P<suffix>{SUFFIX_REGEX})"
39
- rf"\((version=(?P<version>{VERSION_REGEX}), )?property=(?P<property>{PROPERTY_REGEX})\)$"
40
- )
41
-
42
-
43
1
  MORE_THAN_ONE_NONE_ALPHANUMERIC_REGEX = r"([_-]{2,})"
44
2
  PREFIX_COMPLIANCE_REGEX = r"^([a-zA-Z]+)([a-zA-Z0-9]*[_-]{0,1}[a-zA-Z0-9_-]*)([a-zA-Z0-9]*)$"
45
- DATA_MODEL_ID_COMPLIANCE_REGEX = r"^[a-zA-Z]([a-zA-Z0-9_]{0,253}[a-zA-Z0-9])?$"
46
- CDF_SPACE_COMPLIANCE_REGEX = (
47
- r"(?!^(space|cdf|dms|pg3|shared|system|node|edge)$)(^[a-zA-Z][a-zA-Z0-9_-]{0,41}[a-zA-Z0-9]?$)"
48
- )
3
+
49
4
  VIEW_ID_COMPLIANCE_REGEX = (
50
5
  r"(?!^(Query|Mutation|Subscription|String|Int32|Int64|Int|Float32|Float64|Float|"
51
6
  r"Timestamp|JSONObject|Date|Numeric|Boolean|PageInfo|File|Sequence|TimeSeries)$)"
@@ -59,266 +14,3 @@ DMS_PROPERTY_ID_COMPLIANCE_REGEX = (
59
14
  CLASS_ID_COMPLIANCE_REGEX = r"(?!^(Class|class)$)(^[a-zA-Z][a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
60
15
  PROPERTY_ID_COMPLIANCE_REGEX = r"^(\*)|(?!^(Property|property)$)(^[a-zA-Z][a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
61
16
  VERSION_COMPLIANCE_REGEX = r"^[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?$"
62
-
63
-
64
- class ContainerEntity(Entity):
65
- type_: ClassVar[EntityTypes] = EntityTypes.container
66
-
67
- @classmethod
68
- def from_raw(cls, value: Any) -> "ContainerEntity":
69
- if not value:
70
- return ContainerEntity(prefix=Undefined, suffix=value)
71
- elif isinstance(value, ContainerEntity):
72
- return value
73
-
74
- if ENTITY_ID_REGEX_COMPILED.match(value):
75
- return ContainerEntity.from_string(entity_string=value)
76
- else:
77
- return ContainerEntity(prefix=Undefined, suffix=value)
78
-
79
- @classmethod
80
- def from_id(cls, container_id: ContainerId) -> "ContainerEntity":
81
- return ContainerEntity(prefix=container_id.space, suffix=container_id.external_id)
82
-
83
- def as_id(self, default_space: str | None) -> ContainerId:
84
- if self.space is Undefined and default_space is None:
85
- raise ValueError("Space is Undefined! Set default_space!")
86
-
87
- if self.space is Undefined:
88
- return ContainerId(space=cast(str, default_space), external_id=self.external_id)
89
- else:
90
- return ContainerId(space=self.space, external_id=self.external_id)
91
-
92
-
93
- class ViewEntity(Entity):
94
- type_: ClassVar[EntityTypes] = EntityTypes.view
95
-
96
- @classmethod
97
- def from_raw(cls, value: Any) -> "ViewEntity":
98
- if not value:
99
- return ViewEntity(prefix=Undefined, suffix=value)
100
- elif isinstance(value, ViewEntity):
101
- return value
102
-
103
- if ENTITY_ID_REGEX_COMPILED.match(value) or VERSIONED_ENTITY_REGEX_COMPILED.match(value):
104
- return cls.from_string(entity_string=value)
105
- else:
106
- return cls(prefix=Undefined, suffix=value)
107
-
108
- @classmethod
109
- def from_id(cls, view_id: ViewId) -> Self:
110
- return cls(prefix=view_id.space, suffix=view_id.external_id, version=view_id.version)
111
-
112
- @overload
113
- def as_id(
114
- self,
115
- allow_none: Literal[False] = False,
116
- default_space: str | None = None,
117
- default_version: str | None = None,
118
- ) -> ViewId:
119
- ...
120
-
121
- @overload
122
- def as_id(
123
- self,
124
- allow_none: Literal[True],
125
- default_space: str | None = None,
126
- default_version: str | None = None,
127
- ) -> ViewId | None:
128
- ...
129
-
130
- def as_id(
131
- self,
132
- allow_none: bool = False,
133
- default_space: str | None = None,
134
- default_version: str | None = None,
135
- ) -> ViewId | None:
136
- if self.suffix is Unknown and allow_none:
137
- return None
138
- elif self.suffix is Unknown:
139
- raise ValueError("suffix is Unknown and cannot be converted to ViewId")
140
- space = default_space if self.space is Undefined else self.space
141
- version = self.version or default_version
142
-
143
- if space is None or space is Undefined:
144
- raise ValueError("space is required")
145
- if version is None:
146
- raise ValueError("version is required")
147
- return ViewId(space=space, external_id=self.external_id, version=version)
148
-
149
-
150
- class ViewPropEntity(ViewEntity):
151
- type_: ClassVar[EntityTypes] = EntityTypes.view_prop
152
- property_: str | None = None
153
-
154
- @classmethod
155
- def from_raw(cls, value: Any) -> "ViewPropEntity":
156
- if not value:
157
- return ViewPropEntity(prefix=Undefined, suffix=value)
158
- elif isinstance(value, ViewPropEntity):
159
- return value
160
- elif isinstance(value, ViewEntity):
161
- return cls(prefix=value.prefix, suffix=value.suffix, version=value.version)
162
-
163
- if result := PROPERTY_ENTITY_REGEX_COMPILED.match(value):
164
- return cls(
165
- prefix=result.group("prefix") or Undefined,
166
- suffix=result.group("suffix"),
167
- version=result.group("version"),
168
- property_=result.group("property"),
169
- )
170
- elif ENTITY_ID_REGEX_COMPILED.match(value) or VERSIONED_ENTITY_REGEX_COMPILED.match(value):
171
- return cls.from_string(entity_string=value)
172
- else:
173
- return cls(prefix=Undefined, suffix=value)
174
-
175
- @classmethod
176
- def from_prop_id(cls, prop_id: PropertyId) -> "ViewPropEntity":
177
- return ViewPropEntity(
178
- prefix=prop_id.source.space,
179
- suffix=prop_id.source.external_id,
180
- version=cast(ViewId, prop_id.source).version,
181
- property_=prop_id.property,
182
- )
183
-
184
- def as_prop_id(self, default_space: str | None = None, default_version: str | None = None) -> PropertyId:
185
- if self.property_ is None:
186
- raise ValueError("property is required to create PropertyId")
187
- return PropertyId(source=self.as_id(False, default_space, default_version), property=self.property_)
188
-
189
- @property
190
- def versioned_id(self) -> str:
191
- if self.version is None and self.property_ is None:
192
- output = self.id
193
- elif self.version is None:
194
- output = f"{self.id}(property={self.property_})"
195
- elif self.property_ is None:
196
- output = f"{self.id}(version={self.version})"
197
- else:
198
- output = f"{self.id}(version={self.version}, property={self.property_})"
199
- return output
200
-
201
-
202
- class DataModelEntity(Entity):
203
- type_: ClassVar[EntityTypes] = EntityTypes.datamodel
204
-
205
- @classmethod
206
- def from_raw(cls, value: Any) -> "DataModelEntity":
207
- if not value:
208
- return DataModelEntity(prefix=Undefined, suffix=value)
209
- elif isinstance(value, DataModelEntity):
210
- return value
211
-
212
- if ENTITY_ID_REGEX_COMPILED.match(value) or VERSIONED_ENTITY_REGEX_COMPILED.match(value):
213
- return DataModelEntity.from_string(entity_string=value)
214
- else:
215
- return DataModelEntity(prefix=Undefined, suffix=value)
216
-
217
- @classmethod
218
- def from_id(cls, data_model_id: DataModelId) -> "DataModelEntity":
219
- return DataModelEntity(
220
- prefix=data_model_id.space, suffix=data_model_id.external_id, version=data_model_id.version
221
- )
222
-
223
- def as_id(self, default_space: str | None = None, default_version: str | None = None) -> DataModelId:
224
- space = default_space if self.space is Undefined else self.space
225
- version = self.version or default_version
226
-
227
- if space is None or space is Undefined:
228
- raise ValueError("space is required")
229
-
230
- return DataModelId(space=space, external_id=self.external_id, version=version)
231
-
232
-
233
- class ClassEntity(Entity):
234
- type_: ClassVar[EntityTypes] = EntityTypes.class_
235
-
236
- @classmethod
237
- def from_raw(cls, value: Any) -> Self:
238
- if not value:
239
- return cls(prefix=Undefined, suffix=value)
240
- elif isinstance(value, cls):
241
- return value
242
-
243
- if ENTITY_ID_REGEX_COMPILED.match(value) or VERSIONED_ENTITY_REGEX_COMPILED.match(value):
244
- return cls.from_string(entity_string=value)
245
- else:
246
- return cls(prefix=Undefined, suffix=value)
247
-
248
- @classmethod
249
- def from_view_id(cls, view_id: ViewId) -> Self:
250
- return cls(prefix=view_id.space, suffix=view_id.external_id, version=view_id.version)
251
-
252
- @property
253
- def view_id(self) -> ViewId:
254
- return ViewId(space=self.space, external_id=self.external_id, version=self.version)
255
-
256
-
257
- class ParentClassEntity(ClassEntity):
258
- type_: ClassVar[EntityTypes] = EntityTypes.parent_class
259
-
260
- @classmethod
261
- def from_raw(cls, value: Any) -> Self:
262
- if isinstance(value, ClassEntity):
263
- return cls(prefix=value.prefix, suffix=value.suffix, version=value.version)
264
- return super().from_raw(value)
265
-
266
- def as_class_entity(self) -> ClassEntity:
267
- return ClassEntity(prefix=self.prefix, suffix=self.suffix, version=self.version)
268
-
269
-
270
- class ReferenceEntity(ViewPropEntity):
271
- type_: ClassVar[EntityTypes] = EntityTypes.reference_entity
272
-
273
- @classmethod
274
- def from_raw(cls, value: Any) -> "ReferenceEntity":
275
- if not value:
276
- return ReferenceEntity(prefix=Undefined, suffix=value)
277
- elif isinstance(value, ReferenceEntity):
278
- return value
279
- elif isinstance(value, ViewEntity):
280
- return cls(prefix=value.prefix, suffix=value.suffix, version=value.version)
281
-
282
- if result := PROPERTY_ENTITY_REGEX_COMPILED.match(value):
283
- return cls(
284
- prefix=result.group("prefix") or Undefined,
285
- suffix=result.group("suffix"),
286
- version=result.group("version"),
287
- property_=result.group("property"),
288
- )
289
- elif ENTITY_ID_REGEX_COMPILED.match(value) or VERSIONED_ENTITY_REGEX_COMPILED.match(value):
290
- return cls.from_string(entity_string=value)
291
- elif result := SINGLE_PROPERTY_REGEX_COMPILED.match(value):
292
- return cls.from_rdfpath(value)
293
- else:
294
- return cls(prefix=Undefined, suffix=value)
295
-
296
- @classmethod
297
- def from_rdfpath(cls, rdfpath: RDFPath | str) -> "ReferenceEntity":
298
- if isinstance(rdfpath, str):
299
- rdfpath = parse_rule(rdfpath, TransformationRuleType.rdfpath)
300
-
301
- if isinstance(rdfpath.traversal, AllReferences):
302
- return cls(prefix=rdfpath.traversal.class_.prefix, suffix=rdfpath.traversal.class_.suffix)
303
- elif isinstance(rdfpath.traversal, SingleProperty):
304
- return cls(
305
- prefix=rdfpath.traversal.class_.prefix,
306
- suffix=rdfpath.traversal.class_.suffix,
307
- property_=rdfpath.traversal.property.suffix,
308
- )
309
- else:
310
- raise ValueError(f"Invalid RDFPath traversal type: {rdfpath.traversal}")
311
-
312
- def as_rdfpath(self, default_prefix: str | None = None) -> RDFPath:
313
- prefix = self.prefix if self.prefix is not Undefined else default_prefix
314
-
315
- if prefix is None:
316
- raise ValueError("prefix is required")
317
-
318
- if self.property_:
319
- return parse_rule(f"{prefix}:{self.suffix}({self.prefix}:{self.property_})", TransformationRuleType.rdfpath)
320
- else:
321
- return parse_rule(f"{self.prefix}:{self.suffix}", TransformationRuleType.rdfpath)
322
-
323
- def as_class_entity(self) -> ClassEntity:
324
- return ClassEntity(prefix=self.prefix, suffix=self.suffix, version=self.version)