cognite-neat 0.77.2__py3-none-any.whl → 0.77.3__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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.77.2"
1
+ __version__ = "0.77.3"
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import itertools
4
- from datetime import datetime
4
+ import json
5
+ from datetime import datetime, timezone
5
6
  from pathlib import Path
6
7
  from types import GenericAlias
7
8
  from typing import Any, ClassVar, Literal, cast, get_args
@@ -14,14 +15,14 @@ from openpyxl.worksheet.worksheet import Worksheet
14
15
  from cognite.neat.rules._shared import Rules
15
16
  from cognite.neat.rules.models import (
16
17
  DataModelType,
17
- DMSRules,
18
- DomainRules,
19
18
  ExtensionCategory,
20
- InformationRules,
21
19
  RoleTypes,
22
20
  SchemaCompleteness,
23
21
  SheetEntity,
24
22
  )
23
+ from cognite.neat.rules.models.dms import DMSMetadata
24
+ from cognite.neat.rules.models.domain import DomainMetadata
25
+ from cognite.neat.rules.models.information import InformationMetadata
25
26
 
26
27
  from ._base import BaseExporter
27
28
 
@@ -34,9 +35,6 @@ class ExcelExporter(BaseExporter[Workbook]):
34
35
  on the different styles.
35
36
  output_role: The role to use for the exported spreadsheet. If provided, the rules will be converted to
36
37
  this role formate before being written to excel. If not provided, the role from the rules will be used.
37
- new_model_id: The new model ID to use for the exported spreadsheet. This is only applicable if the input
38
- rules have 'is_reference' set. If provided, the model ID will be used to automatically create the
39
- new metadata sheet in the Excel file.
40
38
  dump_as: This determines how the rules are written to the Excel file. An Excel file has up to three sets of
41
39
  sheets: user, last, and reference. The user sheets are used for inputting rules from a user. The last sheets
42
40
  are used for the last version of the same model as the user, while the reference sheets are used for
@@ -49,6 +47,10 @@ class ExcelExporter(BaseExporter[Workbook]):
49
47
  change a model that has already been published to CDF and that model is in production.
50
48
  * "reference": The rules are written to the reference sheets. This is typically used when you want to build
51
49
  a new solution on top of an enterprise model.
50
+ new_model_id: The new model ID to use for the exported spreadsheet. This is only applicable if the input
51
+ rules have 'is_reference' set. If provided, the model ID will be used to automatically create the
52
+ new metadata sheet in the Excel file. The model id is expected to be a tuple of (prefix, title)
53
+ (space, external_id) for InformationRules and DMSRules respectively.
52
54
 
53
55
  The following styles are available:
54
56
 
@@ -74,8 +76,8 @@ class ExcelExporter(BaseExporter[Workbook]):
74
76
  self,
75
77
  styling: Style = "default",
76
78
  output_role: RoleTypes | None = None,
77
- new_model_id: tuple[str, str, str] | None = None,
78
79
  dump_as: DumpOptions = "user",
80
+ new_model_id: tuple[str, str] | None = None,
79
81
  ):
80
82
  if styling not in self.style_options:
81
83
  raise ValueError(f"Invalid styling: {styling}. Valid options are {self.style_options}")
@@ -106,9 +108,11 @@ class ExcelExporter(BaseExporter[Workbook]):
106
108
  dumped_last_rules: dict[str, Any] | None = None
107
109
  dumped_reference_rules: dict[str, Any] | None = None
108
110
  if self.dump_as != "user":
109
- # Writes empty reference sheets
111
+ action = {"last": "update", "reference": "create"}[self.dump_as]
112
+ metadata_creator = _MetadataCreator(action, self.new_model_id) # type: ignore[arg-type]
113
+
110
114
  dumped_user_rules = {
111
- "Metadata": self._create_metadata_sheet_user_rules(rules),
115
+ "Metadata": metadata_creator.create(rules.metadata),
112
116
  }
113
117
 
114
118
  if self.dump_as == "last":
@@ -234,82 +238,67 @@ class ExcelExporter(BaseExporter[Workbook]):
234
238
  sheet.column_dimensions[selected_column.column_letter].width = max(current, max_length + 0.5)
235
239
  return None
236
240
 
237
- def _create_metadata_sheet_user_rules(self, rules: Rules) -> dict[str, Any]:
238
- metadata: dict[str, Any] = {
239
- field_alias: None for field_alias in rules.metadata.model_dump(by_alias=True).keys()
240
- }
241
- if "creator" in metadata:
242
- metadata["creator"] = "YOUR NAME"
243
-
244
- if isinstance(rules, DomainRules):
245
- return metadata
246
- elif isinstance(rules, DMSRules):
247
- existing_model_id = (rules.metadata.space, rules.metadata.external_id, rules.metadata.version)
248
- elif isinstance(rules, InformationRules):
249
- existing_model_id = (rules.metadata.prefix, rules.metadata.name, rules.metadata.version)
250
- else:
251
- raise ValueError(f"Unsupported rules type: {type(rules)}")
252
- existing_metadata = rules.metadata.model_dump(by_alias=True)
253
- if isinstance(existing_metadata["created"], datetime):
254
- metadata["created"] = existing_metadata["created"].replace(tzinfo=None)
255
- if isinstance(existing_metadata["updated"], datetime):
256
- metadata["updated"] = existing_metadata["updated"].replace(tzinfo=None)
257
- # Excel does not support timezone in datetime strings
258
- now_iso = datetime.now().replace(tzinfo=None).isoformat()
259
- is_info = isinstance(rules, InformationRules)
260
- is_dms = isinstance(rules, DMSRules)
261
- is_extension = self.new_model_id is not None or rules.reference is not None
262
- is_solution = rules.metadata.data_model_type == DataModelType.solution
263
-
264
- if is_solution and self.new_model_id:
265
- metadata["prefix" if is_info else "space"] = self.new_model_id[0] # type: ignore[index]
266
- metadata["title" if is_info else "externalId"] = self.new_model_id[1] # type: ignore[index]
267
- metadata["version"] = self.new_model_id[2] # type: ignore[index]
268
- elif is_solution and self.dump_as == "reference" and rules.reference:
269
- metadata["prefix" if is_info else "space"] = "YOUR_PREFIX"
270
- metadata["title" if is_info else "externalId"] = "YOUR_TITLE"
271
- metadata["version"] = "1"
272
- else:
273
- metadata["prefix" if is_info else "space"] = existing_model_id[0]
274
- metadata["title" if is_info else "externalId"] = existing_model_id[1]
275
- metadata["version"] = existing_model_id[2]
276
-
277
- if is_solution and is_info and self.new_model_id:
278
- metadata["namespace"] = f"http://purl.org/{self.new_model_id[0]}/" # type: ignore[index]
279
- elif is_info:
280
- metadata["namespace"] = existing_metadata["namespace"]
281
-
282
- if is_solution and is_dms and self.new_model_id:
283
- metadata["name"] = self.new_model_id[1] # type: ignore[index]
284
-
285
- if is_solution:
286
- metadata["created"] = now_iso
287
- else:
288
- metadata["created"] = existing_metadata["created"]
289
-
290
- if is_solution or is_extension:
291
- metadata["updated"] = now_iso
292
- else:
293
- metadata["updated"] = existing_metadata["updated"]
294
241
 
295
- if is_solution:
296
- metadata["creator"] = "YOUR NAME"
297
- else:
298
- metadata["creator"] = existing_metadata["creator"]
299
-
300
- if not is_solution:
301
- metadata["description"] = existing_metadata["description"]
242
+ class _MetadataCreator:
243
+ creator_name = "<YOUR NAME>"
302
244
 
303
- if is_extension:
304
- metadata["schema"] = SchemaCompleteness.extended.value
305
- else:
306
- metadata["schema"] = SchemaCompleteness.complete.value
307
-
308
- if is_solution:
309
- metadata["dataModelType"] = DataModelType.solution.value
245
+ def __init__(
246
+ self,
247
+ action: Literal["create", "update"],
248
+ new_model_id: tuple[str, str] | None = None,
249
+ ):
250
+ self.action = action
251
+ self.new_model_id = new_model_id or ("YOUR_PREFIX", "YOUR_TITLE")
252
+
253
+ def create(self, metadata: DomainMetadata | InformationMetadata | DMSMetadata) -> dict[str, Any]:
254
+ now = datetime.now(timezone.utc).replace(microsecond=0, tzinfo=None)
255
+ if self.action == "update":
256
+ output = json.loads(metadata.model_dump_json(by_alias=True))
257
+ # This is the same for Information and DMS
258
+ output["updated"] = now.isoformat()
259
+ output["schema"] = SchemaCompleteness.extended.value
260
+ output["extension"] = ExtensionCategory.addition.value
261
+ if value := output.get("creator"):
262
+ output["creator"] = f"{value}, {self.creator_name}"
263
+ else:
264
+ output["creator"] = self.creator_name
265
+ return output
266
+
267
+ # Action "create"
268
+ if isinstance(metadata, DomainMetadata):
269
+ output = {field_alias: None for field_alias in metadata.model_dump(by_alias=True).keys()}
270
+ output["role"] = metadata.role.value
271
+ output["creator"] = self.creator_name
272
+ return output
273
+
274
+ new_metadata = self._create_new_info(now)
275
+ if isinstance(metadata, DMSMetadata):
276
+ from cognite.neat.rules.models.information._converter import _InformationRulesConverter
277
+
278
+ output_metadata: DMSMetadata | InformationMetadata = _InformationRulesConverter._convert_metadata_to_dms(
279
+ new_metadata
280
+ )
281
+ elif isinstance(metadata, InformationMetadata):
282
+ output_metadata = new_metadata
310
283
  else:
311
- metadata["dataModelType"] = DataModelType.enterprise.value
312
-
313
- metadata["extension"] = ExtensionCategory.addition.value
314
- metadata["role"] = (self.output_role and self.output_role.value) or rules.metadata.role.value
315
- return metadata
284
+ raise ValueError(f"Bug in Neat: Unknown metadata type: {type(metadata)}")
285
+
286
+ created = json.loads(output_metadata.model_dump_json(by_alias=True))
287
+ created.pop("extension", None)
288
+ return created
289
+
290
+ def _create_new_info(self, now: datetime) -> InformationMetadata:
291
+ prefix = self.new_model_id[0]
292
+ return InformationMetadata(
293
+ data_model_type=DataModelType.solution,
294
+ schema_=SchemaCompleteness.extended,
295
+ extension=ExtensionCategory.addition,
296
+ prefix=prefix,
297
+ namespace=f"http://purl.org/neat/{prefix}/", # type: ignore[arg-type]
298
+ description=None,
299
+ version="1",
300
+ created=now,
301
+ updated=now,
302
+ creator=[self.creator_name],
303
+ name=self.new_model_id[1],
304
+ )
@@ -61,8 +61,10 @@ class DMSImporter(BaseImporter):
61
61
  self.ref_metadata = ref_metadata
62
62
  self.issue_list = IssueList(read_issues)
63
63
  self._all_containers_by_id = schema.containers.copy()
64
+ self._all_view_ids = set(self.root_schema.views.keys())
64
65
  if self.root_schema.reference:
65
66
  self._all_containers_by_id.update(self.root_schema.reference.containers)
67
+ self._all_view_ids.update(self.root_schema.reference.views.keys())
66
68
 
67
69
  @classmethod
68
70
  def from_data_model_id(
@@ -100,15 +102,17 @@ class DMSImporter(BaseImporter):
100
102
  else:
101
103
  ref_model = None
102
104
 
103
- try:
105
+ issue_list = IssueList()
106
+ with _handle_issues(issue_list) as result:
104
107
  schema = DMSSchema.from_data_model(client, user_model, ref_model)
105
- except Exception as e:
106
- return cls(DMSSchema(), [issues.importing.APIError(str(e))])
108
+
109
+ if result.result == "failure" or issue_list.has_errors:
110
+ return cls(DMSSchema(), issue_list)
107
111
 
108
112
  metadata = cls._create_metadata_from_model(user_model)
109
113
  ref_metadata = cls._create_metadata_from_model(ref_model) if ref_model else None
110
114
 
111
- return cls(schema, [], metadata, ref_metadata)
115
+ return cls(schema, issue_list, metadata, ref_metadata)
112
116
 
113
117
  @classmethod
114
118
  def _find_model_in_list(
@@ -361,7 +365,7 @@ class DMSImporter(BaseImporter):
361
365
  elif isinstance(prop, dm.MappedPropertyApply):
362
366
  container_prop = self._container_prop_unsafe(cast(dm.MappedPropertyApply, prop))
363
367
  if isinstance(container_prop.type, dm.DirectRelation):
364
- if prop.source is None:
368
+ if prop.source is None or prop.source not in self._all_view_ids:
365
369
  # The warning is issued when the DMS Rules are created.
366
370
  return DMSUnknownEntity()
367
371
  else:
@@ -30,6 +30,7 @@ __all__ = [
30
30
  "HasDataFilterAppliedToTooManyContainersWarning",
31
31
  "ReverseRelationMissingOtherSideWarning",
32
32
  "NodeTypeFilterOnParentViewWarning",
33
+ "MissingViewInModelWarning",
33
34
  "ChangingContainerError",
34
35
  "ChangingViewError",
35
36
  ]
@@ -293,6 +294,24 @@ class ViewMapsToTooManyContainersWarning(DMSSchemaWarning):
293
294
  return output
294
295
 
295
296
 
297
+ @dataclass(frozen=True)
298
+ class MissingViewInModelWarning(DMSSchemaWarning):
299
+ description = "The data model contains view pointing to views not present in the data model"
300
+ fix = "Add the view(s) to the data model"
301
+ error_name: ClassVar[str] = "MissingViewInModel"
302
+ data_model_id: dm.DataModelId
303
+ view_ids: set[dm.ViewId]
304
+
305
+ def message(self) -> str:
306
+ return f"The view(s) {self.view_ids} are missing in the data model {self.data_model_id}"
307
+
308
+ def dump(self) -> dict[str, Any]:
309
+ output = super().dump()
310
+ output["data_model_id"] = self.data_model_id.dump()
311
+ output["view_id"] = [view_id.dump() for view_id in self.view_ids]
312
+ return output
313
+
314
+
296
315
  @dataclass(frozen=True)
297
316
  class ContainerPropertyUsedMultipleTimesError(DMSSchemaError):
298
317
  description = "The container property is used multiple times by the same view property"
@@ -1,5 +1,6 @@
1
1
  from abc import ABC
2
2
  from dataclasses import dataclass
3
+ from typing import Any
3
4
 
4
5
  from .base import NeatValidationError, ValidationWarning
5
6
 
@@ -23,6 +24,7 @@ __all__ = [
23
24
  "MissingIdentifierError",
24
25
  "UnsupportedPropertyTypeError",
25
26
  "APIError",
27
+ "FailedImportWarning",
26
28
  ]
27
29
 
28
30
 
@@ -259,6 +261,20 @@ class APIWarning(ModelImportWarning):
259
261
  return {"error_message": self.error_message}
260
262
 
261
263
 
264
+ @dataclass(frozen=True)
265
+ class FailedImportWarning(ModelImportWarning):
266
+ description = "Failed to import part of the model."
267
+ fix = "No fix is available."
268
+
269
+ identifier: set[str]
270
+
271
+ def message(self) -> str:
272
+ return f"Failed to import: {self.identifier}. This will be skipped."
273
+
274
+ def dump(self) -> dict[str, Any]:
275
+ return {"identifier": list(self.identifier)}
276
+
277
+
262
278
  @dataclass(frozen=True)
263
279
  class ModelImportError(NeatValidationError, ABC):
264
280
  description = "An error was raised during importing."
@@ -1,6 +1,5 @@
1
1
  import warnings
2
- from datetime import datetime
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 = InformationMetadata(
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,23 @@ 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
+ prefix=prefix,
109
+ namespace=Namespace(f"https://purl.orgl/neat/{prefix}/"),
110
+ version=metadata.version,
111
+ description=metadata.description,
112
+ name=metadata.name or metadata.external_id,
113
+ creator=metadata.creator,
114
+ created=metadata.created,
115
+ updated=metadata.updated,
116
+ )
117
+
114
118
  @classmethod
115
119
  def _get_class_reference(cls, view: DMSView) -> ReferenceEntity | None:
116
120
  parents_other_namespace = [parent for parent in view.implements or [] if parent.prefix != view.class_.prefix]
@@ -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
- # We need to include parent views in the schema to make sure that the schema is valid.
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.
@@ -1,14 +1,11 @@
1
1
  import re
2
2
  from collections import defaultdict
3
- from datetime import datetime
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, created: datetime | None = None, updated: datetime | None = None) -> "DMSRules":
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
- space = self._to_space(info_metadata.prefix)
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"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cognite-neat
3
- Version: 0.77.2
3
+ Version: 0.77.3
4
4
  Summary: Knowledge graph transformation
5
5
  Home-page: https://cognite-neat.readthedocs-hosted.com/
6
6
  License: Apache-2.0
@@ -1,5 +1,5 @@
1
1
  cognite/neat/__init__.py,sha256=v-rRiDOgZ3sQSMQKq0vgUQZvpeOkoHFXissAx6Ktg84,61
2
- cognite/neat/_version.py,sha256=kh8YirXq1n0W6XtV5vM5A8L0p7-1zfBuOABzfVzGjbs,23
2
+ cognite/neat/_version.py,sha256=NPJS42_jfINt0XsTzh6J8mMo-DNeRf0PVi2gr3NvRzw,23
3
3
  cognite/neat/app/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cognite/neat/app/api/asgi/metrics.py,sha256=nxFy7L5cChTI0a-zkCiJ59Aq8yLuIJp5c9Dg0wRXtV0,152
5
5
  cognite/neat/app/api/configuration.py,sha256=2U5M6M252swvQPQyooA1EBzFUZNtcTmuSaywfJDgckM,4232
@@ -166,13 +166,13 @@ cognite/neat/rules/exporters/__init__.py,sha256=Gn3CjkVKHJF9Po1ZPH4wAJ-sRW9up7b2
166
166
  cognite/neat/rules/exporters/_base.py,sha256=m63iw8xjlZbZAxGL8mn7pjGf1pW3rVv8C20_RSiu4t0,1511
167
167
  cognite/neat/rules/exporters/_models.py,sha256=vRd0P_YsrZ1eaAGGHfdTeFunaqHdaa0ZtnWiVZBR1nc,1976
168
168
  cognite/neat/rules/exporters/_rules2dms.py,sha256=US2IO4YTJSF_CDzau1dTpXyeHntJWVSPkMCQoUoKeC0,13688
169
- cognite/neat/rules/exporters/_rules2excel.py,sha256=K3D_AC6UZ-cG9ZFkqFvuDiMTdBC9ZUW9_IkkY9KsYW0,14934
169
+ cognite/neat/rules/exporters/_rules2excel.py,sha256=XuPCMzX6RweFCyt8A264NzM5iRVZtcwZrzYXy2LRLns,14172
170
170
  cognite/neat/rules/exporters/_rules2ontology.py,sha256=NWS3cn2927LQqW_PdQ-92OLIlmIKGNk7xh5yOMAyj94,20120
171
171
  cognite/neat/rules/exporters/_rules2yaml.py,sha256=sOSdnTJ5mXuyAJECdNnNsX6oLvgETptkpgPUQbK0n2w,3026
172
172
  cognite/neat/rules/exporters/_validation.py,sha256=OlKIyf4nhSDehJwFHDQ8Zdf6HpNfW7dSe2s67eywHu4,4078
173
173
  cognite/neat/rules/importers/__init__.py,sha256=zqNbGpvdVhYkLjWx1i9dJ3FXzYGtuQyTydUYsj-BndQ,408
174
174
  cognite/neat/rules/importers/_base.py,sha256=GUiJrYwJ25thI71iS9hCeP_iSZ0Vv8ou3z6MfD07FAk,4274
175
- cognite/neat/rules/importers/_dms2rules.py,sha256=UxAatq8WL0rYz4wcopY0wHcBE4JTf--FzflhMxymypY,18274
175
+ cognite/neat/rules/importers/_dms2rules.py,sha256=R6NCzo42AEQKgHJ5pYJvccCjlKiFX5BuOrIysvTlCto,18546
176
176
  cognite/neat/rules/importers/_dtdl2rules/__init__.py,sha256=CNR-sUihs2mnR1bPMKs3j3L4ds3vFTsrl6YycExZTfU,68
177
177
  cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py,sha256=wW4saKva61Q_i17guY0dc4OseJDQfqHy_QZBtm0OD6g,12134
178
178
  cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py,sha256=ysmWUxZ0npwrTB0uiH5jA0v37sfCwowGaYk17IyxPUU,12663
@@ -187,10 +187,10 @@ cognite/neat/rules/importers/_spreadsheet2rules.py,sha256=dKTue97yZlPQagegfdyOWt
187
187
  cognite/neat/rules/importers/_yaml2rules.py,sha256=F0uksSz1A3po5OlRM2152_w5j8D9oYTLB9NFTkSMlWI,4275
188
188
  cognite/neat/rules/issues/__init__.py,sha256=Ms6jgCxCezc5IgTOwCFtXQPtoVFfOvdcXj84_rs917I,563
189
189
  cognite/neat/rules/issues/base.py,sha256=i2aTC-wq3UVW2bj_7wKeuhYxCpMD06Bd9-m00bWcTBs,6438
190
- cognite/neat/rules/issues/dms.py,sha256=LP6RREMg_CNKBwqYZLR7IBozKWzR607HH4JuUD7X9Fk,22893
190
+ cognite/neat/rules/issues/dms.py,sha256=CKztcpNu9E_ygbAmiODOhaYKPX6o9eaXeiod7Ak-kNY,23617
191
191
  cognite/neat/rules/issues/fileread.py,sha256=ao199mtvhPSW0IA8ZQZ0RzuLIIipYtL0jp6fLqxb4_c,5748
192
192
  cognite/neat/rules/issues/formatters.py,sha256=_ag2bJ9hncOj8pAGJvTTEPs9kTtxbD7vkqvS9Zcnizc,3385
193
- cognite/neat/rules/issues/importing.py,sha256=p90847g_TbUAXMyxalcEaWXaPygJoSE5E85dQO4syoo,12288
193
+ cognite/neat/rules/issues/importing.py,sha256=l0VKmOWN-qyvOMukNAVJZrN2WGD2YcGXeCKbxV-G_vA,12726
194
194
  cognite/neat/rules/issues/spreadsheet.py,sha256=-jMcamtvDIACKiIHtDNafjiMgovVN-VthyqE1FaSy-0,13936
195
195
  cognite/neat/rules/issues/spreadsheet_file.py,sha256=YCp0Pk_TsiqYuOPdWpjUpre-zvi2c5_MvrC_dxw10YY,4964
196
196
  cognite/neat/rules/models/__init__.py,sha256=aqhQUidHYgOk5_iqdi6s72s2g8qyMRFXShYzh-ctNpw,782
@@ -201,17 +201,17 @@ cognite/neat/rules/models/_types/_base.py,sha256=2GhLUE1ukV8X8SGL_JDxpbWGZyAvOnS
201
201
  cognite/neat/rules/models/_types/_field.py,sha256=74WfCSVbTubpK4n4VsysQqCch6VI8IcPqnHQpvNbFZ8,3197
202
202
  cognite/neat/rules/models/data_types.py,sha256=lanwkhwG8iHKfjYfia4v2SBTJrMeXOsqaVkVEP2QMXs,6078
203
203
  cognite/neat/rules/models/dms/__init__.py,sha256=Wzyqzz2ZIjpUbDg04CMuuIAw-f2A02DayNeqO9R-2Hw,491
204
- cognite/neat/rules/models/dms/_converter.py,sha256=x3u3jLnkknozoXXoAXXOWFHCsppqUwSvWv9wMOJ2F1Y,5706
204
+ cognite/neat/rules/models/dms/_converter.py,sha256=aOZI9zPEEcJSXhbN0uS3JLpWT68pweastKEyFpCLWWs,5863
205
205
  cognite/neat/rules/models/dms/_exporter.py,sha256=WTokr7gyjrpxW212kZpFfvd7zw09RRVPjAsxe_aizFo,18903
206
206
  cognite/neat/rules/models/dms/_rules.py,sha256=ZLdJLdAJGX1l5t1hChEic9TOHdculbWRhiLbUluZRRQ,15568
207
207
  cognite/neat/rules/models/dms/_rules_input.py,sha256=2ZGE3nsQyJ7RgdR5o9Wf8XbpSD57ZPbhvMz6H92aJ9g,13633
208
- cognite/neat/rules/models/dms/_schema.py,sha256=6lJSLPoZAjFnbfFl6dmAJR0xlAsQKi_Obcxp8Lp_t-0,41973
208
+ cognite/neat/rules/models/dms/_schema.py,sha256=P0StFJppq5JV2OHws1yUbDh9gvKRfJCHMDV0-ZeW1ts,43743
209
209
  cognite/neat/rules/models/dms/_serializer.py,sha256=Zulj__rnaVNtrbGJPkn4dYMfMXWYyRmtNPR2Yb5zYW0,6668
210
210
  cognite/neat/rules/models/dms/_validation.py,sha256=-7bpj1vQybB7P7nqvSc1XjKJhbpIRCXBzm3pdx6pqPQ,14589
211
211
  cognite/neat/rules/models/domain.py,sha256=13OhG-XavE5ipU2ICaYaUhz60volkuVfbJrsp0PhaUU,2993
212
212
  cognite/neat/rules/models/entities.py,sha256=iBG84Jr1qQ7PvkMJUJzJ1oWApeONb1IACixdJSztUhk,16395
213
213
  cognite/neat/rules/models/information/__init__.py,sha256=KvbYxVk38qReGbGTrU_Y3P3Gz6Bfghk5lHSKs8DlTOI,195
214
- cognite/neat/rules/models/information/_converter.py,sha256=jzaIk7Q2CeU3TIGULEINwUNNyhWu-VdOW646EjH_FrI,7964
214
+ cognite/neat/rules/models/information/_converter.py,sha256=TxVYzR41Rhejf7ep73oqMRNFPOdxAbamoEWnvsnXbng,8040
215
215
  cognite/neat/rules/models/information/_rules.py,sha256=YE7X8MsPQv-AVtl4vYtQW99moT45sYk2dI2DDS1YRO0,15546
216
216
  cognite/neat/rules/models/wrapped_entities.py,sha256=ThhjnNNrpgz0HeORIQ8Q894trxP73P7T_TuZj6qH2CU,7157
217
217
  cognite/neat/utils/__init__.py,sha256=l5Nyqhqo25bcQXCOb_lk01cr-UXsG8cczz_y_I0u6bg,68
@@ -272,8 +272,8 @@ cognite/neat/workflows/steps_registry.py,sha256=fkTX14ZA7_gkUYfWIlx7A1XbCidvqR23
272
272
  cognite/neat/workflows/tasks.py,sha256=dqlJwKAb0jlkl7abbY8RRz3m7MT4SK8-7cntMWkOYjw,788
273
273
  cognite/neat/workflows/triggers.py,sha256=_BLNplzoz0iic367u1mhHMHiUrCwP-SLK6_CZzfODX0,7071
274
274
  cognite/neat/workflows/utils.py,sha256=gKdy3RLG7ctRhbCRwaDIWpL9Mi98zm56-d4jfHDqP1E,453
275
- cognite_neat-0.77.2.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
276
- cognite_neat-0.77.2.dist-info/METADATA,sha256=3XmTaOBYr0Q856UUs19-zkc2BAeUTudgKn2LoMgHW6Q,9316
277
- cognite_neat-0.77.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
278
- cognite_neat-0.77.2.dist-info/entry_points.txt,sha256=61FPqiWb25vbqB0KI7znG8nsg_ibLHBvTjYnkPvNFso,50
279
- cognite_neat-0.77.2.dist-info/RECORD,,
275
+ cognite_neat-0.77.3.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
276
+ cognite_neat-0.77.3.dist-info/METADATA,sha256=tUDauNAgbTO_dsbRSkfgvJrVwmOs13HWyjWVidwBW4A,9316
277
+ cognite_neat-0.77.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
278
+ cognite_neat-0.77.3.dist-info/entry_points.txt,sha256=61FPqiWb25vbqB0KI7znG8nsg_ibLHBvTjYnkPvNFso,50
279
+ cognite_neat-0.77.3.dist-info/RECORD,,