cognite-neat 0.121.1__py3-none-any.whl → 0.122.0__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.
- cognite/neat/_version.py +1 -1
- cognite/neat/core/_client/_api/statistics.py +91 -0
- cognite/neat/core/_client/_api_client.py +2 -0
- cognite/neat/core/_client/data_classes/statistics.py +125 -0
- cognite/neat/core/_client/testing.py +4 -0
- cognite/neat/core/_constants.py +6 -7
- cognite/neat/core/_data_model/_constants.py +23 -16
- cognite/neat/core/_data_model/_shared.py +33 -17
- cognite/neat/core/_data_model/analysis/__init__.py +2 -2
- cognite/neat/core/_data_model/analysis/_base.py +186 -183
- cognite/neat/core/_data_model/catalog/__init__.py +2 -2
- cognite/neat/core/_data_model/exporters/__init__.py +6 -6
- cognite/neat/core/_data_model/exporters/_base.py +10 -8
- cognite/neat/core/_data_model/exporters/{_rules2dms.py → _data_model2dms.py} +22 -18
- cognite/neat/core/_data_model/exporters/{_rules2excel.py → _data_model2excel.py} +51 -51
- cognite/neat/core/_data_model/exporters/{_rules2instance_template.py → _data_model2instance_template.py} +14 -14
- cognite/neat/core/_data_model/exporters/{_rules2ontology.py → _data_model2ontology.py} +50 -50
- cognite/neat/core/_data_model/exporters/{_rules2yaml.py → _data_model2yaml.py} +21 -18
- cognite/neat/core/_data_model/importers/__init__.py +8 -8
- cognite/neat/core/_data_model/importers/_base.py +8 -6
- cognite/neat/core/_data_model/importers/_base_file_reader.py +56 -0
- cognite/neat/core/_data_model/importers/{_yaml2rules.py → _dict2data_model.py} +50 -25
- cognite/neat/core/_data_model/importers/{_dms2rules.py → _dms2data_model.py} +58 -49
- cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/dtdl_converter.py +22 -22
- cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/dtdl_importer.py +7 -7
- cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/spec.py +3 -3
- cognite/neat/core/_data_model/importers/_rdf/__init__.py +3 -3
- cognite/neat/core/_data_model/importers/_rdf/_base.py +15 -15
- cognite/neat/core/_data_model/importers/_rdf/{_imf2rules.py → _imf2data_model.py} +17 -17
- cognite/neat/core/_data_model/importers/_rdf/{_inference2rules.py → _inference2rdata_model.py} +59 -59
- cognite/neat/core/_data_model/importers/_rdf/{_owl2rules.py → _owl2data_model.py} +17 -17
- cognite/neat/core/_data_model/importers/_rdf/_shared.py +25 -25
- cognite/neat/core/_data_model/importers/{_spreadsheet2rules.py → _spreadsheet2data_model.py} +76 -19
- cognite/neat/core/_data_model/models/__init__.py +11 -9
- cognite/neat/core/_data_model/models/_base_unverified.py +12 -12
- cognite/neat/core/_data_model/models/_base_verified.py +9 -14
- cognite/neat/core/_data_model/models/_types.py +6 -6
- cognite/neat/core/_data_model/models/conceptual/__init__.py +6 -6
- cognite/neat/core/_data_model/models/conceptual/_unverified.py +20 -20
- cognite/neat/core/_data_model/models/conceptual/_validation.py +88 -78
- cognite/neat/core/_data_model/models/conceptual/_verified.py +54 -52
- cognite/neat/core/_data_model/models/data_types.py +2 -2
- cognite/neat/core/_data_model/models/entities/__init__.py +8 -8
- cognite/neat/core/_data_model/models/entities/_loaders.py +11 -10
- cognite/neat/core/_data_model/models/entities/_multi_value.py +5 -5
- cognite/neat/core/_data_model/models/entities/_single_value.py +44 -38
- cognite/neat/core/_data_model/models/entities/_types.py +9 -3
- cognite/neat/core/_data_model/models/entities/_wrapped.py +3 -3
- cognite/neat/core/_data_model/models/mapping/_classic2core.py +12 -9
- cognite/neat/core/_data_model/models/physical/__init__.py +40 -0
- cognite/neat/core/_data_model/models/{dms → physical}/_exporter.py +75 -55
- cognite/neat/core/_data_model/models/{dms/_rules_input.py → physical/_unverified.py} +48 -39
- cognite/neat/core/_data_model/models/{dms → physical}/_validation.py +17 -15
- cognite/neat/core/_data_model/models/{dms/_rules.py → physical/_verified.py} +68 -60
- cognite/neat/core/_data_model/transformers/__init__.py +29 -25
- cognite/neat/core/_data_model/transformers/_base.py +27 -20
- cognite/neat/core/_data_model/transformers/_converters.py +707 -622
- cognite/neat/core/_data_model/transformers/_mapping.py +74 -55
- cognite/neat/core/_data_model/transformers/_verification.py +64 -55
- cognite/neat/core/_instances/extractors/_base.py +2 -2
- cognite/neat/core/_instances/extractors/_classic_cdf/_classic.py +9 -9
- cognite/neat/core/_instances/extractors/_dms_graph.py +42 -34
- cognite/neat/core/_instances/extractors/_mock_graph_generator.py +107 -103
- cognite/neat/core/_instances/loaders/_base.py +3 -3
- cognite/neat/core/_instances/loaders/_rdf2dms.py +22 -22
- cognite/neat/core/_instances/transformers/_base.py +7 -4
- cognite/neat/core/_instances/transformers/_rdfpath.py +1 -1
- cognite/neat/core/_instances/transformers/_value_type.py +2 -6
- cognite/neat/core/_issues/_base.py +4 -4
- cognite/neat/core/_issues/_factory.py +1 -1
- cognite/neat/core/_issues/errors/__init__.py +2 -2
- cognite/neat/core/_issues/errors/_resources.py +1 -1
- cognite/neat/core/_issues/errors/_wrapper.py +2 -2
- cognite/neat/core/_issues/warnings/_models.py +4 -4
- cognite/neat/core/_issues/warnings/_properties.py +1 -1
- cognite/neat/core/_store/__init__.py +3 -3
- cognite/neat/core/_store/{_rules_store.py → _data_model.py} +119 -112
- cognite/neat/core/_store/{_graph_store.py → _instance.py} +3 -4
- cognite/neat/core/_store/_provenance.py +2 -2
- cognite/neat/core/_store/exceptions.py +2 -2
- cognite/neat/core/_utils/rdf_.py +14 -0
- cognite/neat/core/_utils/text.py +1 -1
- cognite/neat/session/_base.py +42 -36
- cognite/neat/session/_drop.py +2 -2
- cognite/neat/session/_experimental.py +1 -1
- cognite/neat/session/_inspect.py +13 -13
- cognite/neat/session/_mapping.py +15 -9
- cognite/neat/session/_read.py +39 -37
- cognite/neat/session/_set.py +6 -6
- cognite/neat/session/_show.py +24 -21
- cognite/neat/session/_state/README.md +1 -1
- cognite/neat/session/_state.py +27 -27
- cognite/neat/session/_subset.py +14 -11
- cognite/neat/session/_template.py +23 -21
- cognite/neat/session/_to.py +42 -42
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.122.0.dist-info}/METADATA +14 -7
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.122.0.dist-info}/RECORD +102 -100
- cognite/neat/core/_data_model/exporters/_validation.py +0 -14
- cognite/neat/core/_data_model/models/dms/__init__.py +0 -32
- /cognite/neat/core/_data_model/catalog/{info-rules-imf.xlsx → conceptual-imf-data-model.xlsx} +0 -0
- /cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/__init__.py +0 -0
- /cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/_unit_lookup.py +0 -0
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.122.0.dist-info}/WHEEL +0 -0
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.122.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,23 +22,23 @@ from cognite.neat.core._data_model.models._base_verified import (
|
|
|
22
22
|
ViewRef,
|
|
23
23
|
)
|
|
24
24
|
from cognite.neat.core._data_model.models._types import (
|
|
25
|
-
|
|
25
|
+
ConceptEntityType,
|
|
26
26
|
ContainerEntityType,
|
|
27
|
-
|
|
27
|
+
PhysicalPropertyType,
|
|
28
28
|
StrListType,
|
|
29
29
|
URIRefType,
|
|
30
30
|
ViewEntityType,
|
|
31
31
|
)
|
|
32
32
|
from cognite.neat.core._data_model.models.data_types import DataType
|
|
33
33
|
from cognite.neat.core._data_model.models.entities import (
|
|
34
|
+
ConceptualEntity,
|
|
34
35
|
ContainerEntityList,
|
|
35
|
-
DMSEntity,
|
|
36
36
|
DMSNodeEntity,
|
|
37
|
-
DMSUnknownEntity,
|
|
38
37
|
EdgeEntity,
|
|
39
|
-
Entity,
|
|
40
38
|
HasDataFilter,
|
|
41
39
|
NodeTypeFilter,
|
|
40
|
+
PhysicalEntity,
|
|
41
|
+
PhysicalUnknownEntity,
|
|
42
42
|
RawFilter,
|
|
43
43
|
ReverseConnectionEntity,
|
|
44
44
|
ViewEntity,
|
|
@@ -53,10 +53,10 @@ if TYPE_CHECKING:
|
|
|
53
53
|
_DEFAULT_VERSION = "1"
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
class
|
|
56
|
+
class PhysicalMetadata(BaseVerifiedMetadata):
|
|
57
57
|
role: ClassVar[RoleTypes] = RoleTypes.dms
|
|
58
58
|
level: ClassVar[DataModelLevel] = DataModelLevel.physical
|
|
59
|
-
|
|
59
|
+
conceptual: URIRefType | None = None
|
|
60
60
|
|
|
61
61
|
def as_space(self) -> dm.SpaceApply:
|
|
62
62
|
return dm.SpaceApply(
|
|
@@ -83,15 +83,21 @@ class DMSMetadata(BaseVerifiedMetadata):
|
|
|
83
83
|
return self.space
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def _metadata(context: Any) ->
|
|
87
|
-
if isinstance(context, dict) and isinstance(context.get("metadata"),
|
|
86
|
+
def _metadata(context: Any) -> PhysicalMetadata | None:
|
|
87
|
+
if isinstance(context, dict) and isinstance(context.get("metadata"), PhysicalMetadata):
|
|
88
88
|
return context["metadata"]
|
|
89
89
|
return None
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
class
|
|
92
|
+
class PhysicalProperty(SheetRow):
|
|
93
|
+
"""Physical property provides a complete definition of a property in the data model in a physical data model.
|
|
94
|
+
This includes view to which the property belongs as well mapping between the view and container property.
|
|
95
|
+
"""
|
|
96
|
+
|
|
93
97
|
view: ViewEntityType = Field(alias="View", description="The property identifier.")
|
|
94
|
-
view_property:
|
|
98
|
+
view_property: PhysicalPropertyType = Field(
|
|
99
|
+
alias="View Property", description="The ViewId this property belongs to"
|
|
100
|
+
)
|
|
95
101
|
name: str | None = Field(alias="Name", default=None, description="Human readable name of the property")
|
|
96
102
|
description: str | None = Field(alias="Description", default=None, description="Short description of the property")
|
|
97
103
|
connection: Literal["direct"] | ReverseConnectionEntity | EdgeEntity | None = Field(
|
|
@@ -100,7 +106,7 @@ class DMSProperty(SheetRow):
|
|
|
100
106
|
description="nly applies to connection between views. "
|
|
101
107
|
"It specify how the connection should be implemented in CDF.",
|
|
102
108
|
)
|
|
103
|
-
value_type: DataType | ViewEntity |
|
|
109
|
+
value_type: DataType | ViewEntity | PhysicalUnknownEntity = Field(
|
|
104
110
|
alias="Value Type",
|
|
105
111
|
description="Value type that the property can hold. It takes either subset of CDF primitive types or a View id",
|
|
106
112
|
)
|
|
@@ -131,7 +137,7 @@ class DMSProperty(SheetRow):
|
|
|
131
137
|
alias="Container",
|
|
132
138
|
description="Specifies container where the property is stored. Only applies to primitive type.",
|
|
133
139
|
)
|
|
134
|
-
container_property:
|
|
140
|
+
container_property: PhysicalPropertyType | None = Field(
|
|
135
141
|
None,
|
|
136
142
|
alias="Container Property",
|
|
137
143
|
description="Specifies property in the container where the property is stored. Only applies to primitive type.",
|
|
@@ -146,10 +152,10 @@ class DMSProperty(SheetRow):
|
|
|
146
152
|
alias="Constraint",
|
|
147
153
|
description="The names of the uniquness (comma separated) that should be created for the property.",
|
|
148
154
|
)
|
|
149
|
-
|
|
155
|
+
conceptual: URIRefType | None = Field(
|
|
150
156
|
None,
|
|
151
|
-
alias="
|
|
152
|
-
description="Used to make connection between physical and
|
|
157
|
+
alias="Conceptual",
|
|
158
|
+
description="Used to make connection between physical and conceptual data model aspect",
|
|
153
159
|
)
|
|
154
160
|
|
|
155
161
|
@property
|
|
@@ -193,8 +199,8 @@ class DMSProperty(SheetRow):
|
|
|
193
199
|
|
|
194
200
|
@field_validator("value_type", mode="after")
|
|
195
201
|
def connections_value_type(
|
|
196
|
-
cls, value: EdgeEntity | ViewEntity |
|
|
197
|
-
) -> DataType | EdgeEntity | ViewEntity |
|
|
202
|
+
cls, value: EdgeEntity | ViewEntity | PhysicalUnknownEntity, info: ValidationInfo
|
|
203
|
+
) -> DataType | EdgeEntity | ViewEntity | PhysicalUnknownEntity:
|
|
198
204
|
if (connection := info.data.get("connection")) is None:
|
|
199
205
|
if isinstance(value, ViewEntity):
|
|
200
206
|
raise ValueError(
|
|
@@ -202,7 +208,7 @@ class DMSProperty(SheetRow):
|
|
|
202
208
|
f"is required with value type pointing to another view."
|
|
203
209
|
)
|
|
204
210
|
return value
|
|
205
|
-
if connection == "direct" and not isinstance(value, ViewEntity |
|
|
211
|
+
if connection == "direct" and not isinstance(value, ViewEntity | PhysicalUnknownEntity):
|
|
206
212
|
raise ValueError(f"Direct relation must have a value type that points to a view, got {value}")
|
|
207
213
|
elif isinstance(connection, EdgeEntity) and not isinstance(value, ViewEntity):
|
|
208
214
|
raise ValueError(f"Edge connection must have a value type that points to a view, got {value}")
|
|
@@ -261,7 +267,7 @@ class DMSProperty(SheetRow):
|
|
|
261
267
|
|
|
262
268
|
@field_serializer("view", "container", when_used="unless-none")
|
|
263
269
|
def remove_default_space(self, value: str, info: SerializationInfo) -> str:
|
|
264
|
-
if (metadata := _metadata(info.context)) and isinstance(value,
|
|
270
|
+
if (metadata := _metadata(info.context)) and isinstance(value, ConceptualEntity):
|
|
265
271
|
if info.field_name == "container" and info.context.get("as_reference") is True:
|
|
266
272
|
# When dumping as reference, the container should keep the default space for easy copying
|
|
267
273
|
# over to user sheets.
|
|
@@ -271,7 +277,7 @@ class DMSProperty(SheetRow):
|
|
|
271
277
|
|
|
272
278
|
@field_serializer("connection", when_used="unless-none")
|
|
273
279
|
def remove_defaults(self, value: Any, info: SerializationInfo) -> str:
|
|
274
|
-
if isinstance(value,
|
|
280
|
+
if isinstance(value, ConceptualEntity) and (metadata := _metadata(info.context)):
|
|
275
281
|
default_type = f"{self.view.external_id}.{self.view_property}"
|
|
276
282
|
if isinstance(value, EdgeEntity) and value.edge_type and value.edge_type.space != metadata.space:
|
|
277
283
|
default_type = f"{metadata.space}{default_type}"
|
|
@@ -287,7 +293,7 @@ class DMSProperty(SheetRow):
|
|
|
287
293
|
return ViewProperty(view=self.view, property_=self.view_property)
|
|
288
294
|
|
|
289
295
|
|
|
290
|
-
class
|
|
296
|
+
class PhysicalContainer(SheetRow):
|
|
291
297
|
container: ContainerEntityType = Field(
|
|
292
298
|
alias="Container", description="Container id, strongly advised to PascalCase usage."
|
|
293
299
|
)
|
|
@@ -327,9 +333,9 @@ class DMSContainer(SheetRow):
|
|
|
327
333
|
@field_serializer("container", when_used="unless-none")
|
|
328
334
|
def remove_default_space(self, value: Any, info: SerializationInfo) -> str:
|
|
329
335
|
if metadata := _metadata(info.context):
|
|
330
|
-
if isinstance(value,
|
|
336
|
+
if isinstance(value, PhysicalEntity):
|
|
331
337
|
return value.dump(space=metadata.space, version=metadata.version)
|
|
332
|
-
elif isinstance(value,
|
|
338
|
+
elif isinstance(value, ConceptualEntity):
|
|
333
339
|
return value.dump(prefix=metadata.space, version=metadata.version)
|
|
334
340
|
return str(value)
|
|
335
341
|
|
|
@@ -338,14 +344,14 @@ class DMSContainer(SheetRow):
|
|
|
338
344
|
if isinstance(value, list) and (metadata := _metadata(info.context)):
|
|
339
345
|
return ",".join(
|
|
340
346
|
constraint.dump(space=metadata.space, version=metadata.version)
|
|
341
|
-
if isinstance(constraint,
|
|
347
|
+
if isinstance(constraint, PhysicalEntity)
|
|
342
348
|
else str(constraint)
|
|
343
349
|
for constraint in value
|
|
344
350
|
)
|
|
345
351
|
return ",".join(str(value) for value in value)
|
|
346
352
|
|
|
347
353
|
|
|
348
|
-
class
|
|
354
|
+
class PhysicalView(SheetRow):
|
|
349
355
|
view: ViewEntityType = Field(alias="View", description="View id, strongly advised to PascalCase usage.")
|
|
350
356
|
name: str | None = Field(alias="Name", default=None, description="Human readable name of the view being defined.")
|
|
351
357
|
description: str | None = Field(
|
|
@@ -364,10 +370,10 @@ class DMSView(SheetRow):
|
|
|
364
370
|
alias="In Model",
|
|
365
371
|
description="Indicates whether the view being defined is a part of the data model.",
|
|
366
372
|
)
|
|
367
|
-
|
|
373
|
+
conceptual: URIRefType | None = Field(
|
|
368
374
|
None,
|
|
369
|
-
alias="
|
|
370
|
-
description="Used to make connection between physical and
|
|
375
|
+
alias="Conceptual",
|
|
376
|
+
description="Used to make connection between physical and conceptual data model level",
|
|
371
377
|
)
|
|
372
378
|
|
|
373
379
|
def _identifier(self) -> tuple[Hashable, ...]:
|
|
@@ -375,7 +381,7 @@ class DMSView(SheetRow):
|
|
|
375
381
|
|
|
376
382
|
@field_serializer("view", when_used="unless-none")
|
|
377
383
|
def remove_default_space(self, value: Any, info: SerializationInfo) -> str:
|
|
378
|
-
if (metadata := _metadata(info.context)) and isinstance(value,
|
|
384
|
+
if (metadata := _metadata(info.context)) and isinstance(value, ConceptualEntity):
|
|
379
385
|
return value.dump(prefix=metadata.space, version=metadata.version)
|
|
380
386
|
return str(value)
|
|
381
387
|
|
|
@@ -384,7 +390,7 @@ class DMSView(SheetRow):
|
|
|
384
390
|
if isinstance(value, list) and (metadata := _metadata(info.context)):
|
|
385
391
|
return ",".join(
|
|
386
392
|
parent.dump(space=metadata.space, version=metadata.version)
|
|
387
|
-
if isinstance(parent,
|
|
393
|
+
if isinstance(parent, PhysicalEntity)
|
|
388
394
|
else str(parent)
|
|
389
395
|
for parent in value
|
|
390
396
|
)
|
|
@@ -409,7 +415,7 @@ class DMSView(SheetRow):
|
|
|
409
415
|
return ViewRef(view=self.view)
|
|
410
416
|
|
|
411
417
|
|
|
412
|
-
class
|
|
418
|
+
class PhysicalNodeType(SheetRow):
|
|
413
419
|
node: DMSNodeEntity = Field(alias="Node", description="The type definition of the node.")
|
|
414
420
|
usage: Literal["type", "collection"] = Field(
|
|
415
421
|
alias="Usage", description="What the usage of the node is in the data model."
|
|
@@ -432,13 +438,13 @@ class DMSNode(SheetRow):
|
|
|
432
438
|
|
|
433
439
|
@field_serializer("node", when_used="unless-none")
|
|
434
440
|
def remove_default_space(self, value: Any, info: SerializationInfo) -> str:
|
|
435
|
-
if isinstance(value,
|
|
441
|
+
if isinstance(value, PhysicalEntity) and (metadata := _metadata(info.context)):
|
|
436
442
|
return value.dump(space=metadata.space, version=metadata.version)
|
|
437
443
|
return str(value)
|
|
438
444
|
|
|
439
445
|
|
|
440
|
-
class
|
|
441
|
-
collection:
|
|
446
|
+
class PhysicalEnum(SheetRow):
|
|
447
|
+
collection: ConceptEntityType = Field(alias="Collection", description="The collection this enum belongs to.")
|
|
442
448
|
value: str = Field(alias="Value", description="The value of the enum.")
|
|
443
449
|
name: str | None = Field(alias="Name", default=None, description="Human readable name of the enum.")
|
|
444
450
|
description: str | None = Field(alias="Description", default=None, description="Short description of the enum.")
|
|
@@ -448,29 +454,31 @@ class DMSEnum(SheetRow):
|
|
|
448
454
|
|
|
449
455
|
@field_serializer("collection", when_used="unless-none")
|
|
450
456
|
def remove_default_space(self, value: Any, info: SerializationInfo) -> str:
|
|
451
|
-
if isinstance(value,
|
|
457
|
+
if isinstance(value, PhysicalEntity) and (metadata := _metadata(info.context)):
|
|
452
458
|
return value.dump(space=metadata.space, version=metadata.version)
|
|
453
459
|
return str(value)
|
|
454
460
|
|
|
455
461
|
|
|
456
|
-
class
|
|
457
|
-
metadata:
|
|
458
|
-
properties: SheetList[
|
|
462
|
+
class PhysicalDataModel(BaseVerifiedDataModel):
|
|
463
|
+
metadata: PhysicalMetadata = Field(alias="Metadata", description="Contains information about the data model.")
|
|
464
|
+
properties: SheetList[PhysicalProperty] = Field(
|
|
459
465
|
alias="Properties", description="Contains the properties of the data model."
|
|
460
466
|
)
|
|
461
|
-
views: SheetList[
|
|
462
|
-
containers: SheetList[
|
|
467
|
+
views: SheetList[PhysicalView] = Field(alias="Views", description="Contains the views of the data model.")
|
|
468
|
+
containers: SheetList[PhysicalContainer] | None = Field(
|
|
463
469
|
None,
|
|
464
470
|
alias="Containers",
|
|
465
471
|
description="Contains the definition containers that are the physical storage of the data model.",
|
|
466
472
|
)
|
|
467
|
-
enum: SheetList[
|
|
468
|
-
|
|
473
|
+
enum: SheetList[PhysicalEnum] | None = Field(
|
|
474
|
+
None, alias="Enum", description="Contains the definition of enum values."
|
|
475
|
+
)
|
|
476
|
+
nodes: SheetList[PhysicalNodeType] | None = Field(
|
|
469
477
|
None, alias="Nodes", description="Contains the definition of the node types."
|
|
470
478
|
)
|
|
471
479
|
|
|
472
480
|
@model_validator(mode="after")
|
|
473
|
-
def set_neat_id(self) -> "
|
|
481
|
+
def set_neat_id(self) -> "PhysicalDataModel":
|
|
474
482
|
namespace = self.metadata.namespace
|
|
475
483
|
|
|
476
484
|
for view in self.views:
|
|
@@ -494,25 +502,25 @@ class DMSRules(BaseVerifiedDataModel):
|
|
|
494
502
|
for property_ in self.properties:
|
|
495
503
|
property_.neatId = namespace[f"{property_.view.suffix}/{property_.view_property}"]
|
|
496
504
|
|
|
497
|
-
def
|
|
505
|
+
def sync_with_conceptual_data_model(self, conceptual_data_model: "ConceptualDataModel") -> None:
|
|
498
506
|
# Sync at the metadata level
|
|
499
|
-
if
|
|
500
|
-
self.metadata.
|
|
507
|
+
if conceptual_data_model.metadata.physical == self.metadata.identifier:
|
|
508
|
+
self.metadata.conceptual = conceptual_data_model.metadata.identifier
|
|
501
509
|
else:
|
|
502
510
|
# if models are not linked to start with, we skip
|
|
503
511
|
return None
|
|
504
512
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
for neat_id, prop in
|
|
508
|
-
if prop.physical in
|
|
509
|
-
|
|
513
|
+
conceptual_properties_by_neat_id = {prop.neatId: prop for prop in conceptual_data_model.properties}
|
|
514
|
+
physical_properties_by_neat_id = {prop.neatId: prop for prop in self.properties}
|
|
515
|
+
for neat_id, prop in conceptual_properties_by_neat_id.items():
|
|
516
|
+
if prop.physical in physical_properties_by_neat_id:
|
|
517
|
+
physical_properties_by_neat_id[prop.physical].conceptual = neat_id
|
|
510
518
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
for neat_id, class_ in
|
|
514
|
-
if class_.physical in
|
|
515
|
-
|
|
519
|
+
classes_by_neat_id = {cls.neatId: cls for cls in conceptual_data_model.concepts}
|
|
520
|
+
views_by_neat_id = {view.neatId: view for view in self.views}
|
|
521
|
+
for neat_id, class_ in classes_by_neat_id.items():
|
|
522
|
+
if class_.physical in views_by_neat_id:
|
|
523
|
+
views_by_neat_id[class_.physical].conceptual = neat_id
|
|
516
524
|
|
|
517
525
|
def as_schema(self, instance_space: str | None = None, remove_cdf_spaces: bool = False) -> DMSSchema:
|
|
518
526
|
from ._exporter import _DMSExporter
|
|
@@ -521,12 +529,12 @@ class DMSRules(BaseVerifiedDataModel):
|
|
|
521
529
|
|
|
522
530
|
@classmethod
|
|
523
531
|
def display_type_name(cls) -> str:
|
|
524
|
-
return "
|
|
532
|
+
return "VerifiedPhysicalModel"
|
|
525
533
|
|
|
526
534
|
def _repr_html_(self) -> str:
|
|
527
535
|
summary = {
|
|
528
|
-
"
|
|
529
|
-
"intended for": "
|
|
536
|
+
"level": self.metadata.level,
|
|
537
|
+
"intended for": "Data Engineer",
|
|
530
538
|
"name": self.metadata.name,
|
|
531
539
|
"space": self.metadata.space,
|
|
532
540
|
"external_id": self.metadata.external_id,
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
from ._base import
|
|
1
|
+
from ._base import DataModelTransformer, VerifiedDataModelTransformer
|
|
2
2
|
from ._converters import (
|
|
3
|
-
AddClassImplements,
|
|
4
3
|
AddCogniteProperties,
|
|
4
|
+
AddConceptImplements,
|
|
5
5
|
ChangeViewPrefix,
|
|
6
6
|
ClassicPrepareCore,
|
|
7
|
+
ConceptualToPhysical,
|
|
7
8
|
ConversionTransformer,
|
|
8
|
-
|
|
9
|
-
DMSToInformation,
|
|
9
|
+
ConvertToDataModel,
|
|
10
10
|
DropModelViews,
|
|
11
11
|
IncludeReferenced,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
MergeConceptualDataModels,
|
|
13
|
+
MergePhysicalDataModels,
|
|
14
|
+
PhysicalToConceptual,
|
|
15
15
|
PrefixEntities,
|
|
16
16
|
SetIDDMSModel,
|
|
17
17
|
StandardizeNaming,
|
|
18
18
|
StandardizeSpaceAndVersion,
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
SubsetConceptualDataModel,
|
|
20
|
+
SubsetPhysicalDataModel,
|
|
21
21
|
ToCompliantEntities,
|
|
22
22
|
ToDataProductModel,
|
|
23
23
|
ToDMSCompliantEntities,
|
|
@@ -25,40 +25,44 @@ from ._converters import (
|
|
|
25
25
|
ToExtensionModel,
|
|
26
26
|
ToSolutionModel,
|
|
27
27
|
)
|
|
28
|
-
from ._mapping import AsParentPropertyId, MapOneToOne,
|
|
29
|
-
from ._verification import
|
|
28
|
+
from ._mapping import AsParentPropertyId, MapOneToOne, PhysicalDataModelMapper
|
|
29
|
+
from ._verification import (
|
|
30
|
+
VerifyAnyDataModel,
|
|
31
|
+
VerifyConceptualDataModel,
|
|
32
|
+
VerifyPhysicalDataModel,
|
|
33
|
+
)
|
|
30
34
|
|
|
31
35
|
__all__ = [
|
|
32
|
-
"AddClassImplements",
|
|
33
36
|
"AddCogniteProperties",
|
|
37
|
+
"AddConceptImplements",
|
|
34
38
|
"AsParentPropertyId",
|
|
35
39
|
"ChangeViewPrefix",
|
|
36
40
|
"ClassicPrepareCore",
|
|
41
|
+
"ConceptualToPhysical",
|
|
37
42
|
"ConversionTransformer",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
43
|
+
"ConvertToDataModel",
|
|
44
|
+
"DataModelTransformer",
|
|
40
45
|
"DropModelViews",
|
|
41
46
|
"IncludeReferenced",
|
|
42
|
-
"InformationToDMS",
|
|
43
47
|
"MapOneToOne",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
48
|
+
"MergeConceptualDataModels",
|
|
49
|
+
"MergePhysicalDataModels",
|
|
50
|
+
"PhysicalDataModelMapper",
|
|
51
|
+
"PhysicalToConceptual",
|
|
46
52
|
"PrefixEntities",
|
|
47
|
-
"RuleMapper",
|
|
48
|
-
"RulesTransformer",
|
|
49
53
|
"SetIDDMSModel",
|
|
50
54
|
"StandardizeNaming",
|
|
51
55
|
"StandardizeSpaceAndVersion",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
56
|
+
"SubsetConceptualDataModel",
|
|
57
|
+
"SubsetPhysicalDataModel",
|
|
54
58
|
"ToCompliantEntities",
|
|
55
59
|
"ToDMSCompliantEntities",
|
|
56
60
|
"ToDataProductModel",
|
|
57
61
|
"ToEnterpriseModel",
|
|
58
62
|
"ToExtensionModel",
|
|
59
63
|
"ToSolutionModel",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
+
"VerifiedDataModelTransformer",
|
|
65
|
+
"VerifyAnyDataModel",
|
|
66
|
+
"VerifyConceptualDataModel",
|
|
67
|
+
"VerifyPhysicalDataModel",
|
|
64
68
|
]
|
|
@@ -5,25 +5,29 @@ from types import UnionType
|
|
|
5
5
|
from typing import Generic, TypeVar, Union, get_args, get_origin
|
|
6
6
|
|
|
7
7
|
from cognite.neat.core._constants import DEFAULT_NAMESPACE
|
|
8
|
-
from cognite.neat.core._data_model._shared import
|
|
8
|
+
from cognite.neat.core._data_model._shared import (
|
|
9
|
+
DataModel,
|
|
10
|
+
ImportedDataModel,
|
|
11
|
+
VerifiedDataModel,
|
|
12
|
+
)
|
|
9
13
|
from cognite.neat.core._data_model.models import (
|
|
10
|
-
DMSInputRules,
|
|
11
14
|
UnverifiedConceptualDataModel,
|
|
15
|
+
UnverifiedPhysicalDataModel,
|
|
12
16
|
)
|
|
13
17
|
from cognite.neat.core._store._provenance import Agent as ProvenanceAgent
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
T_VerifiedIn = TypeVar("T_VerifiedIn", bound=
|
|
18
|
-
T_VerifiedOut = TypeVar("T_VerifiedOut", bound=
|
|
19
|
+
T_DataModelIn = TypeVar("T_DataModelIn", bound=DataModel)
|
|
20
|
+
T_DataModelOut = TypeVar("T_DataModelOut", bound=DataModel)
|
|
21
|
+
T_VerifiedIn = TypeVar("T_VerifiedIn", bound=VerifiedDataModel)
|
|
22
|
+
T_VerifiedOut = TypeVar("T_VerifiedOut", bound=VerifiedDataModel)
|
|
19
23
|
|
|
20
24
|
|
|
21
|
-
class
|
|
22
|
-
"""This is the base class for all
|
|
25
|
+
class DataModelTransformer(ABC, Generic[T_DataModelIn, T_DataModelOut]):
|
|
26
|
+
"""This is the base class for all data model transformers."""
|
|
23
27
|
|
|
24
28
|
@abstractmethod
|
|
25
|
-
def transform(self,
|
|
26
|
-
"""Transform the input
|
|
29
|
+
def transform(self, data_model: T_DataModelIn) -> T_DataModelOut:
|
|
30
|
+
"""Transform the input data model into the output data model."""
|
|
27
31
|
raise NotImplementedError()
|
|
28
32
|
|
|
29
33
|
@property
|
|
@@ -36,15 +40,15 @@ class RulesTransformer(ABC, Generic[T_RulesIn, T_RulesOut]):
|
|
|
36
40
|
"""Get the description of the transformer."""
|
|
37
41
|
return "MISSING DESCRIPTION"
|
|
38
42
|
|
|
39
|
-
def is_valid_input(self,
|
|
40
|
-
"""Check if the input
|
|
43
|
+
def is_valid_input(self, data_model: T_DataModelIn) -> bool:
|
|
44
|
+
"""Check if the input data model is valid."""
|
|
41
45
|
types = self.transform_type_hint()
|
|
42
46
|
for type_ in types:
|
|
43
|
-
if get_origin(type_) is
|
|
47
|
+
if get_origin(type_) is ImportedDataModel:
|
|
44
48
|
inner = get_args(type_)[0]
|
|
45
|
-
if isinstance(
|
|
49
|
+
if isinstance(data_model, ImportedDataModel) and isinstance(data_model.unverified_data_model, inner):
|
|
46
50
|
return True
|
|
47
|
-
elif isinstance(
|
|
51
|
+
elif isinstance(data_model, type_):
|
|
48
52
|
return True
|
|
49
53
|
return False
|
|
50
54
|
|
|
@@ -53,7 +57,7 @@ class RulesTransformer(ABC, Generic[T_RulesIn, T_RulesOut]):
|
|
|
53
57
|
def transform_type_hint(cls) -> tuple[type, ...]:
|
|
54
58
|
# This is an expensive operation, so we cache the result
|
|
55
59
|
signature = inspect.signature(cls.transform)
|
|
56
|
-
annotation = signature.parameters["
|
|
60
|
+
annotation = signature.parameters["data_model"].annotation
|
|
57
61
|
if isinstance(annotation, TypeVar):
|
|
58
62
|
if annotation.__bound__ is None:
|
|
59
63
|
raise TypeError(f"TypeVar {annotation} must be bound to a type.")
|
|
@@ -62,11 +66,14 @@ class RulesTransformer(ABC, Generic[T_RulesIn, T_RulesOut]):
|
|
|
62
66
|
if get_origin(annotation) in [UnionType, Union]:
|
|
63
67
|
return get_args(annotation)
|
|
64
68
|
|
|
65
|
-
if get_origin(annotation) is
|
|
66
|
-
# Hardcoded for now, as we only have two types of
|
|
67
|
-
return
|
|
69
|
+
if get_origin(annotation) is ImportedDataModel and isinstance(get_args(annotation)[0], TypeVar):
|
|
70
|
+
# Hardcoded for now, as we only have two types of imported data models
|
|
71
|
+
return (
|
|
72
|
+
ImportedDataModel[UnverifiedPhysicalDataModel],
|
|
73
|
+
ImportedDataModel[UnverifiedConceptualDataModel],
|
|
74
|
+
)
|
|
68
75
|
|
|
69
76
|
return (annotation,)
|
|
70
77
|
|
|
71
78
|
|
|
72
|
-
class
|
|
79
|
+
class VerifiedDataModelTransformer(DataModelTransformer[T_VerifiedIn, T_VerifiedOut], ABC): ...
|