cognite-neat 0.104.0__py3-none-any.whl → 0.105.1__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 (143) 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 +57 -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 +1 -1
  10. cognite/neat/_graph/loaders/_rdf2dms.py +31 -5
  11. cognite/neat/_graph/transformers/__init__.py +3 -1
  12. cognite/neat/_graph/transformers/_classic_cdf.py +39 -51
  13. cognite/neat/_graph/transformers/_rdfpath.py +14 -15
  14. cognite/neat/_graph/transformers/_value_type.py +72 -0
  15. cognite/neat/_issues/__init__.py +0 -2
  16. cognite/neat/_issues/_base.py +19 -35
  17. cognite/neat/_issues/warnings/__init__.py +6 -1
  18. cognite/neat/_issues/warnings/_general.py +7 -0
  19. cognite/neat/_issues/warnings/_properties.py +11 -0
  20. cognite/neat/_issues/warnings/_resources.py +11 -0
  21. cognite/neat/_rules/exporters/_rules2dms.py +35 -1
  22. cognite/neat/_rules/exporters/_rules2excel.py +2 -2
  23. cognite/neat/_rules/importers/_dms2rules.py +66 -55
  24. cognite/neat/_rules/models/_base_rules.py +4 -1
  25. cognite/neat/_rules/models/entities/_wrapped.py +10 -5
  26. cognite/neat/_rules/models/mapping/_classic2core.yaml +239 -38
  27. cognite/neat/_rules/transformers/__init__.py +8 -2
  28. cognite/neat/_rules/transformers/_converters.py +271 -188
  29. cognite/neat/_rules/transformers/_mapping.py +75 -59
  30. cognite/neat/_rules/transformers/_verification.py +2 -3
  31. cognite/neat/_session/_inspect.py +3 -1
  32. cognite/neat/_session/_prepare.py +112 -24
  33. cognite/neat/_session/_read.py +33 -70
  34. cognite/neat/_session/_state.py +2 -2
  35. cognite/neat/_session/_to.py +2 -2
  36. cognite/neat/_store/_rules_store.py +4 -8
  37. cognite/neat/_utils/reader/_base.py +27 -0
  38. cognite/neat/_version.py +1 -1
  39. {cognite_neat-0.104.0.dist-info → cognite_neat-0.105.1.dist-info}/METADATA +4 -3
  40. cognite_neat-0.105.1.dist-info/RECORD +179 -0
  41. {cognite_neat-0.104.0.dist-info → cognite_neat-0.105.1.dist-info}/WHEEL +1 -1
  42. cognite/neat/_app/api/__init__.py +0 -0
  43. cognite/neat/_app/api/asgi/metrics.py +0 -4
  44. cognite/neat/_app/api/configuration.py +0 -98
  45. cognite/neat/_app/api/context_manager/__init__.py +0 -3
  46. cognite/neat/_app/api/context_manager/manager.py +0 -16
  47. cognite/neat/_app/api/data_classes/__init__.py +0 -0
  48. cognite/neat/_app/api/data_classes/rest.py +0 -59
  49. cognite/neat/_app/api/explorer.py +0 -66
  50. cognite/neat/_app/api/routers/configuration.py +0 -25
  51. cognite/neat/_app/api/routers/crud.py +0 -102
  52. cognite/neat/_app/api/routers/metrics.py +0 -10
  53. cognite/neat/_app/api/routers/workflows.py +0 -224
  54. cognite/neat/_app/api/utils/__init__.py +0 -0
  55. cognite/neat/_app/api/utils/data_mapping.py +0 -17
  56. cognite/neat/_app/api/utils/logging.py +0 -26
  57. cognite/neat/_app/api/utils/query_templates.py +0 -92
  58. cognite/neat/_app/main.py +0 -17
  59. cognite/neat/_app/monitoring/__init__.py +0 -0
  60. cognite/neat/_app/monitoring/metrics.py +0 -69
  61. cognite/neat/_app/ui/index.html +0 -1
  62. cognite/neat/_app/ui/neat-app/.gitignore +0 -23
  63. cognite/neat/_app/ui/neat-app/README.md +0 -70
  64. cognite/neat/_app/ui/neat-app/build/asset-manifest.json +0 -14
  65. cognite/neat/_app/ui/neat-app/build/favicon.ico +0 -0
  66. cognite/neat/_app/ui/neat-app/build/img/architect-icon.svg +0 -116
  67. cognite/neat/_app/ui/neat-app/build/img/developer-icon.svg +0 -112
  68. cognite/neat/_app/ui/neat-app/build/img/sme-icon.svg +0 -34
  69. cognite/neat/_app/ui/neat-app/build/index.html +0 -1
  70. cognite/neat/_app/ui/neat-app/build/logo192.png +0 -0
  71. cognite/neat/_app/ui/neat-app/build/manifest.json +0 -25
  72. cognite/neat/_app/ui/neat-app/build/robots.txt +0 -3
  73. cognite/neat/_app/ui/neat-app/build/static/css/main.72e3d92e.css +0 -2
  74. cognite/neat/_app/ui/neat-app/build/static/css/main.72e3d92e.css.map +0 -1
  75. cognite/neat/_app/ui/neat-app/build/static/js/main.5a52cf09.js +0 -3
  76. cognite/neat/_app/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt +0 -88
  77. cognite/neat/_app/ui/neat-app/build/static/js/main.5a52cf09.js.map +0 -1
  78. cognite/neat/_app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -1
  79. cognite/neat/_app/ui/neat-app/package-lock.json +0 -18306
  80. cognite/neat/_app/ui/neat-app/package.json +0 -62
  81. cognite/neat/_app/ui/neat-app/public/favicon.ico +0 -0
  82. cognite/neat/_app/ui/neat-app/public/img/architect-icon.svg +0 -116
  83. cognite/neat/_app/ui/neat-app/public/img/developer-icon.svg +0 -112
  84. cognite/neat/_app/ui/neat-app/public/img/sme-icon.svg +0 -34
  85. cognite/neat/_app/ui/neat-app/public/index.html +0 -43
  86. cognite/neat/_app/ui/neat-app/public/logo192.png +0 -0
  87. cognite/neat/_app/ui/neat-app/public/manifest.json +0 -25
  88. cognite/neat/_app/ui/neat-app/public/robots.txt +0 -3
  89. cognite/neat/_app/ui/neat-app/src/App.css +0 -38
  90. cognite/neat/_app/ui/neat-app/src/App.js +0 -17
  91. cognite/neat/_app/ui/neat-app/src/App.test.js +0 -8
  92. cognite/neat/_app/ui/neat-app/src/MainContainer.tsx +0 -70
  93. cognite/neat/_app/ui/neat-app/src/components/JsonViewer.tsx +0 -43
  94. cognite/neat/_app/ui/neat-app/src/components/LocalUploader.tsx +0 -124
  95. cognite/neat/_app/ui/neat-app/src/components/OverviewComponentEditorDialog.tsx +0 -63
  96. cognite/neat/_app/ui/neat-app/src/components/StepEditorDialog.tsx +0 -511
  97. cognite/neat/_app/ui/neat-app/src/components/TabPanel.tsx +0 -36
  98. cognite/neat/_app/ui/neat-app/src/components/Utils.tsx +0 -56
  99. cognite/neat/_app/ui/neat-app/src/components/WorkflowDeleteDialog.tsx +0 -60
  100. cognite/neat/_app/ui/neat-app/src/components/WorkflowExecutionReport.tsx +0 -112
  101. cognite/neat/_app/ui/neat-app/src/components/WorkflowImportExportDialog.tsx +0 -67
  102. cognite/neat/_app/ui/neat-app/src/components/WorkflowMetadataDialog.tsx +0 -79
  103. cognite/neat/_app/ui/neat-app/src/index.css +0 -13
  104. cognite/neat/_app/ui/neat-app/src/index.js +0 -13
  105. cognite/neat/_app/ui/neat-app/src/logo.svg +0 -1
  106. cognite/neat/_app/ui/neat-app/src/reportWebVitals.js +0 -13
  107. cognite/neat/_app/ui/neat-app/src/setupTests.js +0 -5
  108. cognite/neat/_app/ui/neat-app/src/types/WorkflowTypes.ts +0 -388
  109. cognite/neat/_app/ui/neat-app/src/views/AboutView.tsx +0 -61
  110. cognite/neat/_app/ui/neat-app/src/views/ConfigView.tsx +0 -184
  111. cognite/neat/_app/ui/neat-app/src/views/GlobalConfigView.tsx +0 -180
  112. cognite/neat/_app/ui/neat-app/src/views/WorkflowView.tsx +0 -570
  113. cognite/neat/_app/ui/neat-app/tsconfig.json +0 -27
  114. cognite/neat/_workflows/__init__.py +0 -17
  115. cognite/neat/_workflows/base.py +0 -590
  116. cognite/neat/_workflows/cdf_store.py +0 -393
  117. cognite/neat/_workflows/examples/Export_DMS/workflow.yaml +0 -89
  118. cognite/neat/_workflows/examples/Export_Semantic_Data_Model/workflow.yaml +0 -66
  119. cognite/neat/_workflows/examples/Import_DMS/workflow.yaml +0 -65
  120. cognite/neat/_workflows/examples/Validate_Rules/workflow.yaml +0 -67
  121. cognite/neat/_workflows/examples/Validate_Solution_Model/workflow.yaml +0 -64
  122. cognite/neat/_workflows/manager.py +0 -292
  123. cognite/neat/_workflows/model.py +0 -203
  124. cognite/neat/_workflows/steps/__init__.py +0 -0
  125. cognite/neat/_workflows/steps/data_contracts.py +0 -109
  126. cognite/neat/_workflows/steps/lib/__init__.py +0 -0
  127. cognite/neat/_workflows/steps/lib/current/__init__.py +0 -6
  128. cognite/neat/_workflows/steps/lib/current/graph_extractor.py +0 -100
  129. cognite/neat/_workflows/steps/lib/current/graph_loader.py +0 -51
  130. cognite/neat/_workflows/steps/lib/current/graph_store.py +0 -48
  131. cognite/neat/_workflows/steps/lib/current/rules_exporter.py +0 -537
  132. cognite/neat/_workflows/steps/lib/current/rules_importer.py +0 -323
  133. cognite/neat/_workflows/steps/lib/current/rules_validator.py +0 -106
  134. cognite/neat/_workflows/steps/lib/io/__init__.py +0 -1
  135. cognite/neat/_workflows/steps/lib/io/io_steps.py +0 -393
  136. cognite/neat/_workflows/steps/step_model.py +0 -79
  137. cognite/neat/_workflows/steps_registry.py +0 -218
  138. cognite/neat/_workflows/tasks.py +0 -18
  139. cognite/neat/_workflows/triggers.py +0 -169
  140. cognite/neat/_workflows/utils.py +0 -19
  141. cognite_neat-0.104.0.dist-info/RECORD +0 -276
  142. {cognite_neat-0.104.0.dist-info → cognite_neat-0.105.1.dist-info}/LICENSE +0 -0
  143. {cognite_neat-0.104.0.dist-info → cognite_neat-0.105.1.dist-info}/entry_points.txt +0 -0
@@ -1,537 +0,0 @@
1
- import time
2
- from pathlib import Path
3
- from typing import ClassVar, Literal, cast
4
-
5
- from cognite.neat._client import NeatClient
6
- from cognite.neat._issues.errors import WorkflowStepNotInitializedError
7
- from cognite.neat._rules import exporters
8
- from cognite.neat._rules._shared import DMSRules, InformationRules, VerifiedRules
9
- from cognite.neat._rules.models import RoleTypes
10
- from cognite.neat._rules.transformers import (
11
- DMSToInformation,
12
- InformationToDMS,
13
- )
14
- from cognite.neat._workflows.model import FlowMessage, StepExecutionStatus
15
- from cognite.neat._workflows.steps.data_contracts import CogniteClient, MultiRuleData
16
- from cognite.neat._workflows.steps.step_model import Configurable, Step
17
-
18
- __all__ = [
19
- "DeleteDataModelFromCDF",
20
- "RulesToDMS",
21
- "RulesToExcel",
22
- "RulesToOntology",
23
- "RulesToSHACL",
24
- "RulesToSemanticDataModel",
25
- ]
26
-
27
-
28
- CATEGORY = __name__.split(".")[-1].replace("_", " ").title()
29
-
30
-
31
- class DeleteDataModelFromCDF(Step):
32
- """
33
- This step deletes data model and its components from CDF
34
- """
35
-
36
- description = "This step deletes data model and its components from CDF."
37
- version = "private-beta"
38
- category = CATEGORY
39
-
40
- configurables: ClassVar[list[Configurable]] = [
41
- Configurable(
42
- name="Dry run",
43
- value="False",
44
- label=("Whether to perform a dry run of the deleter. "),
45
- options=["True", "False"],
46
- ),
47
- Configurable(
48
- name="Components",
49
- type="multi_select",
50
- value="",
51
- label="Select which DMS schema component(s) to be deleted from CDF",
52
- options=["spaces", "containers", "views", "data_models"],
53
- ),
54
- Configurable(
55
- name="Multi-space components deletion",
56
- value="False",
57
- label=(
58
- "Whether to delete only components belonging to the data model space"
59
- " (i.e. space define under Metadata sheet of Rules), "
60
- "or also additionally delete components outside of the data model space."
61
- ),
62
- options=["True", "False"],
63
- ),
64
- ]
65
-
66
- def run(self, rules: MultiRuleData, cdf_client: CogniteClient) -> FlowMessage: # type: ignore[override]
67
- if self.configs is None or self.data_store_path is None:
68
- raise WorkflowStepNotInitializedError(type(self).__name__)
69
- components_to_delete = {
70
- cast(Literal["spaces", "data_models", "views", "containers"], key)
71
- for key, value in self.complex_configs["Components"].items()
72
- if value
73
- }
74
- dry_run = self.configs["Dry run"] == "True"
75
- multi_space_components_delete: bool = self.configs["Multi-space components deletion"] == "True"
76
-
77
- if not components_to_delete:
78
- return FlowMessage(
79
- error_text="No DMS Schema components selected for removal! Please select minimum one!",
80
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
81
- )
82
- input_rules = rules.dms or rules.information
83
- if input_rules is None:
84
- return FlowMessage(
85
- error_text="Missing DMS or Information rules in the input data! "
86
- "Please ensure that a DMS or Information rules is provided!",
87
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
88
- )
89
- if isinstance(input_rules, DMSRules):
90
- dms_rules = input_rules
91
- elif isinstance(input_rules, InformationRules):
92
- dms_rules = InformationToDMS().transform(input_rules)
93
- else:
94
- raise NotImplementedError(f"Unsupported rules type {type(input_rules)}")
95
-
96
- dms_exporter = exporters.DMSExporter(
97
- export_components=frozenset(components_to_delete),
98
- include_space=(None if multi_space_components_delete else {dms_rules.metadata.space}),
99
- )
100
-
101
- report_lines = ["# Data Model Deletion from CDF\n\n"]
102
- errors = []
103
- for result in dms_exporter.delete_from_cdf(rules=dms_rules, client=NeatClient(cdf_client), dry_run=dry_run):
104
- report_lines.append(str(result))
105
- errors.extend(result.error_messages)
106
-
107
- report_lines.append("\n\n# ERRORS\n\n")
108
- report_lines.extend(errors)
109
-
110
- output_dir = self.config.staging_path
111
- output_dir.mkdir(parents=True, exist_ok=True)
112
- report_file = "dms_component_creation_report.txt"
113
- report_full_path = output_dir / report_file
114
- report_full_path.write_text("\n".join(report_lines))
115
-
116
- output_text = (
117
- "<p></p>"
118
- "Download Data Model Deletion "
119
- f'<a href="/data/staging/{report_file}?{time.time()}" '
120
- f'target="_blank">Report</a>'
121
- )
122
-
123
- if errors:
124
- return FlowMessage(error_text=output_text, step_execution_status=StepExecutionStatus.ABORT_AND_FAIL)
125
- else:
126
- return FlowMessage(output_text=output_text)
127
-
128
-
129
- class RulesToDMS(Step):
130
- """
131
- This step exports Rules to DMS Schema components in CDF
132
- """
133
-
134
- description = "This step exports Rules to DMS Schema components in CDF."
135
- version = "private-beta"
136
- category = CATEGORY
137
-
138
- configurables: ClassVar[list[Configurable]] = [
139
- Configurable(
140
- name="Dry run",
141
- value="False",
142
- label=("Whether to perform a dry run of the export. "),
143
- options=["True", "False"],
144
- ),
145
- Configurable(
146
- name="Components",
147
- type="multi_select",
148
- value="",
149
- label="Select which DMS schema component(s) to export to CDF",
150
- options=["spaces", "containers", "views", "data_models"],
151
- ),
152
- Configurable(
153
- name="Existing component handling",
154
- value="fail",
155
- label=(
156
- "How to handle situation when components being exported in CDF already exist."
157
- "Fail the step if any component already exists, "
158
- "Skip the component if it already exists, "
159
- " or Update the component try to update the component."
160
- ),
161
- options=["fail", "skip", "update", "force"],
162
- ),
163
- Configurable(
164
- name="Multi-space components create",
165
- value="False",
166
- label=(
167
- "Whether to create only components belonging to the data model space"
168
- " (i.e. space define under Metadata sheet of Rules), "
169
- "or also additionally components outside of the data model space."
170
- ),
171
- options=["True", "False"],
172
- ),
173
- ]
174
-
175
- def run(self, rules: MultiRuleData, cdf_client: CogniteClient) -> FlowMessage: # type: ignore[override]
176
- if self.configs is None or self.data_store_path is None:
177
- raise WorkflowStepNotInitializedError(type(self).__name__)
178
- existing_components_handling = cast(
179
- Literal["fail", "update", "skip", "force"], self.configs["Existing component handling"]
180
- )
181
- multi_space_components_create: bool = self.configs["Multi-space components create"] == "True"
182
- components_to_create = {
183
- cast(Literal["spaces", "data_models", "views", "containers"], key)
184
- for key, value in self.complex_configs["Components"].items()
185
- if value
186
- }
187
- dry_run = self.configs["Dry run"] == "True"
188
-
189
- if not components_to_create:
190
- return FlowMessage(
191
- error_text="No DMS Schema components selected for upload! Please select minimum one!",
192
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
193
- )
194
- input_rules = rules.dms or rules.information
195
- if input_rules is None:
196
- return FlowMessage(
197
- error_text="Missing DMS or Information rules in the input data! "
198
- "Please ensure that a DMS or Information rules is provided!",
199
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
200
- )
201
- if isinstance(input_rules, DMSRules):
202
- dms_rules = input_rules
203
- elif isinstance(input_rules, InformationRules):
204
- dms_rules = InformationToDMS().transform(input_rules)
205
- else:
206
- raise NotImplementedError(f"Unsupported rules type {type(input_rules)}")
207
-
208
- dms_exporter = exporters.DMSExporter(
209
- export_components=frozenset(components_to_create),
210
- include_space=(None if multi_space_components_create else {dms_rules.metadata.space}),
211
- existing=existing_components_handling,
212
- )
213
-
214
- output_dir = self.config.staging_path
215
- output_dir.mkdir(parents=True, exist_ok=True)
216
- file_name = input_rules.metadata.external_id
217
- schema_zip = f"{file_name}.zip"
218
- schema_full_path = output_dir / schema_zip
219
- dms_exporter.export_to_file(dms_rules, schema_full_path)
220
-
221
- report_lines = ["# DMS Schema Export to CDF\n\n"]
222
- errors = []
223
- for result in dms_exporter.export_to_cdf_iterable(
224
- rules=dms_rules, client=NeatClient(cdf_client), dry_run=dry_run
225
- ):
226
- report_lines.append(str(result))
227
- errors.extend(result.error_messages)
228
-
229
- report_lines.append("\n\n# ERRORS\n\n")
230
- report_lines.extend(errors)
231
-
232
- output_dir = self.config.staging_path
233
- output_dir.mkdir(parents=True, exist_ok=True)
234
- report_file = "dms_component_creation_report.txt"
235
- report_full_path = output_dir / report_file
236
- report_full_path.write_text("\n".join(report_lines))
237
-
238
- output_text = (
239
- "<p></p>"
240
- "Download DMS Export "
241
- f'<a href="/data/staging/{report_file}?{time.time()}" '
242
- f'target="_blank">Report</a>'
243
- "<p></p>"
244
- "Download DMS exported schema"
245
- f'- <a href="/data/staging/{schema_zip}?{time.time()}" '
246
- f'target="_blank">{schema_zip}</a>'
247
- )
248
-
249
- if errors:
250
- return FlowMessage(error_text=output_text, step_execution_status=StepExecutionStatus.ABORT_AND_FAIL)
251
- else:
252
- return FlowMessage(output_text=output_text)
253
-
254
-
255
- class RulesToExcel(Step):
256
- """This step exports Rules to Excel serialization"""
257
-
258
- description = "This step exports Rules to Excel serialization."
259
- version = "private-beta"
260
- category = CATEGORY
261
-
262
- configurables: ClassVar[list[Configurable]] = [
263
- Configurable(
264
- name="Styling",
265
- value="default",
266
- label="Styling of the Excel file",
267
- options=list(exporters.ExcelExporter.style_options),
268
- ),
269
- Configurable(
270
- name="Output role format",
271
- value="input",
272
- label="The role to use for the exported spreadsheet. If provided, the rules will be converted to "
273
- "this role format before being written to excel. If not provided, the role from the input "
274
- "rules will be used.",
275
- options=["input", *RoleTypes.__members__.keys()],
276
- ),
277
- Configurable(
278
- name="New Data Model ID",
279
- value="",
280
- label="If you chose Dump Format 'reference', the provided ID will be use in the new medata sheet. "
281
- "Expected format 'sp_space:my_external_id'.",
282
- ),
283
- Configurable(
284
- name="File path",
285
- value="",
286
- label="File path to the generated Excel file.For example: 'staging/exported-rules.xlsx'",
287
- ),
288
- ]
289
-
290
- def run(self, rules: MultiRuleData) -> FlowMessage: # type: ignore[override, syntax]
291
- if self.configs is None or self.data_store_path is None:
292
- raise WorkflowStepNotInitializedError(type(self).__name__)
293
-
294
- styling = cast(exporters.ExcelExporter.Style, self.configs.get("Styling", "default"))
295
- role = self.configs.get("Output role format")
296
- output_role: RoleTypes | None = None
297
- if role != "input" and role is not None:
298
- output_role = RoleTypes[role]
299
-
300
- new_model_str = self.configs.get("New Data Model ID")
301
- new_model_id: tuple[str, str] | None = None
302
- if new_model_str and ":" in new_model_str:
303
- new_model_id = tuple(new_model_str.split(":", 1)) # type: ignore[assignment]
304
- elif new_model_str:
305
- return FlowMessage(
306
- error_text="New Data Model ID must be in the format 'sp_space:my_external_id'!",
307
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
308
- )
309
-
310
- excel_exporter = exporters.ExcelExporter(styling=styling, new_model_id=new_model_id) # type: ignore[arg-type]
311
-
312
- # Todo - Move the conversion to a separate workflow step.
313
- rule_instance: VerifiedRules
314
-
315
- if rules.information:
316
- rule_instance = rules.information
317
- elif rules.dms:
318
- rule_instance = rules.dms
319
- else:
320
- output_errors = "No rules provided for export!"
321
- return FlowMessage(error_text=output_errors, step_execution_status=StepExecutionStatus.ABORT_AND_FAIL)
322
-
323
- if rule_instance.metadata.role is output_role or output_role is None:
324
- ...
325
- elif output_role is RoleTypes.dms:
326
- if isinstance(rule_instance, InformationRules):
327
- rule_instance = InformationToDMS().transform(rule_instance)
328
- else:
329
- raise NotImplementedError(f"Role {output_role} is not supported for {type(rules).__name__} rules")
330
- elif output_role is RoleTypes.information:
331
- if isinstance(rule_instance, DMSRules):
332
- rule_instance = DMSToInformation().transform(rule_instance)
333
- else:
334
- raise NotImplementedError(f"Role {output_role} is not supported for {type(rules).__name__} rules")
335
- else:
336
- raise NotImplementedError(f"Role {output_role} is not supported for {type(rules).__name__} rules")
337
-
338
- if output_role is None:
339
- output_role = rule_instance.metadata.role
340
- output_dir = self.data_store_path / Path("staging")
341
- output_dir.mkdir(parents=True, exist_ok=True)
342
- file_name = f"exported_rules_{output_role.value}.xlsx"
343
- filepath = output_dir / file_name
344
- if self.configs.get("File path", ""):
345
- file_name = self.configs["File path"]
346
- filepath = Path(self.data_store_path) / Path(file_name)
347
- else:
348
- file_name = f"staging/{file_name}"
349
-
350
- excel_exporter.export_to_file(rule_instance, filepath)
351
-
352
- output_text = (
353
- "<p></p>"
354
- f"Download Excel Exported {output_role.value} rules: "
355
- f'- <a href="/data/{file_name}?{time.time()}" '
356
- f'target="_blank">{file_name}</a>'
357
- )
358
-
359
- return FlowMessage(output_text=output_text)
360
-
361
-
362
- class RulesToOntology(Step):
363
- """
364
- This step exports Rules to OWL ontology
365
- """
366
-
367
- description = "This step exports Rules to OWL ontology"
368
- version = "private-beta"
369
- category = CATEGORY
370
- configurables: ClassVar[list[Configurable]] = [
371
- Configurable(
372
- name="File path",
373
- value="staging/ontology.ttl",
374
- label=("Relative path for the ontology file storage, " " It will be auto-created if not provided ! "),
375
- )
376
- ]
377
-
378
- def run(self, rules: MultiRuleData) -> FlowMessage: # type: ignore[override, syntax]
379
- if self.configs is None or self.data_store_path is None:
380
- raise WorkflowStepNotInitializedError(type(self).__name__)
381
-
382
- if not rules.information and not rules.dms:
383
- return FlowMessage(
384
- error_text="Rules must be made either by Information Architect or DMS Architect!",
385
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
386
- )
387
-
388
- default_path = self.config.staging_path / _get_default_file_name(rules, "ontology", "ttl")
389
-
390
- storage_path = (
391
- self.data_store_path / Path(self.configs["File path"]) if self.configs["File path"] else default_path
392
- )
393
- storage_path.parent.mkdir(parents=True, exist_ok=True)
394
-
395
- input_rules = rules.information or rules.dms
396
- if isinstance(input_rules, DMSRules):
397
- info_rules = DMSToInformation().transform(input_rules)
398
- elif isinstance(input_rules, InformationRules):
399
- info_rules = input_rules
400
- else:
401
- raise NotImplementedError(f"Unsupported rules type {type(input_rules)}")
402
-
403
- exporter = exporters.OWLExporter()
404
- exporter.export_to_file(info_rules, storage_path)
405
-
406
- relative_file_path = "/".join(storage_path.relative_to(self.data_store_path).parts)
407
-
408
- output_text = (
409
- "<p></p>"
410
- "Rules exported as OWL ontology can be downloaded here : "
411
- f'<a href="/data/{relative_file_path}?{time.time()}" '
412
- f'target="_blank">{storage_path.stem}.ttl</a>'
413
- )
414
-
415
- return FlowMessage(output_text=output_text)
416
-
417
-
418
- class RulesToSHACL(Step):
419
- """
420
- This step exports Rules to SHACL
421
- """
422
-
423
- description = "This step exports Rules to SHACL"
424
- version = "private-beta"
425
- category = CATEGORY
426
- configurables: ClassVar[list[Configurable]] = [
427
- Configurable(
428
- name="File path",
429
- value="staging/shacl.ttl",
430
- label=(
431
- "Relative path for the shacl file storage, "
432
- "must end with .ttl ! It will be auto-created if not provided !"
433
- ),
434
- )
435
- ]
436
-
437
- def run(self, rules: MultiRuleData) -> FlowMessage: # type: ignore[override, syntax]
438
- if self.configs is None or self.data_store_path is None:
439
- raise WorkflowStepNotInitializedError(type(self).__name__)
440
-
441
- if not rules.information and not rules.dms:
442
- return FlowMessage(
443
- error_text="Rules must be made either by Information Architect or DMS Architect!",
444
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
445
- )
446
-
447
- default_path = self.config.staging_path / _get_default_file_name(rules, "shacl", "ttl")
448
-
449
- storage_path = (
450
- self.data_store_path / Path(self.configs["File path"]) if self.configs["File path"] else default_path
451
- )
452
- storage_path.parent.mkdir(parents=True, exist_ok=True)
453
-
454
- input_rules = rules.information or rules.dms
455
- if isinstance(input_rules, DMSRules):
456
- info_rules = DMSToInformation().transform(input_rules)
457
- elif isinstance(input_rules, InformationRules):
458
- info_rules = input_rules
459
- else:
460
- raise NotImplementedError(f"Unsupported rules type {type(input_rules)}")
461
-
462
- exporter = exporters.SHACLExporter()
463
- exporter.export_to_file(info_rules, storage_path)
464
-
465
- relative_file_path = "/".join(storage_path.relative_to(self.data_store_path).parts)
466
-
467
- output_text = (
468
- "<p></p>"
469
- "Rules exported as SHACL shapes can be downloaded here : "
470
- f'<a href="/data/{relative_file_path}?{time.time()}" '
471
- f'target="_blank">{storage_path.stem}.ttl</a>'
472
- )
473
-
474
- return FlowMessage(output_text=output_text)
475
-
476
-
477
- class RulesToSemanticDataModel(Step):
478
- """
479
- This step exports Rules to semantic data model
480
- """
481
-
482
- description = "This step exports Rules to semantic data model (ontology + SHACL)"
483
- version = "private-beta"
484
- category = CATEGORY
485
- configurables: ClassVar[list[Configurable]] = [
486
- Configurable(
487
- name="File path",
488
- value="staging/semantic-data-model.ttl",
489
- label=(
490
- "Relative path for the semantic data model file storage, "
491
- "must end with .ttl ! It will be auto-created if not provided !"
492
- ),
493
- )
494
- ]
495
-
496
- def run(self, rules: MultiRuleData) -> FlowMessage: # type: ignore[override, syntax]
497
- if self.configs is None or self.data_store_path is None:
498
- raise WorkflowStepNotInitializedError(type(self).__name__)
499
-
500
- if not rules.information and not rules.dms:
501
- return FlowMessage(
502
- error_text="Rules must be made either by Information Architect or DMS Architect!",
503
- step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
504
- )
505
-
506
- default_path = self.config.staging_path / _get_default_file_name(rules, "semantic-data-model", "ttl")
507
-
508
- storage_path = (
509
- self.data_store_path / Path(self.configs["File path"]) if self.configs["File path"] else default_path
510
- )
511
- storage_path.parent.mkdir(parents=True, exist_ok=True)
512
- input_rules = rules.information or rules.dms
513
- if isinstance(input_rules, DMSRules):
514
- info_rules = DMSToInformation().transform(input_rules)
515
- elif isinstance(input_rules, InformationRules):
516
- info_rules = input_rules
517
- else:
518
- raise NotImplementedError(f"Unsupported rules type {type(input_rules)}")
519
- exporter = exporters.SemanticDataModelExporter()
520
- exporter.export_to_file(info_rules, storage_path)
521
-
522
- relative_file_path = "/".join(storage_path.relative_to(self.data_store_path).parts)
523
-
524
- output_text = (
525
- "<p></p>"
526
- "Rules exported as semantic data model (OWL + SHACL) can be downloaded here : "
527
- f'<a href="/data/{relative_file_path}?{time.time()}" '
528
- f'target="_blank">{storage_path.stem}.ttl</a>'
529
- )
530
-
531
- return FlowMessage(output_text=output_text)
532
-
533
-
534
- def _get_default_file_name(rules: MultiRuleData, file_category: str = "ontology", extension: str = "ttl") -> str:
535
- name = rules.information.metadata.prefix if rules.information else cast(DMSRules, rules.dms).metadata.space
536
- version = rules.information.metadata.version if rules.information else cast(DMSRules, rules.dms).metadata.version
537
- return f"{name}-v{version.strip().replace('.', '_')}-{file_category}.{extension}"