cognite-neat 0.101.0__py3-none-any.whl → 0.103.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.

Files changed (74) hide show
  1. cognite/neat/__init__.py +1 -1
  2. cognite/neat/_app/api/routers/crud.py +1 -1
  3. cognite/neat/_client/__init__.py +1 -1
  4. cognite/neat/_client/_api/data_modeling_loaders.py +1 -1
  5. cognite/neat/_client/_api/schema.py +1 -1
  6. cognite/neat/_constants.py +5 -1
  7. cognite/neat/_graph/_tracking/__init__.py +1 -1
  8. cognite/neat/_graph/extractors/__init__.py +8 -8
  9. cognite/neat/_graph/extractors/_mock_graph_generator.py +2 -3
  10. cognite/neat/_graph/loaders/_base.py +1 -1
  11. cognite/neat/_graph/loaders/_rdf2dms.py +165 -47
  12. cognite/neat/_graph/queries/_base.py +22 -2
  13. cognite/neat/_graph/queries/_shared.py +4 -4
  14. cognite/neat/_graph/transformers/__init__.py +25 -9
  15. cognite/neat/_graph/transformers/_base.py +1 -1
  16. cognite/neat/_graph/transformers/_iodd.py +2 -2
  17. cognite/neat/_graph/transformers/_prune_graph.py +98 -24
  18. cognite/neat/_graph/transformers/_value_type.py +196 -2
  19. cognite/neat/_issues/__init__.py +6 -6
  20. cognite/neat/_issues/_base.py +4 -4
  21. cognite/neat/_issues/errors/__init__.py +22 -22
  22. cognite/neat/_issues/formatters.py +1 -1
  23. cognite/neat/_issues/warnings/__init__.py +20 -18
  24. cognite/neat/_issues/warnings/_properties.py +7 -0
  25. cognite/neat/_issues/warnings/user_modeling.py +2 -2
  26. cognite/neat/_rules/analysis/__init__.py +1 -1
  27. cognite/neat/_rules/catalog/__init__.py +1 -0
  28. cognite/neat/_rules/catalog/hello_world_pump.xlsx +0 -0
  29. cognite/neat/_rules/exporters/__init__.py +5 -5
  30. cognite/neat/_rules/exporters/_rules2excel.py +12 -6
  31. cognite/neat/_rules/importers/__init__.py +4 -4
  32. cognite/neat/_rules/importers/_base.py +7 -3
  33. cognite/neat/_rules/importers/_dms2rules.py +51 -19
  34. cognite/neat/_rules/importers/_rdf/__init__.py +1 -1
  35. cognite/neat/_rules/importers/_rdf/_base.py +2 -2
  36. cognite/neat/_rules/models/__init__.py +5 -5
  37. cognite/neat/_rules/models/_base_rules.py +1 -1
  38. cognite/neat/_rules/models/dms/__init__.py +11 -11
  39. cognite/neat/_rules/models/dms/_validation.py +16 -10
  40. cognite/neat/_rules/models/entities/__init__.py +26 -26
  41. cognite/neat/_rules/models/information/__init__.py +5 -5
  42. cognite/neat/_rules/models/information/_rules.py +3 -3
  43. cognite/neat/_rules/models/mapping/_classic2core.yaml +54 -8
  44. cognite/neat/_rules/transformers/__init__.py +12 -12
  45. cognite/neat/_rules/transformers/_pipelines.py +10 -5
  46. cognite/neat/_session/_base.py +71 -0
  47. cognite/neat/_session/_collector.py +3 -1
  48. cognite/neat/_session/_drop.py +10 -0
  49. cognite/neat/_session/_inspect.py +35 -1
  50. cognite/neat/_session/_mapping.py +5 -0
  51. cognite/neat/_session/_prepare.py +196 -7
  52. cognite/neat/_session/_read.py +180 -20
  53. cognite/neat/_session/_set.py +11 -1
  54. cognite/neat/_session/_show.py +41 -2
  55. cognite/neat/_session/_to.py +58 -10
  56. cognite/neat/_session/engine/__init__.py +1 -1
  57. cognite/neat/_session/engine/_load.py +3 -1
  58. cognite/neat/_store/__init__.py +3 -2
  59. cognite/neat/_store/{_base.py → _graph_store.py} +56 -2
  60. cognite/neat/_store/_provenance.py +11 -1
  61. cognite/neat/_store/_rules_store.py +20 -0
  62. cognite/neat/_utils/auth.py +7 -5
  63. cognite/neat/_utils/reader/__init__.py +1 -1
  64. cognite/neat/_version.py +2 -2
  65. cognite/neat/_workflows/__init__.py +3 -3
  66. cognite/neat/_workflows/steps/lib/current/graph_extractor.py +1 -1
  67. cognite/neat/_workflows/steps/lib/current/rules_exporter.py +1 -1
  68. cognite/neat/_workflows/steps/lib/current/rules_importer.py +2 -2
  69. cognite/neat/_workflows/steps/lib/io/io_steps.py +3 -3
  70. {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/METADATA +1 -1
  71. {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/RECORD +74 -72
  72. {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/LICENSE +0 -0
  73. {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/WHEEL +0 -0
  74. {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/entry_points.txt +0 -0
@@ -34,8 +34,6 @@ class ExcelExporter(BaseExporter[VerifiedRules, Workbook]):
34
34
  Args:
35
35
  styling: The styling to use for the Excel file. Defaults to "default". See below for details
36
36
  on the different styles.
37
- output_role: The role to use for the exported spreadsheet. If provided, the rules will be converted to
38
- this role formate before being written to excel. If not provided, the role from the rules will be used.
39
37
  new_model_id: The new model ID to use for the exported spreadsheet. This is only applicable if the input
40
38
  rules have 'is_reference' set. If provided, the model ID will be used to automatically create the
41
39
  new metadata sheet in the Excel file. The model id is expected to be a tuple of (prefix, title)
@@ -119,7 +117,11 @@ class ExcelExporter(BaseExporter[VerifiedRules, Workbook]):
119
117
 
120
118
  main_header = self._main_header_by_sheet_name[sheet_name]
121
119
  sheet.append([main_header] + [""] * (len(headers) - 1))
122
- sheet.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(headers))
120
+
121
+ if headers[0] == "Neat ID":
122
+ # Move the Neat ID to the end of the columns
123
+ headers = headers[1:] + ["Neat ID"]
124
+
123
125
  sheet.append(headers)
124
126
 
125
127
  fill_colors = itertools.cycle(["CADCFC", "FFFFFF"])
@@ -127,6 +129,9 @@ class ExcelExporter(BaseExporter[VerifiedRules, Workbook]):
127
129
  last_class: str | None = None
128
130
  item: dict[str, Any]
129
131
  for item in dumped_rules.get(sheet_name) or []:
132
+ if "Neat ID" in item:
133
+ # Move the Neat ID to the end of the columns
134
+ item["Neat ID"] = item.pop("Neat ID")
130
135
  row = list(item.values())
131
136
  class_ = row[0]
132
137
 
@@ -152,12 +157,13 @@ class ExcelExporter(BaseExporter[VerifiedRules, Workbook]):
152
157
  # This freezes all rows above the given row
153
158
  sheet.freeze_panes = sheet["A3"]
154
159
 
155
- sheet["A1"].alignment = Alignment(horizontal="center")
160
+ sheet["A1"].alignment = Alignment(horizontal="left")
156
161
 
157
162
  if self._styling_level > 1:
158
163
  # Make the header row bold, larger, and colored
159
- sheet["A1"].font = Font(bold=True, size=20)
160
- sheet["A1"].fill = PatternFill(fgColor="FFC000", patternType="solid")
164
+ for cell, *_ in sheet.iter_cols(min_row=1, max_row=1, min_col=1, max_col=len(headers)):
165
+ cell.font = Font(bold=True, size=20)
166
+ cell.fill = PatternFill(fgColor="FFC000", patternType="solid")
161
167
  for cell in sheet["2"]:
162
168
  cell.font = Font(bold=True, size=14)
163
169
 
@@ -7,14 +7,14 @@ from ._yaml2rules import YAMLImporter
7
7
 
8
8
  __all__ = [
9
9
  "BaseImporter",
10
- "OWLImporter",
11
- "IMFImporter",
12
10
  "DMSImporter",
11
+ "DTDLImporter",
13
12
  "ExcelImporter",
14
13
  "GoogleSheetImporter",
15
- "DTDLImporter",
16
- "YAMLImporter",
14
+ "IMFImporter",
17
15
  "InferenceImporter",
16
+ "OWLImporter",
17
+ "YAMLImporter",
18
18
  ]
19
19
 
20
20
  RulesImporters = (
@@ -3,16 +3,18 @@ from abc import ABC, abstractmethod
3
3
  from collections.abc import Iterator
4
4
  from contextlib import contextmanager, suppress
5
5
  from datetime import datetime
6
- from typing import Any, Generic, Literal
6
+ from typing import TYPE_CHECKING, Any, Generic, Literal
7
7
 
8
8
  from pydantic import ValidationError
9
9
 
10
10
  from cognite.neat._constants import DEFAULT_NAMESPACE
11
11
  from cognite.neat._issues import IssueList, NeatError, NeatWarning
12
12
  from cognite.neat._rules._shared import ReadRules, T_InputRules
13
- from cognite.neat._store._provenance import Agent as ProvenanceAgent
14
13
  from cognite.neat._utils.auxiliary import class_html_doc
15
14
 
15
+ if TYPE_CHECKING:
16
+ from cognite.neat._store._provenance import Agent as ProvenanceAgent
17
+
16
18
 
17
19
  class BaseImporter(ABC, Generic[T_InputRules]):
18
20
  """
@@ -48,8 +50,10 @@ class BaseImporter(ABC, Generic[T_InputRules]):
48
50
  return class_html_doc(cls)
49
51
 
50
52
  @property
51
- def agent(self) -> ProvenanceAgent:
53
+ def agent(self) -> "ProvenanceAgent":
52
54
  """Provenance agent for the importer."""
55
+ from cognite.neat._store._provenance import Agent as ProvenanceAgent
56
+
53
57
  return ProvenanceAgent(id_=DEFAULT_NAMESPACE[f"agent/{type(self).__name__}"])
54
58
 
55
59
 
@@ -1,4 +1,4 @@
1
- from collections import Counter
1
+ from collections import Counter, defaultdict
2
2
  from collections.abc import Collection, Iterable, Sequence
3
3
  from datetime import datetime, timezone
4
4
  from pathlib import Path
@@ -222,12 +222,18 @@ class DMSImporter(BaseImporter[DMSInputRules]):
222
222
  schema: DMSSchema,
223
223
  metadata: DMSInputMetadata | None = None,
224
224
  ) -> DMSInputRules:
225
+ enum_by_container_property = self._create_enum_collections(schema.containers.values())
226
+ enum_collection_by_container_property = {
227
+ key: enum_list[0].collection for key, enum_list in enum_by_container_property.items() if enum_list
228
+ }
229
+
225
230
  properties: list[DMSInputProperty] = []
226
231
  for view_id, view in schema.views.items():
227
232
  view_entity = ViewEntity.from_id(view_id)
228
- class_entity = view_entity.as_class()
229
233
  for prop_id, prop in (view.properties or {}).items():
230
- dms_property = self._create_dms_property(prop_id, prop, view_entity, class_entity)
234
+ dms_property = self._create_dms_property(
235
+ prop_id, prop, view_entity, enum_collection_by_container_property
236
+ )
231
237
  if dms_property is not None:
232
238
  properties.append(dms_property)
233
239
 
@@ -237,8 +243,6 @@ class DMSImporter(BaseImporter[DMSInputRules]):
237
243
 
238
244
  metadata = metadata or DMSInputMetadata.from_data_model(data_model)
239
245
 
240
- enum = self._create_enum_collections(schema.containers.values())
241
-
242
246
  return DMSInputRules(
243
247
  metadata=metadata,
244
248
  properties=properties,
@@ -248,7 +252,7 @@ class DMSImporter(BaseImporter[DMSInputRules]):
248
252
  for view_id, view in schema.views.items()
249
253
  ],
250
254
  nodes=[DMSInputNode.from_node_type(node_type) for node_type in schema.node_types.values()],
251
- enum=enum,
255
+ enum=[enum for enum_list in enum_by_container_property.values() for enum in enum_list] or None,
252
256
  )
253
257
 
254
258
  @classmethod
@@ -267,7 +271,11 @@ class DMSImporter(BaseImporter[DMSInputRules]):
267
271
  )
268
272
 
269
273
  def _create_dms_property(
270
- self, prop_id: str, prop: ViewPropertyApply, view_entity: ViewEntity, class_entity: ClassEntity
274
+ self,
275
+ prop_id: str,
276
+ prop: ViewPropertyApply,
277
+ view_entity: ViewEntity,
278
+ enum_collection_by_container_property: dict[tuple[dm.ContainerId, str], str],
271
279
  ) -> DMSInputProperty | None:
272
280
  if isinstance(prop, dm.MappedPropertyApply) and prop.container not in self._all_containers_by_id:
273
281
  self.issue_list.append(
@@ -300,7 +308,7 @@ class DMSImporter(BaseImporter[DMSInputRules]):
300
308
  )
301
309
  return None
302
310
 
303
- value_type = self._get_value_type(prop, view_entity, prop_id)
311
+ value_type = self._get_value_type(prop, view_entity, prop_id, enum_collection_by_container_property)
304
312
  if value_type is None:
305
313
  return None
306
314
 
@@ -347,7 +355,11 @@ class DMSImporter(BaseImporter[DMSInputRules]):
347
355
  return None
348
356
 
349
357
  def _get_value_type(
350
- self, prop: ViewPropertyApply, view_entity: ViewEntity, prop_id
358
+ self,
359
+ prop: ViewPropertyApply,
360
+ view_entity: ViewEntity,
361
+ prop_id: str,
362
+ enum_collection_by_container_property: dict[tuple[dm.ContainerId, str], str],
351
363
  ) -> DataType | ViewEntity | DMSUnknownEntity | None:
352
364
  if isinstance(
353
365
  prop,
@@ -367,7 +379,16 @@ class DMSImporter(BaseImporter[DMSInputRules]):
367
379
  elif isinstance(container_prop.type, PropertyTypeWithUnit) and container_prop.type.unit:
368
380
  return DataType.load(f"{container_prop.type._type}(unit={container_prop.type.unit.external_id})")
369
381
  elif isinstance(container_prop.type, DMSEnum):
370
- return Enum(collection=ClassEntity(suffix=prop_id), unknownValue=container_prop.type.unknown_value)
382
+ collection = enum_collection_by_container_property.get(
383
+ (prop.container, prop.container_property_identifier)
384
+ )
385
+ if collection is None:
386
+ # This should never happen
387
+ raise ValueError(
388
+ f"BUG in Neat: Enum for {prop.container}.{prop.container_property_identifier} not found."
389
+ )
390
+
391
+ return Enum(collection=ClassEntity(suffix=collection), unknownValue=container_prop.type.unknown_value)
371
392
  else:
372
393
  return DataType.load(container_prop.type._type)
373
394
  else:
@@ -477,15 +498,26 @@ class DMSImporter(BaseImporter[DMSInputRules]):
477
498
  return candidates[0]
478
499
 
479
500
  @staticmethod
480
- def _create_enum_collections(containers: Collection[dm.ContainerApply]) -> list[DMSInputEnum] | None:
481
- enum_collections: list[DMSInputEnum] = []
501
+ def _create_enum_collections(
502
+ containers: Collection[dm.ContainerApply],
503
+ ) -> dict[tuple[dm.ContainerId, str], list[DMSInputEnum]]:
504
+ enum_by_container_property: dict[tuple[dm.ContainerId, str], list[DMSInputEnum]] = defaultdict(list)
505
+
506
+ is_external_id_unique = len({container.external_id for container in containers}) == len(containers)
507
+
482
508
  for container in containers:
509
+ container_id = container.as_id()
483
510
  for prop_id, prop in container.properties.items():
484
- if isinstance(prop.type, DMSEnum):
485
- for identifier, value in prop.type.values.items():
486
- enum_collections.append(
487
- DMSInputEnum(
488
- collection=prop_id, value=identifier, name=value.name, description=value.description
489
- )
511
+ if not isinstance(prop.type, DMSEnum):
512
+ continue
513
+ if is_external_id_unique:
514
+ collection = f"{container.external_id}.{prop_id}"
515
+ else:
516
+ collection = f"{container.space}:{container.external_id}.{prop_id}"
517
+ for identifier, value in prop.type.values.items():
518
+ enum_by_container_property[(container_id, prop_id)].append(
519
+ DMSInputEnum(
520
+ collection=collection, value=identifier, name=value.name, description=value.description
490
521
  )
491
- return enum_collections
522
+ )
523
+ return enum_by_container_property
@@ -2,4 +2,4 @@ from ._imf2rules import IMFImporter
2
2
  from ._inference2rules import InferenceImporter
3
3
  from ._owl2rules import OWLImporter
4
4
 
5
- __all__ = ["IMFImporter", "OWLImporter", "InferenceImporter"]
5
+ __all__ = ["IMFImporter", "InferenceImporter", "OWLImporter"]
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from cognite.client import data_modeling as dm
5
5
  from rdflib import Graph, Namespace, URIRef
6
6
 
7
- from cognite.neat._constants import get_default_prefixes
7
+ from cognite.neat._constants import get_default_prefixes_and_namespaces
8
8
  from cognite.neat._issues import IssueList
9
9
  from cognite.neat._issues.errors import FileReadError
10
10
  from cognite.neat._issues.errors._general import NeatValueError
@@ -97,7 +97,7 @@ class BaseRDFImporter(BaseImporter[InformationInputRules]):
97
97
  issue_list.append(FileReadError(filepath, str(e)))
98
98
 
99
99
  # bind key namespaces
100
- for prefix, namespace in get_default_prefixes().items():
100
+ for prefix, namespace in get_default_prefixes_and_namespaces().items():
101
101
  graph.bind(prefix, namespace)
102
102
 
103
103
  return cls(
@@ -17,16 +17,16 @@ VERIFIED_RULES_BY_ROLE: dict[RoleTypes, type[InformationRules] | type[DMSRules]]
17
17
 
18
18
 
19
19
  __all__ = [
20
+ "INPUT_RULES_BY_ROLE",
20
21
  "DMSInputRules",
21
- "InformationInputRules",
22
- "InformationRules",
23
22
  "DMSRules",
24
- "INPUT_RULES_BY_ROLE",
25
23
  "DMSSchema",
24
+ "DataModelType",
25
+ "ExtensionCategory",
26
+ "InformationInputRules",
27
+ "InformationRules",
26
28
  "RoleTypes",
27
29
  "SchemaCompleteness",
28
- "ExtensionCategory",
29
- "DataModelType",
30
30
  "SheetList",
31
31
  "SheetRow",
32
32
  ]
@@ -149,7 +149,7 @@ class BaseMetadata(SchemaModel):
149
149
 
150
150
  role: ClassVar[RoleTypes] = Field(description="Role of the person creating the data model")
151
151
  aspect: ClassVar[DataModelAspect] = Field(description="Aspect of the data model")
152
- space: SpaceType = Field(alias="prefix", description="The space where the data model is defined")
152
+ space: SpaceType = Field(description="The space where the data model is defined")
153
153
  external_id: DataModelExternalIdType = Field(
154
154
  alias="externalId", description="External identifier for the data model"
155
155
  )
@@ -13,20 +13,20 @@ from ._rules_input import (
13
13
  from ._validation import DMSValidation
14
14
 
15
15
  __all__ = [
16
- "DMSRules",
17
- "DMSSchema",
18
- "DMSMetadata",
19
- "DMSView",
20
- "DMSProperty",
21
16
  "DMSContainer",
22
- "DMSNode",
23
17
  "DMSEnum",
24
- "DMSInputRules",
25
- "DMSInputMetadata",
26
- "DMSInputView",
27
- "DMSInputProperty",
28
18
  "DMSInputContainer",
29
- "DMSInputNode",
30
19
  "DMSInputEnum",
20
+ "DMSInputMetadata",
21
+ "DMSInputNode",
22
+ "DMSInputProperty",
23
+ "DMSInputRules",
24
+ "DMSInputView",
25
+ "DMSMetadata",
26
+ "DMSNode",
27
+ "DMSProperty",
28
+ "DMSRules",
29
+ "DMSSchema",
31
30
  "DMSValidation",
31
+ "DMSView",
32
32
  ]
@@ -1,5 +1,6 @@
1
1
  import warnings
2
2
  from collections import Counter, defaultdict
3
+ from collections.abc import Mapping
3
4
  from functools import lru_cache
4
5
  from typing import ClassVar
5
6
 
@@ -115,7 +116,9 @@ class DMSValidation:
115
116
  **ref_container_by_id,
116
117
  }
117
118
  all_views_by_id: dict[dm.ViewId, dm.ViewApply | dm.View] = {**dict(dms_schema.views.items()), **ref_view_by_id}
118
- properties_by_ids = self._as_properties_by_ids(dms_schema, ref_view_by_id)
119
+ properties_by_ids = self._as_properties_by_ids(dms_schema.views, ref_view_by_id)
120
+ ref_properties_by_ids = self._as_properties_by_ids(ref_view_by_id, {})
121
+ all_properties_by_ids = {**ref_properties_by_ids, **properties_by_ids}
119
122
  view_properties_by_id = self._as_view_properties_by_id(properties_by_ids)
120
123
  parents_view_ids_by_child_id = self._parent_view_ids_by_child_id(all_views_by_id)
121
124
 
@@ -132,7 +135,9 @@ class DMSValidation:
132
135
  # SDK classes validation
133
136
  issue_list.extend(self._containers_are_proper_size(dms_schema))
134
137
  issue_list.extend(
135
- self._validate_reverse_connections(properties_by_ids, all_containers_by_id, parents_view_ids_by_child_id)
138
+ self._validate_reverse_connections(
139
+ properties_by_ids, all_containers_by_id, parents_view_ids_by_child_id, all_properties_by_ids
140
+ )
136
141
  )
137
142
  issue_list.extend(self._validate_schema(dms_schema, all_views_by_id, all_containers_by_id))
138
143
  issue_list.extend(self._validate_referenced_container_limits(dms_schema.views, view_properties_by_id))
@@ -140,22 +145,22 @@ class DMSValidation:
140
145
 
141
146
  @staticmethod
142
147
  def _as_properties_by_ids(
143
- dms_schema: DMSSchema, ref_view_by_id: dict[dm.ViewId, dm.View]
148
+ view_by_id: Mapping[dm.ViewId, dm.ViewApply] | Mapping[dm.ViewId, dm.View],
149
+ ref_view_by_id: dict[dm.ViewId, dm.View],
144
150
  ) -> dict[tuple[ViewId, str], ViewPropertyApply | ViewProperty]:
145
151
  # Priority DMS schema properties.
146
152
  # No need to do long lookups in ref_views as these already contain all ancestor properties.
147
153
  properties_by_id: dict[tuple[ViewId, str], ViewPropertyApply | ViewProperty] = {}
148
- for view in dms_schema.views.values():
149
- view_id = view.as_id()
154
+ for view_id, view in view_by_id.items():
150
155
  for prop_id, prop in (view.properties or {}).items():
151
156
  properties_by_id[(view_id, prop_id)] = prop
152
157
  if view.implements:
153
158
  to_check = view.implements.copy()
154
159
  while to_check:
155
160
  parent_id = to_check.pop()
156
- if parent_id in dms_schema.views:
157
- # Priority DMS Schema properties
158
- parent_view = dms_schema.views[parent_id]
161
+ if parent_id in view_by_id:
162
+ # Priority of the DMS schema properties
163
+ parent_view = view_by_id[parent_id]
159
164
  for prop_id, prop in (parent_view.properties or {}).items():
160
165
  if (view_id, prop_id) not in properties_by_id:
161
166
  properties_by_id[(view_id, prop_id)] = prop
@@ -406,6 +411,7 @@ class DMSValidation:
406
411
  view_property_by_property_id: dict[tuple[dm.ViewId, str], ViewPropertyApply | ViewProperty],
407
412
  containers_by_id: dict[dm.ContainerId, dm.ContainerApply | dm.Container],
408
413
  parents_by_view: dict[dm.ViewId, set[dm.ViewId]],
414
+ all_view_property_by_property_id: dict[tuple[dm.ViewId, str], ViewPropertyApply | ViewProperty],
409
415
  ) -> IssueList:
410
416
  issue_list = IssueList()
411
417
  # do not check for reverse connections in Cognite models
@@ -416,7 +422,7 @@ class DMSValidation:
416
422
  if not isinstance(prop_, ReverseDirectRelationApply | ReverseDirectRelation):
417
423
  continue
418
424
  target_id = prop_.through.source, prop_.through.property
419
- if target_id not in view_property_by_property_id:
425
+ if target_id not in all_view_property_by_property_id:
420
426
  issue_list.append(
421
427
  ReversedConnectionNotFeasibleError(
422
428
  view_id,
@@ -430,7 +436,7 @@ class DMSValidation:
430
436
  # Todo: How to handle this case? Should not happen if you created the model with Neat
431
437
  continue
432
438
 
433
- target_property = view_property_by_property_id[(target_id[0], target_id[1])]
439
+ target_property = all_view_property_by_property_id[(target_id[0], target_id[1])]
434
440
  # Validate that the target is a direct relation pointing to the view_id
435
441
  is_direct_relation = False
436
442
  if isinstance(target_property, dm.MappedProperty) and isinstance(target_property.type, dm.DirectRelation):
@@ -25,38 +25,38 @@ from ._types import CdfResourceEntityList, ClassEntityList, ContainerEntityList,
25
25
  from ._wrapped import DMSFilter, HasDataFilter, NodeTypeFilter, RawFilter, WrappedEntity
26
26
 
27
27
  __all__ = [
28
- "Entity",
29
- "UnitEntity",
30
- "DMSVersionedEntity",
31
- "RelationshipEntity",
32
- "EdgeEntity",
33
- "ViewEntity",
34
- "ClassEntity",
35
- "ViewEntityList",
36
- "UnknownEntity",
37
- "Unknown",
38
- "Undefined",
39
- "T_Entity",
40
28
  "AssetEntity",
41
29
  "AssetFields",
42
- "ReverseConnectionEntity",
43
- "MultiValueTypeInfo",
44
- "DMSNodeEntity",
45
- "DMSEntity",
30
+ "CdfResourceEntityList",
31
+ "ClassEntity",
32
+ "ClassEntityList",
46
33
  "ContainerEntity",
34
+ "ContainerEntityList",
35
+ "DMSEntity",
36
+ "DMSFilter",
37
+ "DMSNodeEntity",
47
38
  "DMSUnknownEntity",
39
+ "DMSVersionedEntity",
48
40
  "DataModelEntity",
41
+ "EdgeEntity",
42
+ "Entity",
43
+ "HasDataFilter",
44
+ "MultiValueTypeInfo",
45
+ "NodeTypeFilter",
46
+ "RawFilter",
49
47
  "ReferenceEntity",
50
- "ClassEntityList",
51
- "CdfResourceEntityList",
52
- "ContainerEntityList",
48
+ "RelationshipEntity",
49
+ "ReverseConnectionEntity",
50
+ "T_Entity",
53
51
  "URLEntity",
54
- "load_value_type",
55
- "load_dms_value_type",
56
- "load_connection",
52
+ "Undefined",
53
+ "UnitEntity",
54
+ "Unknown",
55
+ "UnknownEntity",
56
+ "ViewEntity",
57
+ "ViewEntityList",
57
58
  "WrappedEntity",
58
- "NodeTypeFilter",
59
- "DMSFilter",
60
- "HasDataFilter",
61
- "RawFilter",
59
+ "load_connection",
60
+ "load_dms_value_type",
61
+ "load_value_type",
62
62
  ]
@@ -8,13 +8,13 @@ from ._rules_input import (
8
8
  from ._validation import InformationValidation
9
9
 
10
10
  __all__ = [
11
- "InformationRules",
12
- "InformationMetadata",
13
11
  "InformationClass",
14
- "InformationProperty",
15
- "InformationInputRules",
16
- "InformationInputMetadata",
17
12
  "InformationInputClass",
13
+ "InformationInputMetadata",
18
14
  "InformationInputProperty",
15
+ "InformationInputRules",
16
+ "InformationMetadata",
17
+ "InformationProperty",
18
+ "InformationRules",
19
19
  "InformationValidation",
20
20
  ]
@@ -7,7 +7,7 @@ from pydantic import Field, field_serializer, field_validator, model_validator
7
7
  from pydantic_core.core_schema import SerializationInfo
8
8
  from rdflib import Namespace, URIRef
9
9
 
10
- from cognite.neat._constants import get_default_prefixes
10
+ from cognite.neat._constants import get_default_prefixes_and_namespaces
11
11
  from cognite.neat._issues.errors import NeatValueError, PropertyDefinitionError
12
12
  from cognite.neat._rules._constants import EntityTypes
13
13
  from cognite.neat._rules.models._base_rules import (
@@ -255,7 +255,7 @@ class InformationRules(BaseRules):
255
255
  classes: SheetList[InformationClass] = Field(alias="Classes", description="List of classes")
256
256
  prefixes: dict[str, Namespace] = Field(
257
257
  alias="Prefixes",
258
- default_factory=get_default_prefixes,
258
+ default_factory=get_default_prefixes_and_namespaces,
259
259
  description="the definition of the prefixes that are used in the semantic data model",
260
260
  )
261
261
 
@@ -264,7 +264,7 @@ class InformationRules(BaseRules):
264
264
  if isinstance(values, dict):
265
265
  return {key: Namespace(value) if isinstance(value, str) else value for key, value in values.items()}
266
266
  elif values is None:
267
- values = get_default_prefixes()
267
+ values = get_default_prefixes_and_namespaces()
268
268
  return values
269
269
 
270
270
  def as_dms_rules(self) -> "DMSRules":