cognite-neat 0.103.1__py3-none-any.whl → 0.105.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 (175) hide show
  1. cognite/neat/_client/_api/data_modeling_loaders.py +83 -23
  2. cognite/neat/_client/_api/schema.py +2 -1
  3. cognite/neat/_client/data_classes/neat_sequence.py +261 -0
  4. cognite/neat/_client/data_classes/schema.py +5 -1
  5. cognite/neat/_client/testing.py +33 -0
  6. cognite/neat/_constants.py +56 -0
  7. cognite/neat/_graph/extractors/_classic_cdf/_base.py +6 -5
  8. cognite/neat/_graph/extractors/_classic_cdf/_sequences.py +225 -11
  9. cognite/neat/_graph/extractors/_mock_graph_generator.py +2 -2
  10. cognite/neat/_graph/loaders/_rdf2dms.py +13 -2
  11. cognite/neat/_graph/transformers/__init__.py +3 -1
  12. cognite/neat/_graph/transformers/_base.py +109 -1
  13. cognite/neat/_graph/transformers/_classic_cdf.py +6 -1
  14. cognite/neat/_graph/transformers/_prune_graph.py +103 -47
  15. cognite/neat/_graph/transformers/_rdfpath.py +41 -17
  16. cognite/neat/_graph/transformers/_value_type.py +188 -151
  17. cognite/neat/_issues/__init__.py +0 -2
  18. cognite/neat/_issues/_base.py +54 -43
  19. cognite/neat/_issues/warnings/__init__.py +4 -1
  20. cognite/neat/_issues/warnings/_general.py +7 -0
  21. cognite/neat/_issues/warnings/_resources.py +12 -1
  22. cognite/neat/_rules/_shared.py +18 -34
  23. cognite/neat/_rules/exporters/_base.py +28 -2
  24. cognite/neat/_rules/exporters/_rules2dms.py +39 -1
  25. cognite/neat/_rules/exporters/_rules2excel.py +13 -2
  26. cognite/neat/_rules/exporters/_rules2instance_template.py +4 -0
  27. cognite/neat/_rules/exporters/_rules2ontology.py +13 -1
  28. cognite/neat/_rules/exporters/_rules2yaml.py +4 -0
  29. cognite/neat/_rules/importers/_base.py +9 -0
  30. cognite/neat/_rules/importers/_dms2rules.py +80 -57
  31. cognite/neat/_rules/importers/_dtdl2rules/dtdl_importer.py +5 -2
  32. cognite/neat/_rules/importers/_rdf/_base.py +10 -8
  33. cognite/neat/_rules/importers/_rdf/_imf2rules.py +4 -0
  34. cognite/neat/_rules/importers/_rdf/_inference2rules.py +7 -0
  35. cognite/neat/_rules/importers/_rdf/_owl2rules.py +4 -0
  36. cognite/neat/_rules/importers/_spreadsheet2rules.py +17 -8
  37. cognite/neat/_rules/importers/_yaml2rules.py +21 -7
  38. cognite/neat/_rules/models/_base_input.py +1 -1
  39. cognite/neat/_rules/models/_base_rules.py +9 -1
  40. cognite/neat/_rules/models/dms/_rules.py +4 -0
  41. cognite/neat/_rules/models/dms/_rules_input.py +9 -0
  42. cognite/neat/_rules/models/entities/_wrapped.py +10 -5
  43. cognite/neat/_rules/models/information/_rules.py +4 -0
  44. cognite/neat/_rules/models/information/_rules_input.py +9 -0
  45. cognite/neat/_rules/models/mapping/_classic2core.py +2 -5
  46. cognite/neat/_rules/models/mapping/_classic2core.yaml +239 -38
  47. cognite/neat/_rules/transformers/__init__.py +13 -6
  48. cognite/neat/_rules/transformers/_base.py +41 -65
  49. cognite/neat/_rules/transformers/_converters.py +404 -234
  50. cognite/neat/_rules/transformers/_mapping.py +93 -72
  51. cognite/neat/_rules/transformers/_verification.py +50 -38
  52. cognite/neat/_session/_base.py +32 -121
  53. cognite/neat/_session/_inspect.py +5 -3
  54. cognite/neat/_session/_mapping.py +17 -105
  55. cognite/neat/_session/_prepare.py +138 -268
  56. cognite/neat/_session/_read.py +39 -195
  57. cognite/neat/_session/_set.py +6 -30
  58. cognite/neat/_session/_show.py +40 -21
  59. cognite/neat/_session/_state.py +49 -107
  60. cognite/neat/_session/_to.py +44 -33
  61. cognite/neat/_shared.py +23 -2
  62. cognite/neat/_store/_provenance.py +3 -82
  63. cognite/neat/_store/_rules_store.py +368 -10
  64. cognite/neat/_store/exceptions.py +23 -0
  65. cognite/neat/_utils/graph_transformations_report.py +36 -0
  66. cognite/neat/_utils/rdf_.py +8 -0
  67. cognite/neat/_utils/reader/_base.py +27 -0
  68. cognite/neat/_utils/spreadsheet.py +5 -4
  69. cognite/neat/_version.py +1 -1
  70. {cognite_neat-0.103.1.dist-info → cognite_neat-0.105.0.dist-info}/METADATA +3 -2
  71. cognite_neat-0.105.0.dist-info/RECORD +179 -0
  72. {cognite_neat-0.103.1.dist-info → cognite_neat-0.105.0.dist-info}/WHEEL +1 -1
  73. cognite/neat/_app/api/__init__.py +0 -0
  74. cognite/neat/_app/api/asgi/metrics.py +0 -4
  75. cognite/neat/_app/api/configuration.py +0 -98
  76. cognite/neat/_app/api/context_manager/__init__.py +0 -3
  77. cognite/neat/_app/api/context_manager/manager.py +0 -16
  78. cognite/neat/_app/api/data_classes/__init__.py +0 -0
  79. cognite/neat/_app/api/data_classes/rest.py +0 -59
  80. cognite/neat/_app/api/explorer.py +0 -66
  81. cognite/neat/_app/api/routers/configuration.py +0 -25
  82. cognite/neat/_app/api/routers/crud.py +0 -102
  83. cognite/neat/_app/api/routers/metrics.py +0 -10
  84. cognite/neat/_app/api/routers/workflows.py +0 -224
  85. cognite/neat/_app/api/utils/__init__.py +0 -0
  86. cognite/neat/_app/api/utils/data_mapping.py +0 -17
  87. cognite/neat/_app/api/utils/logging.py +0 -26
  88. cognite/neat/_app/api/utils/query_templates.py +0 -92
  89. cognite/neat/_app/main.py +0 -17
  90. cognite/neat/_app/monitoring/__init__.py +0 -0
  91. cognite/neat/_app/monitoring/metrics.py +0 -69
  92. cognite/neat/_app/ui/index.html +0 -1
  93. cognite/neat/_app/ui/neat-app/.gitignore +0 -23
  94. cognite/neat/_app/ui/neat-app/README.md +0 -70
  95. cognite/neat/_app/ui/neat-app/build/asset-manifest.json +0 -14
  96. cognite/neat/_app/ui/neat-app/build/favicon.ico +0 -0
  97. cognite/neat/_app/ui/neat-app/build/img/architect-icon.svg +0 -116
  98. cognite/neat/_app/ui/neat-app/build/img/developer-icon.svg +0 -112
  99. cognite/neat/_app/ui/neat-app/build/img/sme-icon.svg +0 -34
  100. cognite/neat/_app/ui/neat-app/build/index.html +0 -1
  101. cognite/neat/_app/ui/neat-app/build/logo192.png +0 -0
  102. cognite/neat/_app/ui/neat-app/build/manifest.json +0 -25
  103. cognite/neat/_app/ui/neat-app/build/robots.txt +0 -3
  104. cognite/neat/_app/ui/neat-app/build/static/css/main.72e3d92e.css +0 -2
  105. cognite/neat/_app/ui/neat-app/build/static/css/main.72e3d92e.css.map +0 -1
  106. cognite/neat/_app/ui/neat-app/build/static/js/main.5a52cf09.js +0 -3
  107. cognite/neat/_app/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt +0 -88
  108. cognite/neat/_app/ui/neat-app/build/static/js/main.5a52cf09.js.map +0 -1
  109. cognite/neat/_app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -1
  110. cognite/neat/_app/ui/neat-app/package-lock.json +0 -18306
  111. cognite/neat/_app/ui/neat-app/package.json +0 -62
  112. cognite/neat/_app/ui/neat-app/public/favicon.ico +0 -0
  113. cognite/neat/_app/ui/neat-app/public/img/architect-icon.svg +0 -116
  114. cognite/neat/_app/ui/neat-app/public/img/developer-icon.svg +0 -112
  115. cognite/neat/_app/ui/neat-app/public/img/sme-icon.svg +0 -34
  116. cognite/neat/_app/ui/neat-app/public/index.html +0 -43
  117. cognite/neat/_app/ui/neat-app/public/logo192.png +0 -0
  118. cognite/neat/_app/ui/neat-app/public/manifest.json +0 -25
  119. cognite/neat/_app/ui/neat-app/public/robots.txt +0 -3
  120. cognite/neat/_app/ui/neat-app/src/App.css +0 -38
  121. cognite/neat/_app/ui/neat-app/src/App.js +0 -17
  122. cognite/neat/_app/ui/neat-app/src/App.test.js +0 -8
  123. cognite/neat/_app/ui/neat-app/src/MainContainer.tsx +0 -70
  124. cognite/neat/_app/ui/neat-app/src/components/JsonViewer.tsx +0 -43
  125. cognite/neat/_app/ui/neat-app/src/components/LocalUploader.tsx +0 -124
  126. cognite/neat/_app/ui/neat-app/src/components/OverviewComponentEditorDialog.tsx +0 -63
  127. cognite/neat/_app/ui/neat-app/src/components/StepEditorDialog.tsx +0 -511
  128. cognite/neat/_app/ui/neat-app/src/components/TabPanel.tsx +0 -36
  129. cognite/neat/_app/ui/neat-app/src/components/Utils.tsx +0 -56
  130. cognite/neat/_app/ui/neat-app/src/components/WorkflowDeleteDialog.tsx +0 -60
  131. cognite/neat/_app/ui/neat-app/src/components/WorkflowExecutionReport.tsx +0 -112
  132. cognite/neat/_app/ui/neat-app/src/components/WorkflowImportExportDialog.tsx +0 -67
  133. cognite/neat/_app/ui/neat-app/src/components/WorkflowMetadataDialog.tsx +0 -79
  134. cognite/neat/_app/ui/neat-app/src/index.css +0 -13
  135. cognite/neat/_app/ui/neat-app/src/index.js +0 -13
  136. cognite/neat/_app/ui/neat-app/src/logo.svg +0 -1
  137. cognite/neat/_app/ui/neat-app/src/reportWebVitals.js +0 -13
  138. cognite/neat/_app/ui/neat-app/src/setupTests.js +0 -5
  139. cognite/neat/_app/ui/neat-app/src/types/WorkflowTypes.ts +0 -388
  140. cognite/neat/_app/ui/neat-app/src/views/AboutView.tsx +0 -61
  141. cognite/neat/_app/ui/neat-app/src/views/ConfigView.tsx +0 -184
  142. cognite/neat/_app/ui/neat-app/src/views/GlobalConfigView.tsx +0 -180
  143. cognite/neat/_app/ui/neat-app/src/views/WorkflowView.tsx +0 -570
  144. cognite/neat/_app/ui/neat-app/tsconfig.json +0 -27
  145. cognite/neat/_rules/transformers/_pipelines.py +0 -70
  146. cognite/neat/_workflows/__init__.py +0 -17
  147. cognite/neat/_workflows/base.py +0 -590
  148. cognite/neat/_workflows/cdf_store.py +0 -393
  149. cognite/neat/_workflows/examples/Export_DMS/workflow.yaml +0 -89
  150. cognite/neat/_workflows/examples/Export_Semantic_Data_Model/workflow.yaml +0 -66
  151. cognite/neat/_workflows/examples/Import_DMS/workflow.yaml +0 -65
  152. cognite/neat/_workflows/examples/Validate_Rules/workflow.yaml +0 -67
  153. cognite/neat/_workflows/examples/Validate_Solution_Model/workflow.yaml +0 -64
  154. cognite/neat/_workflows/manager.py +0 -292
  155. cognite/neat/_workflows/model.py +0 -203
  156. cognite/neat/_workflows/steps/__init__.py +0 -0
  157. cognite/neat/_workflows/steps/data_contracts.py +0 -109
  158. cognite/neat/_workflows/steps/lib/__init__.py +0 -0
  159. cognite/neat/_workflows/steps/lib/current/__init__.py +0 -6
  160. cognite/neat/_workflows/steps/lib/current/graph_extractor.py +0 -100
  161. cognite/neat/_workflows/steps/lib/current/graph_loader.py +0 -51
  162. cognite/neat/_workflows/steps/lib/current/graph_store.py +0 -48
  163. cognite/neat/_workflows/steps/lib/current/rules_exporter.py +0 -537
  164. cognite/neat/_workflows/steps/lib/current/rules_importer.py +0 -398
  165. cognite/neat/_workflows/steps/lib/current/rules_validator.py +0 -106
  166. cognite/neat/_workflows/steps/lib/io/__init__.py +0 -1
  167. cognite/neat/_workflows/steps/lib/io/io_steps.py +0 -393
  168. cognite/neat/_workflows/steps/step_model.py +0 -79
  169. cognite/neat/_workflows/steps_registry.py +0 -218
  170. cognite/neat/_workflows/tasks.py +0 -18
  171. cognite/neat/_workflows/triggers.py +0 -169
  172. cognite/neat/_workflows/utils.py +0 -19
  173. cognite_neat-0.103.1.dist-info/RECORD +0 -275
  174. {cognite_neat-0.103.1.dist-info → cognite_neat-0.105.0.dist-info}/LICENSE +0 -0
  175. {cognite_neat-0.103.1.dist-info → cognite_neat-0.105.0.dist-info}/entry_points.txt +0 -0
@@ -1,15 +1,14 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import Literal, cast
3
3
 
4
- from rdflib import URIRef
5
-
6
4
  from cognite.neat._issues import IssueList
7
- from cognite.neat._rules._shared import JustRules, ReadRules, VerifiedRules
8
- from cognite.neat._rules.models.dms._rules import DMSRules
9
- from cognite.neat._rules.models.information._rules import InformationRules
10
- from cognite.neat._rules.models.information._rules_input import InformationInputRules
11
- from cognite.neat._store import NeatGraphStore
12
- from cognite.neat._store._provenance import Change, Provenance
5
+ from cognite.neat._rules.importers import BaseImporter, InferenceImporter
6
+ from cognite.neat._rules.models import DMSRules, InformationRules
7
+ from cognite.neat._rules.transformers import RulesTransformer, ToExtensionModel
8
+ from cognite.neat._store import NeatGraphStore, NeatRulesStore
9
+ from cognite.neat._store._rules_store import ModelEntity
10
+ from cognite.neat._utils.rdf_ import uri_display_name
11
+ from cognite.neat._utils.text import humanize_collection
13
12
  from cognite.neat._utils.upload import UploadResultList
14
13
 
15
14
  from .exceptions import NeatSessionError
@@ -18,7 +17,48 @@ from .exceptions import NeatSessionError
18
17
  class SessionState:
19
18
  def __init__(self, store_type: Literal["memory", "oxigraph"]) -> None:
20
19
  self.instances = InstancesState(store_type)
21
- self.data_model = DataModelState()
20
+ self.rule_store = NeatRulesStore()
21
+ self.last_reference: DMSRules | InformationRules | None = None
22
+
23
+ def rule_transform(self, *transformer: RulesTransformer) -> IssueList:
24
+ if not transformer:
25
+ raise NeatSessionError("No transformers provided.")
26
+ first_transformer = transformer[0]
27
+ pruned = self.rule_store.prune_until_compatible(first_transformer)
28
+ if pruned:
29
+ type_hint = first_transformer.transform_type_hint()
30
+ action = uri_display_name(first_transformer.agent.id_)
31
+ location = cast(ModelEntity, self.rule_store.provenance[-1].target_entity).display_name
32
+ expected = humanize_collection([hint.display_type_name() for hint in type_hint]) # type: ignore[attr-defined]
33
+ step_str = "step" if len(pruned) == 1 else "steps"
34
+ print(
35
+ f"The {action} actions expects a {expected}. "
36
+ f"Moving back {len(pruned)} {step_str} to the last {location}."
37
+ )
38
+ if (
39
+ any(isinstance(t, ToExtensionModel) for t in transformer)
40
+ and isinstance(self.rule_store.provenance[-1].target_entity, ModelEntity)
41
+ and isinstance(self.rule_store.provenance[-1].target_entity.result, DMSRules | InformationRules)
42
+ ):
43
+ self.last_reference = self.rule_store.provenance[-1].target_entity.result
44
+
45
+ start = cast(ModelEntity, self.rule_store.provenance[-1].target_entity).display_name
46
+ issues = self.rule_store.transform(*transformer)
47
+ end = cast(ModelEntity, self.rule_store.provenance[-1].target_entity).display_name
48
+ issues.action = f"{start} → {end}"
49
+ issues.hint = "Use the .inspect.issues() for more details."
50
+ return issues
51
+
52
+ def rule_import(self, importer: BaseImporter) -> IssueList:
53
+ issues = self.rule_store.import_(importer)
54
+ result = cast(ModelEntity, self.rule_store.provenance[-1].target_entity).display_name
55
+ if isinstance(importer, InferenceImporter):
56
+ issues.action = f"Inferred {result}"
57
+ else:
58
+ issues.action = f"Read {result}"
59
+ if issues:
60
+ issues.hint = "Use the .inspect.issues() for more details."
61
+ return issues
22
62
 
23
63
 
24
64
  @dataclass
@@ -48,101 +88,3 @@ class InstancesState:
48
88
  "No outcome available. Try using [bold].to.cdf.instances[/bold] to upload a data minstances."
49
89
  )
50
90
  return self.outcome[-1]
51
-
52
-
53
- @dataclass
54
- class DataModelState:
55
- _rules: dict[URIRef, ReadRules | JustRules | VerifiedRules] = field(init=False, default_factory=dict)
56
- issue_lists: list[IssueList] = field(default_factory=list)
57
- provenance: Provenance = field(default_factory=Provenance)
58
- outcome: list[UploadResultList] = field(default_factory=list)
59
-
60
- def write(self, rules: ReadRules | JustRules | VerifiedRules, change: Change) -> None:
61
- if change.target_entity.id_ in self._rules:
62
- raise NeatSessionError(f"Data model <{change.target_entity.id_}> already exists.")
63
-
64
- else:
65
- self._rules[change.target_entity.id_] = rules
66
- self.provenance.append(change)
67
-
68
- def read(self, id_: URIRef) -> ReadRules | JustRules | VerifiedRules:
69
- if id_ not in self._rules:
70
- raise NeatSessionError(f"Data model <{id_}> not found.")
71
- return self._rules[id_]
72
-
73
- @property
74
- def unverified_rules(self) -> dict[URIRef, ReadRules]:
75
- return {id_: rules for id_, rules in self._rules.items() if isinstance(rules, ReadRules)}
76
-
77
- @property
78
- def verified_rules(self) -> dict[URIRef, VerifiedRules]:
79
- return {id_: rules for id_, rules in self._rules.items() if isinstance(rules, VerifiedRules)}
80
-
81
- @property
82
- def last_unverified_rule(self) -> tuple[URIRef, ReadRules]:
83
- if not self.unverified_rules:
84
- raise NeatSessionError("No data model available. Try using [bold].read[/bold] to load a data model.")
85
- return next(reversed(self.unverified_rules.items()))
86
-
87
- @property
88
- def last_info_unverified_rule(self) -> tuple[URIRef, ReadRules]:
89
- if self.unverified_rules:
90
- for id_, rule in reversed(self.unverified_rules.items()):
91
- if isinstance(rule.rules, InformationInputRules):
92
- return id_, rule
93
-
94
- raise NeatSessionError("No data model available. Try using [bold].read[/bold] to load a data model.")
95
-
96
- @property
97
- def last_verified_rule(self) -> tuple[URIRef, VerifiedRules]:
98
- if not self.verified_rules:
99
- raise NeatSessionError(
100
- "No data model available to verify. Try using [bold].read[/bold] to load a data model."
101
- )
102
- return next(reversed(self.verified_rules.items()))
103
-
104
- @property
105
- def last_verified_information_rules(self) -> tuple[URIRef, InformationRules]:
106
- if self.verified_rules:
107
- for id_, rules in reversed(self.verified_rules.items()):
108
- if isinstance(rules, InformationRules):
109
- return id_, rules
110
-
111
- raise NeatSessionError(
112
- "No verified information data model. Try using [bold].verify()[/bold]"
113
- " to convert unverified information model to verified information model."
114
- )
115
-
116
- @property
117
- def last_verified_dms_rules(self) -> tuple[URIRef, DMSRules]:
118
- if self.verified_rules:
119
- for id_, rules in reversed(self.verified_rules.items()):
120
- if isinstance(rules, DMSRules):
121
- return id_, rules
122
-
123
- raise NeatSessionError(
124
- 'No verified DMS data model. Try using [bold].convert("DMS")[/bold]'
125
- " to convert verified information model to verified DMS model."
126
- )
127
-
128
- @property
129
- def has_unverified_rules(self) -> bool:
130
- return bool(self.unverified_rules)
131
-
132
- @property
133
- def has_verified_rules(self) -> bool:
134
- return bool(self.verified_rules)
135
-
136
- @property
137
- def last_issues(self) -> IssueList:
138
- if not self.issue_lists:
139
- raise NeatSessionError("No issues available. Try using [bold].verify()[/bold] to verify a data model.")
140
- return self.issue_lists[-1]
141
-
142
- @property
143
- def last_outcome(self) -> UploadResultList:
144
- if not self.outcome:
145
- raise NeatSessionError(
146
- "No outcome available. Try using [bold].to.cdf.data_model[/bold] to upload a data model."
147
- )
148
- return self.outcome[-1]
@@ -5,13 +5,14 @@ from typing import Any, Literal, overload
5
5
  from cognite.client.data_classes.data_modeling import SpaceApply
6
6
 
7
7
  from cognite.neat._client import NeatClient
8
+ from cognite.neat._constants import COGNITE_MODELS
8
9
  from cognite.neat._graph import loaders
9
- from cognite.neat._issues import IssueList, catch_warnings
10
10
  from cognite.neat._rules import exporters
11
11
  from cognite.neat._rules._constants import PATTERNS
12
12
  from cognite.neat._rules._shared import VerifiedRules
13
13
  from cognite.neat._rules.exporters._rules2dms import Component
14
- from cognite.neat._utils.upload import UploadResultCore, UploadResultList
14
+ from cognite.neat._rules.models.dms import DMSMetadata
15
+ from cognite.neat._utils.upload import UploadResultList
15
16
 
16
17
  from ._state import SessionState
17
18
  from .exceptions import NeatSessionError, session_class_wrapper
@@ -32,45 +33,59 @@ class ToAPI:
32
33
  def excel(
33
34
  self,
34
35
  io: Any,
35
- model: Literal["dms", "information", "logical", "physical"] | None,
36
+ include_reference: bool = True,
36
37
  ) -> None:
37
38
  """Export the verified data model to Excel.
38
39
 
39
40
  Args:
40
41
  io: The file path or file-like object to write the Excel file to.
41
- model: The format of the data model to export. Defaults to None.
42
+ include_reference: If True, the reference data model will be included. Defaults to True.
43
+ Note that this only applies if you have created the data model using the
44
+ .to_enterprise(), .to_solution(), or .to_data_product() methods.
42
45
 
43
46
  Example:
44
47
  Export information model to excel rules sheet
45
48
  ```python
46
49
  information_rules_file_name = "information_rules.xlsx"
47
- neat.to.excel(information_rules_file_name, model="information")
50
+ neat.to.excel(information_rules_file_name)
48
51
  ```
49
52
 
50
53
  Example:
51
- Export data model to excel rules sheet
54
+ Read CogniteCore model, convert it to an enterprise model, and export it to an excel file
52
55
  ```python
56
+ client = CogniteClient()
57
+ neat = NeatSession(client)
58
+
59
+ neat.read.cdf(("cdf_cdm", "CogniteCore", "v1"))
60
+ neat.verify()
61
+ neat.prepare.data_model.to_enterprise(
62
+ data_model_id=("sp_doctrino_space", "ExtensionCore", "v1"),
63
+ org_name="MyOrg",
64
+ move_connections=True
65
+ )
53
66
  dms_rules_file_name = "dms_rules.xlsx"
54
- neat.to.excel(information_rules_file_name, model="dms")
67
+ neat.to.excel(dms_rules_file_name, include_reference=True)
55
68
  ```
56
69
  """
57
- exporter = exporters.ExcelExporter(styling="maximal")
58
- rules: VerifiedRules
59
- if model == "information" or model == "logical":
60
- rules = self._state.data_model.last_verified_information_rules[1]
61
- elif model == "dms" or model == "physical":
62
- rules = self._state.data_model.last_verified_dms_rules[1]
63
- else:
64
- rules = self._state.data_model.last_verified_rule[1]
65
-
66
- exporter.export_to_file(rules, Path(io))
67
- return None
70
+ reference_rules_with_prefix: tuple[VerifiedRules, str] | None = None
71
+ if include_reference and self._state.last_reference:
72
+ if (
73
+ isinstance(self._state.last_reference.metadata, DMSMetadata)
74
+ and self._state.last_reference.metadata.as_data_model_id() in COGNITE_MODELS
75
+ ):
76
+ prefix = "CDM"
77
+ else:
78
+ prefix = "Ref"
79
+ reference_rules_with_prefix = self._state.last_reference, prefix
80
+
81
+ exporter = exporters.ExcelExporter(styling="maximal", reference_rules_with_prefix=reference_rules_with_prefix)
82
+ return self._state.rule_store.export_to_file(exporter, Path(io))
68
83
 
69
84
  @overload
70
- def yaml(self, io: None, format: Literal["neat"] = "neat") -> str: ...
85
+ def yaml(self, io: None, format: Literal["neat"] = "neat", skip_system_spaces: bool = True) -> str: ...
71
86
 
72
87
  @overload
73
- def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None: ...
88
+ def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat", skip_system_spaces: bool = True) -> None: ...
74
89
 
75
90
  def yaml(
76
91
  self, io: Any | None = None, format: Literal["neat", "toolkit"] = "neat", skip_system_spaces: bool = True
@@ -112,22 +127,22 @@ class ToAPI:
112
127
  """
113
128
  if format == "neat":
114
129
  exporter = exporters.YAMLExporter()
115
- last_verified = self._state.data_model.last_verified_rule[1]
116
130
  if io is None:
117
- return exporter.export(last_verified)
131
+ return self._state.rule_store.export(exporter)
118
132
 
119
- exporter.export_to_file(last_verified, Path(io))
133
+ self._state.rule_store.export_to_file(exporter, Path(io))
120
134
  elif format == "toolkit":
121
135
  if io is None or not isinstance(io, str | Path):
122
136
  raise NeatSessionError(
123
137
  "Please provide a zip file or directory path to write the YAML files to."
124
138
  "This is required for the 'toolkit' format."
125
139
  )
126
- dms_rule = self._state.data_model.last_verified_dms_rules[1]
127
140
  user_path = Path(io)
128
141
  if user_path.suffix == "" and not user_path.exists():
129
142
  user_path.mkdir(parents=True)
130
- exporters.DMSExporter(remove_cdf_spaces=skip_system_spaces).export_to_file(dms_rule, user_path)
143
+ self._state.rule_store.export_to_file(
144
+ exporters.DMSExporter(remove_cdf_spaces=skip_system_spaces), user_path
145
+ )
131
146
  else:
132
147
  raise NeatSessionError("Please provide a valid format. 'neat' or 'toolkit'")
133
148
 
@@ -154,9 +169,9 @@ class CDFToAPI:
154
169
  if not self._client:
155
170
  raise NeatSessionError("No CDF client provided!")
156
171
 
157
- space = space or f"{self._state.data_model.last_verified_dms_rules[1].metadata.space}_instances"
172
+ space = space or f"{self._state.rule_store.last_verified_dms_rules.metadata.space}_instances"
158
173
 
159
- if space and space == self._state.data_model.last_verified_dms_rules[1].metadata.space:
174
+ if space and space == self._state.rule_store.last_verified_dms_rules.metadata.space:
160
175
  raise NeatSessionError("Space for instances must be different from the data model space.")
161
176
  elif not PATTERNS.space_compliance.match(str(space)):
162
177
  raise NeatSessionError("Please provide a valid space name. {PATTERNS.space_compliance.pattern}")
@@ -165,7 +180,7 @@ class CDFToAPI:
165
180
  self._client.data_modeling.spaces.apply(SpaceApply(space=space))
166
181
 
167
182
  loader = loaders.DMSLoader.from_rules(
168
- self._state.data_model.last_verified_dms_rules[1],
183
+ self._state.rule_store.last_verified_dms_rules,
169
184
  self._state.instances.store,
170
185
  instance_space=space,
171
186
  client=self._client,
@@ -207,10 +222,6 @@ class CDFToAPI:
207
222
  if not self._client:
208
223
  raise NeatSessionError("No client provided!")
209
224
 
210
- conversion_issues = IssueList(action="to.cdf.data_model")
211
- with catch_warnings(conversion_issues):
212
- result = exporter.export_to_cdf(self._state.data_model.last_verified_dms_rules[1], self._client, dry_run)
213
- result.insert(0, UploadResultCore(name="schema", issues=conversion_issues))
214
- self._state.data_model.outcome.append(result)
225
+ result = self._state.rule_store.export_to_cdf(exporter, self._client, dry_run)
215
226
  print("You can inspect the details with the .inspect.outcome.data_model(...) method.")
216
227
  return result
cognite/neat/_shared.py CHANGED
@@ -1,11 +1,17 @@
1
+ import sys
1
2
  from abc import abstractmethod
2
- from collections.abc import Hashable, Sequence
3
+ from collections.abc import Hashable, Iterator, Sequence
3
4
  from dataclasses import dataclass
4
- from typing import Any, TypeAlias, TypeVar
5
+ from typing import Any, SupportsIndex, TypeAlias, TypeVar, overload
5
6
 
6
7
  import pandas as pd
7
8
  from rdflib import Literal, URIRef
8
9
 
10
+ if sys.version_info <= (3, 11):
11
+ from typing_extensions import Self
12
+ else:
13
+ from typing import Self
14
+
9
15
  T_ID = TypeVar("T_ID", bound=Hashable)
10
16
 
11
17
 
@@ -51,6 +57,21 @@ class NeatList(list, Sequence[T_NeatObject]):
51
57
  def _repr_html_(self) -> str:
52
58
  return self.to_pandas()._repr_html_() # type: ignore[operator]
53
59
 
60
+ # Implemented to get correct type hints
61
+ def __iter__(self) -> Iterator[T_NeatObject]:
62
+ return super().__iter__()
63
+
64
+ @overload
65
+ def __getitem__(self, index: SupportsIndex) -> T_NeatObject: ...
66
+
67
+ @overload
68
+ def __getitem__(self, index: slice) -> Self: ...
69
+
70
+ def __getitem__(self, index: SupportsIndex | slice, /) -> T_NeatObject | Self:
71
+ if isinstance(index, slice):
72
+ return type(self)(super().__getitem__(index))
73
+ return super().__getitem__(index)
74
+
54
75
 
55
76
  Triple: TypeAlias = tuple[URIRef, URIRef, Literal | URIRef]
56
77
  InstanceType: TypeAlias = URIRef
@@ -20,14 +20,12 @@ import uuid
20
20
  from collections.abc import Iterable, Sequence
21
21
  from dataclasses import dataclass, field
22
22
  from datetime import datetime
23
- from typing import Generic, Optional, TypeVar
23
+ from typing import Optional
24
24
 
25
- from cognite.client.data_classes.data_modeling import DataModelId, DataModelIdentifier
26
25
  from rdflib import PROV, RDF, Literal, URIRef
27
26
 
28
27
  from cognite.neat._constants import CDF_NAMESPACE, DEFAULT_NAMESPACE
29
28
  from cognite.neat._issues import IssueList
30
- from cognite.neat._rules._shared import JustRules, ReadRules, VerifiedRules
31
29
  from cognite.neat._shared import FrozenNeatObject, NeatList, Triple
32
30
 
33
31
 
@@ -72,45 +70,6 @@ class Entity:
72
70
 
73
71
  return output
74
72
 
75
- @classmethod
76
- def from_data_model_id(cls, data_model_id: DataModelIdentifier) -> "Entity":
77
- data_model_id = DataModelId.load(data_model_id)
78
-
79
- return cls(
80
- was_attributed_to=CDF_AGENT,
81
- id_=CDF_NAMESPACE[
82
- f"dms/data-model/{data_model_id.space}/{data_model_id.external_id}/{data_model_id.version}"
83
- ],
84
- )
85
-
86
- @classmethod
87
- def from_rules(
88
- cls,
89
- rules: ReadRules | JustRules | VerifiedRules,
90
- agent: Agent | None = None,
91
- activity: "Activity | None" = None,
92
- ) -> "Entity":
93
- agent = agent or UNKNOWN_AGENT
94
- if isinstance(rules, VerifiedRules):
95
- return cls(
96
- was_attributed_to=agent,
97
- was_generated_by=activity,
98
- id_=rules.metadata.identifier,
99
- )
100
-
101
- elif isinstance(rules, ReadRules | JustRules) and rules.rules is not None:
102
- return cls(
103
- was_attributed_to=agent,
104
- was_generated_by=activity,
105
- id_=rules.rules.metadata.identifier,
106
- )
107
- else:
108
- return cls(
109
- was_attributed_to=agent,
110
- was_generated_by=activity,
111
- id_=DEFAULT_NAMESPACE["unknown-entity"],
112
- )
113
-
114
73
  @classmethod
115
74
  def new_unknown_entity(cls) -> "Entity":
116
75
  return cls(
@@ -119,15 +78,8 @@ class Entity:
119
78
  )
120
79
 
121
80
 
122
- T_Result = TypeVar("T_Result")
123
-
124
-
125
- @dataclass(frozen=True)
126
- class ModelEntity(Entity, Generic[T_Result]):
127
- result: T_Result | None = None
128
-
129
-
130
81
  INSTANCES_ENTITY = Entity(was_attributed_to=NEAT_AGENT, id_=CDF_NAMESPACE["instances"])
82
+ EMPTY_ENTITY = Entity(was_attributed_to=NEAT_AGENT, id_=DEFAULT_NAMESPACE["empty-entity"])
131
83
 
132
84
 
133
85
  @dataclass(frozen=True)
@@ -192,34 +144,6 @@ class Change(FrozenNeatObject):
192
144
  description=description,
193
145
  )
194
146
 
195
- @classmethod
196
- def from_rules_activity(
197
- cls,
198
- rules: ReadRules | JustRules | VerifiedRules,
199
- agent: Agent,
200
- start: datetime,
201
- end: datetime,
202
- description: str,
203
- source_entity: Entity | None = None,
204
- ) -> "Change":
205
- source_entity = source_entity or Entity.new_unknown_entity()
206
- activity = Activity(
207
- started_at_time=start,
208
- ended_at_time=end,
209
- was_associated_with=agent,
210
- used=source_entity,
211
- )
212
-
213
- target_entity = Entity.from_rules(rules, agent, activity)
214
-
215
- return cls(
216
- agent=agent,
217
- activity=activity,
218
- target_entity=target_entity,
219
- description=description,
220
- source_entity=source_entity,
221
- )
222
-
223
147
  def dump(self, aggregate: bool = True) -> dict[str, str]:
224
148
  return {
225
149
  "Source Entity": self.source_entity.id_,
@@ -230,11 +154,8 @@ class Change(FrozenNeatObject):
230
154
  }
231
155
 
232
156
 
233
- T_Change = TypeVar("T_Change", bound=Change)
234
-
235
-
236
157
  class Provenance(NeatList[Change]):
237
- def __init__(self, changes: Sequence[T_Change] | None = None):
158
+ def __init__(self, changes: Sequence[Change] | None = None):
238
159
  super().__init__(changes or [])
239
160
 
240
161
  def activity_took_place(self, activity: str) -> bool: