cognite-neat 0.77.2__py3-none-any.whl → 0.77.4__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/rules/analysis/_information_rules.py +2 -12
- cognite/neat/rules/exporters/_rules2excel.py +78 -89
- cognite/neat/rules/importers/_dms2rules.py +24 -11
- cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +1 -0
- cognite/neat/rules/importers/_spreadsheet2rules.py +21 -8
- cognite/neat/rules/issues/dms.py +19 -0
- cognite/neat/rules/issues/importing.py +16 -0
- cognite/neat/rules/issues/spreadsheet.py +60 -5
- cognite/neat/rules/models/_base.py +6 -0
- cognite/neat/rules/models/dms/_converter.py +25 -19
- cognite/neat/rules/models/dms/_exporter.py +2 -1
- cognite/neat/rules/models/dms/_rules.py +3 -2
- cognite/neat/rules/models/dms/_rules_input.py +4 -11
- cognite/neat/rules/models/dms/_schema.py +41 -5
- cognite/neat/rules/models/dms/_serializer.py +1 -1
- cognite/neat/rules/models/dms/_validation.py +27 -60
- cognite/neat/rules/models/information/__init__.py +8 -1
- cognite/neat/rules/models/information/_converter.py +27 -19
- cognite/neat/rules/models/information/_rules.py +41 -82
- cognite/neat/rules/models/information/_rules_input.py +266 -0
- cognite/neat/rules/models/information/_serializer.py +85 -0
- cognite/neat/rules/models/information/_validation.py +164 -0
- cognite/neat/utils/cdf.py +35 -0
- cognite/neat/workflows/steps/lib/current/rules_exporter.py +30 -7
- cognite/neat/workflows/steps/lib/current/rules_importer.py +21 -2
- {cognite_neat-0.77.2.dist-info → cognite_neat-0.77.4.dist-info}/METADATA +1 -1
- {cognite_neat-0.77.2.dist-info → cognite_neat-0.77.4.dist-info}/RECORD +31 -28
- {cognite_neat-0.77.2.dist-info → cognite_neat-0.77.4.dist-info}/LICENSE +0 -0
- {cognite_neat-0.77.2.dist-info → cognite_neat-0.77.4.dist-info}/WHEEL +0 -0
- {cognite_neat-0.77.2.dist-info → cognite_neat-0.77.4.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import warnings
|
|
2
|
-
from
|
|
3
|
-
from typing import cast
|
|
2
|
+
from typing import TYPE_CHECKING, cast
|
|
4
3
|
|
|
5
4
|
from rdflib import Namespace
|
|
6
5
|
|
|
@@ -20,7 +19,10 @@ from cognite.neat.rules.models.entities import (
|
|
|
20
19
|
)
|
|
21
20
|
from cognite.neat.rules.models.information._rules import InformationRules
|
|
22
21
|
|
|
23
|
-
from ._rules import DMSProperty, DMSRules, DMSView
|
|
22
|
+
from ._rules import DMSMetadata, DMSProperty, DMSRules, DMSView
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from cognite.neat.rules.models.information._rules import InformationMetadata
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
class _DMSRulesConverter:
|
|
@@ -32,31 +34,16 @@ class _DMSRulesConverter:
|
|
|
32
34
|
|
|
33
35
|
def as_information_architect_rules(
|
|
34
36
|
self,
|
|
35
|
-
created: datetime | None = None,
|
|
36
|
-
updated: datetime | None = None,
|
|
37
|
-
name: str | None = None,
|
|
38
|
-
namespace: Namespace | None = None,
|
|
39
37
|
) -> "InformationRules":
|
|
40
38
|
from cognite.neat.rules.models.information._rules import (
|
|
41
39
|
InformationClass,
|
|
42
|
-
InformationMetadata,
|
|
43
40
|
InformationProperty,
|
|
44
41
|
InformationRules,
|
|
45
42
|
)
|
|
46
43
|
|
|
47
44
|
dms = self.dms.metadata
|
|
48
|
-
prefix = dms.space
|
|
49
45
|
|
|
50
|
-
metadata =
|
|
51
|
-
schema_=dms.schema_,
|
|
52
|
-
prefix=prefix,
|
|
53
|
-
namespace=namespace or Namespace(f"https://purl.orgl/neat/{prefix}/"),
|
|
54
|
-
version=dms.version,
|
|
55
|
-
name=name or dms.name or "Missing name",
|
|
56
|
-
creator=dms.creator,
|
|
57
|
-
created=dms.created or created or datetime.now(),
|
|
58
|
-
updated=dms.updated or updated or datetime.now(),
|
|
59
|
-
)
|
|
46
|
+
metadata = self._convert_metadata_to_info(dms)
|
|
60
47
|
|
|
61
48
|
classes = [
|
|
62
49
|
InformationClass(
|
|
@@ -111,6 +98,25 @@ class _DMSRulesConverter:
|
|
|
111
98
|
reference=self.dms.reference.as_information_architect_rules() if self.dms.reference else None,
|
|
112
99
|
)
|
|
113
100
|
|
|
101
|
+
@classmethod
|
|
102
|
+
def _convert_metadata_to_info(cls, metadata: DMSMetadata) -> "InformationMetadata":
|
|
103
|
+
from cognite.neat.rules.models.information._rules import InformationMetadata
|
|
104
|
+
|
|
105
|
+
prefix = metadata.space
|
|
106
|
+
return InformationMetadata(
|
|
107
|
+
schema_=metadata.schema_,
|
|
108
|
+
data_model_type=metadata.data_model_type,
|
|
109
|
+
extension=metadata.extension,
|
|
110
|
+
prefix=prefix,
|
|
111
|
+
namespace=Namespace(f"https://purl.orgl/neat/{prefix}/"),
|
|
112
|
+
version=metadata.version,
|
|
113
|
+
description=metadata.description,
|
|
114
|
+
name=metadata.name or metadata.external_id,
|
|
115
|
+
creator=metadata.creator,
|
|
116
|
+
created=metadata.created,
|
|
117
|
+
updated=metadata.updated,
|
|
118
|
+
)
|
|
119
|
+
|
|
114
120
|
@classmethod
|
|
115
121
|
def _get_class_reference(cls, view: DMSView) -> ReferenceEntity | None:
|
|
116
122
|
parents_other_namespace = [parent for parent in view.implements or [] if parent.prefix != view.class_.prefix]
|
|
@@ -58,7 +58,7 @@ _DEFAULT_VERSION = "1"
|
|
|
58
58
|
|
|
59
59
|
class DMSMetadata(BaseMetadata):
|
|
60
60
|
role: ClassVar[RoleTypes] = RoleTypes.dms_architect
|
|
61
|
-
data_model_type: DataModelType = Field(DataModelType.
|
|
61
|
+
data_model_type: DataModelType = Field(DataModelType.enterprise, alias="dataModelType")
|
|
62
62
|
schema_: SchemaCompleteness = Field(alias="schema")
|
|
63
63
|
extension: ExtensionCategory = ExtensionCategory.addition
|
|
64
64
|
space: ExternalIdType
|
|
@@ -146,10 +146,11 @@ class DMSMetadata(BaseMetadata):
|
|
|
146
146
|
return description, creator
|
|
147
147
|
|
|
148
148
|
@classmethod
|
|
149
|
-
def from_data_model(cls, data_model: dm.DataModelApply) -> "DMSMetadata":
|
|
149
|
+
def from_data_model(cls, data_model: dm.DataModelApply, has_reference: bool) -> "DMSMetadata":
|
|
150
150
|
description, creator = cls._get_description_and_creator(data_model.description)
|
|
151
151
|
return cls(
|
|
152
152
|
schema_=SchemaCompleteness.complete,
|
|
153
|
+
data_model_type=DataModelType.solution if has_reference else DataModelType.enterprise,
|
|
153
154
|
space=data_model.space,
|
|
154
155
|
name=data_model.name or None,
|
|
155
156
|
description=description,
|
|
@@ -3,9 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from typing import Any, Literal, cast, overload
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
from cognite.neat.rules.models._base import DataModelType, ExtensionCategory, SchemaCompleteness
|
|
6
|
+
from cognite.neat.rules.models._base import DataModelType, ExtensionCategory, SchemaCompleteness, _add_alias
|
|
9
7
|
from cognite.neat.rules.models.data_types import DataType
|
|
10
8
|
from cognite.neat.rules.models.entities import (
|
|
11
9
|
ClassEntity,
|
|
@@ -44,8 +42,9 @@ class DMSMetadataInput:
|
|
|
44
42
|
external_id=data.get("external_id"), # type: ignore[arg-type]
|
|
45
43
|
creator=data.get("creator"), # type: ignore[arg-type]
|
|
46
44
|
version=data.get("version"), # type: ignore[arg-type]
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
# safeguard from empty cell, i.e. if key provided by value None
|
|
46
|
+
extension=data.get("extension", "addition") or "addition",
|
|
47
|
+
data_model_type=data.get("data_model_type", "solution") or "solution",
|
|
49
48
|
name=data.get("name"),
|
|
50
49
|
description=data.get("description"),
|
|
51
50
|
created=data.get("created"),
|
|
@@ -355,9 +354,3 @@ class DMSRulesInput:
|
|
|
355
354
|
Last=last,
|
|
356
355
|
Reference=reference,
|
|
357
356
|
)
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
def _add_alias(data: dict[str, Any], base_model: type[BaseModel]) -> None:
|
|
361
|
-
for field_name, field_ in base_model.model_fields.items():
|
|
362
|
-
if field_name not in data and field_.alias in data:
|
|
363
|
-
data[field_name] = data[field_.alias]
|
|
@@ -12,6 +12,7 @@ from cognite.client import CogniteClient
|
|
|
12
12
|
from cognite.client import data_modeling as dm
|
|
13
13
|
from cognite.client.data_classes import DatabaseWrite, DatabaseWriteList, TransformationWrite, TransformationWriteList
|
|
14
14
|
from cognite.client.data_classes.data_modeling import ViewApply
|
|
15
|
+
from cognite.client.data_classes.data_modeling.views import ReverseDirectRelation
|
|
15
16
|
from cognite.client.data_classes.transformations.common import Edges, EdgeType, Nodes, ViewInfo
|
|
16
17
|
|
|
17
18
|
from cognite.neat.rules import issues
|
|
@@ -28,6 +29,7 @@ from cognite.neat.rules.issues.dms import (
|
|
|
28
29
|
MissingSourceViewError,
|
|
29
30
|
MissingSpaceError,
|
|
30
31
|
MissingViewError,
|
|
32
|
+
MissingViewInModelWarning,
|
|
31
33
|
)
|
|
32
34
|
from cognite.neat.rules.models.data_types import _DATA_TYPE_BY_DMS_TYPE
|
|
33
35
|
from cognite.neat.utils.cdf_classes import (
|
|
@@ -146,8 +148,26 @@ class DMSSchema:
|
|
|
146
148
|
space_write = space_read.as_write()
|
|
147
149
|
|
|
148
150
|
view_loader = ViewLoader(client)
|
|
149
|
-
|
|
151
|
+
|
|
150
152
|
existing_view_ids = set(views.as_ids())
|
|
153
|
+
|
|
154
|
+
# We need to include all views the edges/direct relations are pointing to have a complete schema.
|
|
155
|
+
connection_referenced_view_ids: set[dm.ViewId] = set()
|
|
156
|
+
for view in views:
|
|
157
|
+
connection_referenced_view_ids |= cls._connection_references(view)
|
|
158
|
+
connection_referenced_view_ids = connection_referenced_view_ids - existing_view_ids
|
|
159
|
+
if connection_referenced_view_ids:
|
|
160
|
+
warnings.warn(
|
|
161
|
+
MissingViewInModelWarning(data_model.as_id(), connection_referenced_view_ids), UserWarning, stacklevel=2
|
|
162
|
+
)
|
|
163
|
+
connection_referenced_views = view_loader.retrieve(list(connection_referenced_view_ids))
|
|
164
|
+
if failed := connection_referenced_view_ids - set(connection_referenced_views.as_ids()):
|
|
165
|
+
warnings.warn(
|
|
166
|
+
issues.importing.FailedImportWarning({repr(v) for v in failed}), UserWarning, stacklevel=2
|
|
167
|
+
)
|
|
168
|
+
views.extend(connection_referenced_views)
|
|
169
|
+
|
|
170
|
+
# We need to include parent views in the schema to make sure that the schema is valid.
|
|
151
171
|
parent_view_ids = {parent for view in views for parent in view.implements or []}
|
|
152
172
|
parents = view_loader.retrieve_all_parents(list(parent_view_ids - existing_view_ids))
|
|
153
173
|
views.extend([parent for parent in parents if parent.as_id() not in existing_view_ids])
|
|
@@ -203,6 +223,21 @@ class DMSSchema:
|
|
|
203
223
|
reference=ref_schema,
|
|
204
224
|
)
|
|
205
225
|
|
|
226
|
+
@classmethod
|
|
227
|
+
def _connection_references(cls, view: dm.View) -> set[dm.ViewId]:
|
|
228
|
+
view_ids: set[dm.ViewId] = set()
|
|
229
|
+
for prop in (view.properties or {}).values():
|
|
230
|
+
if isinstance(prop, dm.MappedProperty) and isinstance(prop.type, dm.DirectRelation):
|
|
231
|
+
if prop.source:
|
|
232
|
+
view_ids.add(prop.source)
|
|
233
|
+
elif isinstance(prop, dm.EdgeConnection):
|
|
234
|
+
view_ids.add(prop.source)
|
|
235
|
+
if prop.edge_source:
|
|
236
|
+
view_ids.add(prop.edge_source)
|
|
237
|
+
elif isinstance(prop, ReverseDirectRelation):
|
|
238
|
+
view_ids.add(prop.source)
|
|
239
|
+
return view_ids
|
|
240
|
+
|
|
206
241
|
@classmethod
|
|
207
242
|
def from_directory(cls, directory: str | Path) -> Self:
|
|
208
243
|
"""Load a schema from a directory containing YAML files.
|
|
@@ -481,10 +516,11 @@ class DMSSchema:
|
|
|
481
516
|
defined_spaces = self.spaces.copy()
|
|
482
517
|
defined_containers = self.containers.copy()
|
|
483
518
|
defined_views = self.views.copy()
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
519
|
+
for other_schema in [self.reference, self.last]:
|
|
520
|
+
if other_schema:
|
|
521
|
+
defined_spaces |= other_schema.spaces
|
|
522
|
+
defined_containers |= other_schema.containers
|
|
523
|
+
defined_views |= other_schema.views
|
|
488
524
|
|
|
489
525
|
for container in self.containers.values():
|
|
490
526
|
if container.space not in defined_spaces:
|
|
@@ -37,7 +37,7 @@ class _DMSRulesSerializer:
|
|
|
37
37
|
DMSProperty.model_fields[field].alias or field for field in self.properties_fields
|
|
38
38
|
]
|
|
39
39
|
self.views_fields = [DMSView.model_fields[field].alias or field for field in self.views_fields]
|
|
40
|
-
self.
|
|
40
|
+
self.containers_fields = [
|
|
41
41
|
DMSContainer.model_fields[field].alias or field for field in self.containers_fields
|
|
42
42
|
]
|
|
43
43
|
self.prop_view = DMSProperty.model_fields[self.prop_view].alias or self.prop_view
|
|
@@ -5,12 +5,13 @@ from cognite.client import data_modeling as dm
|
|
|
5
5
|
|
|
6
6
|
from cognite.neat.rules import issues
|
|
7
7
|
from cognite.neat.rules.issues import IssueList
|
|
8
|
-
from cognite.neat.rules.models._base import ExtensionCategory, SchemaCompleteness
|
|
8
|
+
from cognite.neat.rules.models._base import DataModelType, ExtensionCategory, SchemaCompleteness
|
|
9
9
|
from cognite.neat.rules.models.data_types import DataType
|
|
10
10
|
from cognite.neat.rules.models.entities import ContainerEntity
|
|
11
11
|
from cognite.neat.rules.models.wrapped_entities import RawFilter
|
|
12
12
|
|
|
13
13
|
from ._rules import DMSProperty, DMSRules
|
|
14
|
+
from ._schema import DMSSchema
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class DMSPostValidation:
|
|
@@ -26,12 +27,17 @@ class DMSPostValidation:
|
|
|
26
27
|
self.issue_list = IssueList()
|
|
27
28
|
|
|
28
29
|
def validate(self) -> IssueList:
|
|
29
|
-
self.
|
|
30
|
+
self._validate_raw_filter()
|
|
30
31
|
self._consistent_container_properties()
|
|
32
|
+
|
|
31
33
|
self._referenced_views_and_containers_are_existing()
|
|
32
|
-
self.
|
|
33
|
-
|
|
34
|
-
self.
|
|
34
|
+
if self.metadata.schema_ is SchemaCompleteness.extended:
|
|
35
|
+
self._validate_extension()
|
|
36
|
+
if self.metadata.schema_ is SchemaCompleteness.partial:
|
|
37
|
+
return self.issue_list
|
|
38
|
+
dms_schema = self.rules.as_schema()
|
|
39
|
+
self.issue_list.extend(dms_schema.validate())
|
|
40
|
+
self._validate_performance(dms_schema)
|
|
35
41
|
return self.issue_list
|
|
36
42
|
|
|
37
43
|
def _consistent_container_properties(self) -> None:
|
|
@@ -106,8 +112,9 @@ class DMSPostValidation:
|
|
|
106
112
|
self.issue_list.extend(errors)
|
|
107
113
|
|
|
108
114
|
def _referenced_views_and_containers_are_existing(self) -> None:
|
|
109
|
-
# There two checks are done in the same method to raise all the errors at once.
|
|
110
115
|
defined_views = {view.view.as_id() for view in self.views}
|
|
116
|
+
if self.metadata.schema_ is SchemaCompleteness.extended and self.rules.last:
|
|
117
|
+
defined_views |= {view.view.as_id() for view in self.rules.last.views}
|
|
111
118
|
|
|
112
119
|
errors: list[issues.NeatValidationError] = []
|
|
113
120
|
for prop_no, prop in enumerate(self.properties):
|
|
@@ -125,6 +132,11 @@ class DMSPostValidation:
|
|
|
125
132
|
)
|
|
126
133
|
if self.metadata.schema_ is SchemaCompleteness.complete:
|
|
127
134
|
defined_containers = {container.container.as_id() for container in self.containers or []}
|
|
135
|
+
if self.metadata.data_model_type == DataModelType.solution and self.rules.reference:
|
|
136
|
+
defined_containers |= {
|
|
137
|
+
container.container.as_id() for container in self.rules.reference.containers or []
|
|
138
|
+
}
|
|
139
|
+
|
|
128
140
|
for prop_no, prop in enumerate(self.properties):
|
|
129
141
|
if prop.container and (container_id := prop.container.as_id()) not in defined_containers:
|
|
130
142
|
errors.append(
|
|
@@ -157,19 +169,16 @@ class DMSPostValidation:
|
|
|
157
169
|
def _validate_extension(self) -> None:
|
|
158
170
|
if self.metadata.schema_ is not SchemaCompleteness.extended:
|
|
159
171
|
return None
|
|
160
|
-
if not self.rules.
|
|
161
|
-
raise ValueError("The schema is set to 'extended', but no
|
|
162
|
-
is_solution = self.metadata.space != self.rules.reference.metadata.space
|
|
163
|
-
if is_solution:
|
|
164
|
-
return None
|
|
172
|
+
if not self.rules.last:
|
|
173
|
+
raise ValueError("The schema is set to 'extended', but no last rules are provided to validate against")
|
|
165
174
|
if self.metadata.extension is ExtensionCategory.rebuild:
|
|
166
175
|
# Everything is allowed
|
|
167
176
|
return None
|
|
168
|
-
# Is an extension of an existing model.
|
|
169
177
|
user_schema = self.rules.as_schema()
|
|
170
|
-
ref_schema = self.rules.reference.as_schema()
|
|
171
178
|
new_containers = user_schema.containers.copy()
|
|
172
|
-
|
|
179
|
+
|
|
180
|
+
last_schema = self.rules.last.as_schema()
|
|
181
|
+
existing_containers = last_schema.containers.copy()
|
|
173
182
|
|
|
174
183
|
for container_id, container in new_containers.items():
|
|
175
184
|
existing_container = existing_containers.get(container_id)
|
|
@@ -189,14 +198,12 @@ class DMSPostValidation:
|
|
|
189
198
|
)
|
|
190
199
|
)
|
|
191
200
|
|
|
192
|
-
if self.metadata.extension is ExtensionCategory.reshape
|
|
193
|
-
return None
|
|
194
|
-
elif self.metadata.extension is ExtensionCategory.reshape:
|
|
201
|
+
if self.metadata.extension is ExtensionCategory.reshape:
|
|
195
202
|
# Reshape allows changes to views
|
|
196
203
|
return None
|
|
197
204
|
|
|
198
205
|
new_views = user_schema.views.copy()
|
|
199
|
-
existing_views =
|
|
206
|
+
existing_views = last_schema.views.copy()
|
|
200
207
|
for view_id, view in new_views.items():
|
|
201
208
|
existing_view = existing_views.get(view_id)
|
|
202
209
|
if not existing_view or existing_view == view:
|
|
@@ -213,14 +220,7 @@ class DMSPostValidation:
|
|
|
213
220
|
)
|
|
214
221
|
)
|
|
215
222
|
|
|
216
|
-
def _validate_performance(self) -> None:
|
|
217
|
-
# we can only validate performance on complete schemas due to the need
|
|
218
|
-
# to access all the container mappings
|
|
219
|
-
if self.metadata.schema_ is not SchemaCompleteness.complete:
|
|
220
|
-
return None
|
|
221
|
-
|
|
222
|
-
dms_schema = self.rules.as_schema()
|
|
223
|
-
|
|
223
|
+
def _validate_performance(self, dms_schema: DMSSchema) -> None:
|
|
224
224
|
for view_id, view in dms_schema.views.items():
|
|
225
225
|
mapped_containers = dms_schema._get_mapped_container_from_view(view_id)
|
|
226
226
|
|
|
@@ -243,7 +243,7 @@ class DMSPostValidation:
|
|
|
243
243
|
)
|
|
244
244
|
)
|
|
245
245
|
|
|
246
|
-
def
|
|
246
|
+
def _validate_raw_filter(self) -> None:
|
|
247
247
|
for view in self.views:
|
|
248
248
|
if view.filter_ and isinstance(view.filter_, RawFilter):
|
|
249
249
|
self.issue_list.append(
|
|
@@ -264,36 +264,3 @@ class DMSPostValidation:
|
|
|
264
264
|
existing_properties = existing_dumped.get("properties", {})
|
|
265
265
|
changed_properties = [prop for prop in new_properties if new_properties[prop] != existing_properties.get(prop)]
|
|
266
266
|
return changed_attributes, changed_properties
|
|
267
|
-
|
|
268
|
-
def _validate_schema(self) -> None:
|
|
269
|
-
if self.metadata.schema_ is SchemaCompleteness.partial:
|
|
270
|
-
return None
|
|
271
|
-
elif self.metadata.schema_ is SchemaCompleteness.complete:
|
|
272
|
-
rules: DMSRules = self.rules
|
|
273
|
-
elif self.metadata.schema_ is SchemaCompleteness.extended:
|
|
274
|
-
if not self.rules.reference:
|
|
275
|
-
raise ValueError(
|
|
276
|
-
"The schema is set to 'extended', but no reference rules are provided to validate against"
|
|
277
|
-
)
|
|
278
|
-
# This is an extension of the reference rules, we need to merge the two
|
|
279
|
-
rules = self.rules.model_copy(deep=True)
|
|
280
|
-
rules.properties.extend(self.rules.reference.properties.data)
|
|
281
|
-
existing_views = {view.view.as_id() for view in rules.views}
|
|
282
|
-
rules.views.extend([view for view in self.rules.reference.views if view.view.as_id() not in existing_views])
|
|
283
|
-
if rules.containers and self.rules.reference.containers:
|
|
284
|
-
existing_containers = {container.container.as_id() for container in rules.containers.data}
|
|
285
|
-
rules.containers.extend(
|
|
286
|
-
[
|
|
287
|
-
container
|
|
288
|
-
for container in self.rules.reference.containers
|
|
289
|
-
if container.container.as_id() not in existing_containers
|
|
290
|
-
]
|
|
291
|
-
)
|
|
292
|
-
elif not rules.containers and self.rules.reference.containers:
|
|
293
|
-
rules.containers = self.rules.reference.containers
|
|
294
|
-
else:
|
|
295
|
-
raise ValueError("Unknown schema completeness")
|
|
296
|
-
|
|
297
|
-
schema = rules.as_schema()
|
|
298
|
-
errors = schema.validate()
|
|
299
|
-
self.issue_list.extend(errors)
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
from ._rules import InformationClass, InformationMetadata, InformationProperty, InformationRules
|
|
2
|
+
from ._rules_input import InformationRulesInput
|
|
2
3
|
|
|
3
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"InformationRules",
|
|
6
|
+
"InformationMetadata",
|
|
7
|
+
"InformationClass",
|
|
8
|
+
"InformationProperty",
|
|
9
|
+
"InformationRulesInput",
|
|
10
|
+
]
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from collections import defaultdict
|
|
3
|
-
from
|
|
4
|
-
from typing import Literal
|
|
3
|
+
from typing import TYPE_CHECKING, Literal
|
|
5
4
|
|
|
6
5
|
from cognite.neat.rules.models._base import (
|
|
7
|
-
DataModelType,
|
|
8
6
|
SheetList,
|
|
9
7
|
)
|
|
10
8
|
from cognite.neat.rules.models.data_types import DataType
|
|
11
|
-
from cognite.neat.rules.models.dms._rules import DMSProperty, DMSRules, DMSView
|
|
12
9
|
from cognite.neat.rules.models.domain import DomainRules
|
|
13
10
|
from cognite.neat.rules.models.entities import (
|
|
14
11
|
ClassEntity,
|
|
@@ -22,6 +19,9 @@ from cognite.neat.rules.models.entities import (
|
|
|
22
19
|
|
|
23
20
|
from ._rules import InformationClass, InformationMetadata, InformationProperty, InformationRules
|
|
24
21
|
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from cognite.neat.rules.models.dms._rules import DMSMetadata, DMSProperty, DMSRules
|
|
24
|
+
|
|
25
25
|
|
|
26
26
|
class _InformationRulesConverter:
|
|
27
27
|
def __init__(self, information: InformationRules):
|
|
@@ -30,30 +30,18 @@ class _InformationRulesConverter:
|
|
|
30
30
|
def as_domain_rules(self) -> DomainRules:
|
|
31
31
|
raise NotImplementedError("DomainRules not implemented yet")
|
|
32
32
|
|
|
33
|
-
def as_dms_architect_rules(self
|
|
33
|
+
def as_dms_architect_rules(self) -> "DMSRules":
|
|
34
34
|
from cognite.neat.rules.models.dms._rules import (
|
|
35
35
|
DMSContainer,
|
|
36
|
-
DMSMetadata,
|
|
37
36
|
DMSProperty,
|
|
38
37
|
DMSRules,
|
|
38
|
+
DMSView,
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
info_metadata = self.information.metadata
|
|
42
42
|
default_version = info_metadata.version
|
|
43
43
|
default_space = self._to_space(info_metadata.prefix)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
metadata = DMSMetadata(
|
|
47
|
-
schema_=info_metadata.schema_,
|
|
48
|
-
space=space,
|
|
49
|
-
data_model_type=DataModelType.solution if self.information.reference else DataModelType.enterprise,
|
|
50
|
-
version=info_metadata.version,
|
|
51
|
-
external_id=info_metadata.name.replace(" ", "_").lower(),
|
|
52
|
-
creator=info_metadata.creator,
|
|
53
|
-
name=info_metadata.name,
|
|
54
|
-
created=created or datetime.now(),
|
|
55
|
-
updated=updated or datetime.now(),
|
|
56
|
-
)
|
|
44
|
+
metadata = self._convert_metadata_to_dms(info_metadata)
|
|
57
45
|
|
|
58
46
|
properties_by_class: dict[str, list[DMSProperty]] = defaultdict(list)
|
|
59
47
|
for prop in self.information.properties:
|
|
@@ -111,6 +99,26 @@ class _InformationRulesConverter:
|
|
|
111
99
|
reference=self.information.reference.as_dms_architect_rules() if self.information.reference else None,
|
|
112
100
|
)
|
|
113
101
|
|
|
102
|
+
@classmethod
|
|
103
|
+
def _convert_metadata_to_dms(cls, metadata: InformationMetadata) -> "DMSMetadata":
|
|
104
|
+
from cognite.neat.rules.models.dms._rules import (
|
|
105
|
+
DMSMetadata,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
space = cls._to_space(metadata.prefix)
|
|
109
|
+
|
|
110
|
+
return DMSMetadata(
|
|
111
|
+
schema_=metadata.schema_,
|
|
112
|
+
space=space,
|
|
113
|
+
data_model_type=metadata.data_model_type,
|
|
114
|
+
version=metadata.version,
|
|
115
|
+
external_id=metadata.name.replace(" ", "_").lower(),
|
|
116
|
+
creator=metadata.creator,
|
|
117
|
+
name=metadata.name,
|
|
118
|
+
created=metadata.created,
|
|
119
|
+
updated=metadata.updated,
|
|
120
|
+
)
|
|
121
|
+
|
|
114
122
|
@classmethod
|
|
115
123
|
def _as_dms_property(cls, prop: InformationProperty, default_space: str, default_version: str) -> "DMSProperty":
|
|
116
124
|
"""This creates the first"""
|