cognite-neat 0.103.0__py3-none-any.whl → 0.104.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 (64) hide show
  1. cognite/neat/_graph/extractors/_mock_graph_generator.py +1 -1
  2. cognite/neat/_graph/transformers/_base.py +109 -1
  3. cognite/neat/_graph/transformers/_classic_cdf.py +4 -0
  4. cognite/neat/_graph/transformers/_prune_graph.py +103 -47
  5. cognite/neat/_graph/transformers/_rdfpath.py +41 -17
  6. cognite/neat/_graph/transformers/_value_type.py +119 -154
  7. cognite/neat/_issues/_base.py +35 -8
  8. cognite/neat/_issues/warnings/_resources.py +1 -1
  9. cognite/neat/_rules/_shared.py +18 -34
  10. cognite/neat/_rules/exporters/_base.py +28 -2
  11. cognite/neat/_rules/exporters/_rules2dms.py +4 -0
  12. cognite/neat/_rules/exporters/_rules2excel.py +11 -0
  13. cognite/neat/_rules/exporters/_rules2instance_template.py +4 -0
  14. cognite/neat/_rules/exporters/_rules2ontology.py +13 -1
  15. cognite/neat/_rules/exporters/_rules2yaml.py +4 -0
  16. cognite/neat/_rules/importers/_base.py +9 -0
  17. cognite/neat/_rules/importers/_dms2rules.py +17 -5
  18. cognite/neat/_rules/importers/_dtdl2rules/dtdl_importer.py +5 -2
  19. cognite/neat/_rules/importers/_rdf/_base.py +10 -8
  20. cognite/neat/_rules/importers/_rdf/_imf2rules.py +4 -0
  21. cognite/neat/_rules/importers/_rdf/_inference2rules.py +7 -0
  22. cognite/neat/_rules/importers/_rdf/_owl2rules.py +4 -0
  23. cognite/neat/_rules/importers/_spreadsheet2rules.py +17 -8
  24. cognite/neat/_rules/importers/_yaml2rules.py +21 -7
  25. cognite/neat/_rules/models/_base_input.py +1 -1
  26. cognite/neat/_rules/models/_base_rules.py +5 -0
  27. cognite/neat/_rules/models/dms/_rules.py +4 -0
  28. cognite/neat/_rules/models/dms/_rules_input.py +9 -0
  29. cognite/neat/_rules/models/dms/_validation.py +2 -0
  30. cognite/neat/_rules/models/entities/_single_value.py +25 -5
  31. cognite/neat/_rules/models/information/_rules.py +4 -0
  32. cognite/neat/_rules/models/information/_rules_input.py +9 -0
  33. cognite/neat/_rules/models/mapping/_classic2core.py +2 -5
  34. cognite/neat/_rules/transformers/__init__.py +5 -4
  35. cognite/neat/_rules/transformers/_base.py +41 -65
  36. cognite/neat/_rules/transformers/_converters.py +149 -62
  37. cognite/neat/_rules/transformers/_mapping.py +17 -12
  38. cognite/neat/_rules/transformers/_verification.py +50 -37
  39. cognite/neat/_session/_base.py +32 -121
  40. cognite/neat/_session/_inspect.py +3 -3
  41. cognite/neat/_session/_mapping.py +17 -105
  42. cognite/neat/_session/_prepare.py +36 -254
  43. cognite/neat/_session/_read.py +11 -130
  44. cognite/neat/_session/_set.py +6 -30
  45. cognite/neat/_session/_show.py +49 -30
  46. cognite/neat/_session/_state.py +49 -107
  47. cognite/neat/_session/_to.py +42 -31
  48. cognite/neat/_shared.py +23 -2
  49. cognite/neat/_store/_provenance.py +3 -82
  50. cognite/neat/_store/_rules_store.py +372 -10
  51. cognite/neat/_store/exceptions.py +23 -0
  52. cognite/neat/_utils/graph_transformations_report.py +36 -0
  53. cognite/neat/_utils/io_.py +11 -0
  54. cognite/neat/_utils/rdf_.py +8 -0
  55. cognite/neat/_utils/spreadsheet.py +5 -4
  56. cognite/neat/_version.py +1 -1
  57. cognite/neat/_workflows/steps/lib/current/rules_exporter.py +7 -7
  58. cognite/neat/_workflows/steps/lib/current/rules_importer.py +24 -99
  59. {cognite_neat-0.103.0.dist-info → cognite_neat-0.104.0.dist-info}/METADATA +1 -1
  60. {cognite_neat-0.103.0.dist-info → cognite_neat-0.104.0.dist-info}/RECORD +63 -61
  61. cognite/neat/_rules/transformers/_pipelines.py +0 -70
  62. {cognite_neat-0.103.0.dist-info → cognite_neat-0.104.0.dist-info}/LICENSE +0 -0
  63. {cognite_neat-0.103.0.dist-info → cognite_neat-0.104.0.dist-info}/WHEEL +0 -0
  64. {cognite_neat-0.103.0.dist-info → cognite_neat-0.104.0.dist-info}/entry_points.txt +0 -0
@@ -1,26 +1,17 @@
1
- from datetime import datetime, timezone
2
- from typing import Literal, cast
1
+ from typing import Literal
3
2
 
4
3
  from cognite.client import CogniteClient
5
4
  from cognite.client import data_modeling as dm
6
5
 
7
6
  from cognite.neat import _version
8
7
  from cognite.neat._client import NeatClient
9
- from cognite.neat._issues import IssueList, catch_issues
8
+ from cognite.neat._issues import IssueList
10
9
  from cognite.neat._issues.errors import RegexViolationError
11
10
  from cognite.neat._rules import importers
12
- from cognite.neat._rules._shared import ReadRules, VerifiedRules
13
- from cognite.neat._rules.models import DMSRules
14
- from cognite.neat._rules.models.dms import DMSValidation
15
- from cognite.neat._rules.models.information import InformationValidation
11
+ from cognite.neat._rules.models._base_input import InputRules
16
12
  from cognite.neat._rules.models.information._rules import InformationRules
17
- from cognite.neat._rules.models.information._rules_input import InformationInputRules
18
13
  from cognite.neat._rules.transformers import ConvertToRules, InformationToDMS, VerifyAnyRules
19
14
  from cognite.neat._rules.transformers._converters import ConversionTransformer
20
- from cognite.neat._store._provenance import (
21
- INSTANCES_ENTITY,
22
- Change,
23
- )
24
15
 
25
16
  from ._collector import _COLLECTOR, Collector
26
17
  from ._drop import DropAPI
@@ -128,47 +119,16 @@ class NeatSession:
128
119
  neat.verify()
129
120
  ```
130
121
  """
131
- source_id, last_unverified_rule = self._state.data_model.last_unverified_rule
132
- transformer = VerifyAnyRules("continue", validate=False)
133
- start = datetime.now(timezone.utc)
134
- output = transformer.try_transform(last_unverified_rule)
135
-
136
- if output.rules:
137
- if isinstance(output.rules, DMSRules):
138
- issues = DMSValidation(output.rules, self._client).validate()
139
- elif isinstance(output.rules, InformationRules):
140
- issues = InformationValidation(output.rules).validate()
141
- else:
142
- raise NeatSessionError("Unsupported rule type")
143
- if issues.has_errors:
144
- # This is up for discussion, but I think we should not return rules that
145
- # only pass the verification but not the validation.
146
- output.rules = None
147
- output.issues.extend(issues)
148
-
149
- end = datetime.now(timezone.utc)
150
-
151
- if output.rules:
152
- change = Change.from_rules_activity(
153
- output.rules,
154
- transformer.agent,
155
- start,
156
- end,
157
- f"Verified data model {source_id} as {output.rules.metadata.identifier}",
158
- self._state.data_model.provenance.source_entity(source_id)
159
- or self._state.data_model.provenance.target_entity(source_id),
160
- )
161
-
162
- self._state.data_model.write(output.rules, change)
163
-
164
- if isinstance(output.rules, InformationRules):
165
- self._state.instances.store.add_rules(output.rules)
166
-
167
- output.issues.action = "verify"
168
- self._state.data_model.issue_lists.append(output.issues)
169
- if output.issues:
122
+ transformer = VerifyAnyRules(validate=True, client=self._client) # type: ignore[var-annotated]
123
+ issues = self._state.rule_transform(transformer)
124
+ if not issues.has_errors:
125
+ rules = self._state.rule_store.last_verified_rule
126
+ if isinstance(rules, InformationRules):
127
+ self._state.instances.store.add_rules(rules)
128
+
129
+ if issues:
170
130
  print("You can inspect the issues with the .inspect.issues(...) method.")
171
- return output.issues
131
+ return issues
172
132
 
173
133
  def convert(
174
134
  self, target: Literal["dms", "information"], mode: Literal["edge_properties"] | None = None
@@ -192,43 +152,17 @@ class NeatSession:
192
152
  neat.convert(target="information")
193
153
  ```
194
154
  """
195
- start = datetime.now(timezone.utc)
196
- issues = IssueList()
197
- converter: ConversionTransformer | None = None
198
- converted_rules: VerifiedRules | None = None
199
- with catch_issues(issues):
200
- if target == "dms":
201
- source_id, info_rules = self._state.data_model.last_verified_information_rules
202
- converter = InformationToDMS(mode=mode)
203
- converted_rules = converter.transform(info_rules).rules
204
- elif target == "information":
205
- source_id, dms_rules = self._state.data_model.last_verified_dms_rules
206
- converter = ConvertToRules(InformationRules)
207
- converted_rules = converter.transform(dms_rules).rules
208
- else:
209
- # Session errors are not caught by the catch_issues context manager
210
- raise NeatSessionError(f"Target {target} not supported.")
211
-
212
- end = datetime.now(timezone.utc)
213
- if issues:
214
- self._state.data_model.issue_lists.append(issues)
215
-
216
- if converted_rules is not None and converter is not None:
217
- # Provenance
218
- change = Change.from_rules_activity(
219
- converted_rules,
220
- converter.agent,
221
- start,
222
- end,
223
- f"Converted data model {source_id} to {converted_rules.metadata.identifier}",
224
- self._state.data_model.provenance.source_entity(source_id)
225
- or self._state.data_model.provenance.target_entity(source_id),
226
- )
227
-
228
- self._state.data_model.write(converted_rules, change)
229
-
230
- if self._verbose and not issues.has_errors:
231
- print(f"Rules converted to {target}")
155
+ converter: ConversionTransformer
156
+ if target == "dms":
157
+ converter = InformationToDMS(mode=mode)
158
+ elif target == "information":
159
+ converter = ConvertToRules(InformationRules)
160
+ else:
161
+ raise NeatSessionError(f"Target {target} not supported.")
162
+ issues = self._state.rule_transform(converter)
163
+
164
+ if self._verbose and not issues.has_errors:
165
+ print(f"Rules converted to {target}")
232
166
  else:
233
167
  print("Conversion failed.")
234
168
  if issues:
@@ -263,53 +197,30 @@ class NeatSession:
263
197
  ```
264
198
  """
265
199
  model_id = dm.DataModelId.load(model_id)
266
-
267
- start = datetime.now(timezone.utc)
268
200
  importer = importers.InferenceImporter.from_graph_store(
269
201
  store=self._state.instances.store,
270
202
  max_number_of_instance=max_number_of_instance,
203
+ data_model_id=model_id,
271
204
  )
272
- inferred_rules: ReadRules = importer.to_rules()
273
- end = datetime.now(timezone.utc)
274
-
275
- if model_id.space:
276
- cast(InformationInputRules, inferred_rules.rules).metadata.space = model_id.space
277
- if model_id.external_id:
278
- cast(InformationInputRules, inferred_rules.rules).metadata.external_id = model_id.external_id
279
-
280
- if model_id.version:
281
- cast(InformationInputRules, inferred_rules.rules).metadata.version = model_id.version
282
-
283
- # Provenance
284
- change = Change.from_rules_activity(
285
- inferred_rules,
286
- importer.agent,
287
- start,
288
- end,
289
- "Inferred data model",
290
- INSTANCES_ENTITY,
291
- )
292
-
293
- self._state.data_model.write(inferred_rules, change)
294
- return inferred_rules.issues
205
+ return self._state.rule_import(importer)
295
206
 
296
207
  def _repr_html_(self) -> str:
297
208
  state = self._state
298
209
  if (
299
210
  not state.instances.has_store
300
- and not state.data_model.has_unverified_rules
301
- and not state.data_model.has_verified_rules
211
+ and not state.rule_store.has_unverified_rules
212
+ and not state.rule_store.has_verified_rules
302
213
  ):
303
214
  return "<strong>Empty session</strong>. Get started by reading something with the <em>.read</em> attribute."
304
215
 
305
216
  output = []
306
217
 
307
- if state.data_model.has_unverified_rules and not state.data_model.has_verified_rules:
308
- rules: ReadRules = state.data_model.last_unverified_rule[1]
309
- output.append(f"<H2>Unverified Data Model</H2><br />{rules.rules._repr_html_()}") # type: ignore
218
+ if state.rule_store.has_unverified_rules and not state.rule_store.has_verified_rules:
219
+ rules: InputRules = state.rule_store.last_unverified_rule
220
+ output.append(f"<H2>Unverified Data Model</H2><br />{rules._repr_html_()}") # type: ignore
310
221
 
311
- if state.data_model.has_verified_rules:
312
- output.append(f"<H2>Verified Data Model</H2><br />{state.data_model.last_verified_rule[1]._repr_html_()}") # type: ignore
222
+ if state.rule_store.has_verified_rules:
223
+ output.append(f"<H2>Verified Data Model</H2><br />{state.rule_store.last_verified_rule._repr_html_()}") # type: ignore
313
224
 
314
225
  if state.instances.has_store:
315
226
  output.append(f"<H2>Instances</H2> {state.instances.store._repr_html_()}")
@@ -59,7 +59,7 @@ class InspectAPI:
59
59
  neat.inspect.properties
60
60
  ```
61
61
  """
62
- return self._state.data_model.last_verified_rule[1].properties.to_pandas()
62
+ return self._state.rule_store.last_verified_rule.properties.to_pandas()
63
63
 
64
64
 
65
65
  @session_class_wrapper
@@ -89,7 +89,7 @@ class InspectIssues:
89
89
  return_dataframe: bool = (False if IN_NOTEBOOK else True), # type: ignore[assignment]
90
90
  ) -> pd.DataFrame | None:
91
91
  """Returns the issues of the current data model."""
92
- issues = self._state.data_model.last_issues
92
+ issues = self._state.rule_store.last_issues
93
93
  if not issues:
94
94
  self._print("No issues found.")
95
95
 
@@ -141,7 +141,7 @@ class InspectOutcome:
141
141
  """
142
142
 
143
143
  def __init__(self, state: SessionState) -> None:
144
- self.data_model = InspectUploadOutcome(lambda: state.data_model.last_outcome)
144
+ self.data_model = InspectUploadOutcome(lambda: state.rule_store.last_outcome)
145
145
  self.instances = InspectUploadOutcome(lambda: state.instances.last_outcome)
146
146
 
147
147
 
@@ -1,13 +1,8 @@
1
- from datetime import datetime, timezone
2
-
3
1
  from cognite.neat._client import NeatClient
4
- from cognite.neat._constants import DEFAULT_NAMESPACE
5
- from cognite.neat._rules.importers import DMSImporter
6
- from cognite.neat._rules.models.dms import DMSValidation
2
+ from cognite.neat._issues import IssueList
3
+ from cognite.neat._rules.models import DMSRules
7
4
  from cognite.neat._rules.models.mapping import load_classic_to_core_mapping
8
- from cognite.neat._rules.transformers import AsParentPropertyId, RuleMapper, VerifyDMSRules
9
- from cognite.neat._store._provenance import Agent as ProvenanceAgent
10
- from cognite.neat._store._provenance import Change
5
+ from cognite.neat._rules.transformers import AsParentPropertyId, IncludeReferenced, RuleMapper
11
6
 
12
7
  from ._state import SessionState
13
8
  from .exceptions import NeatSessionError, session_class_wrapper
@@ -25,7 +20,7 @@ class DataModelMappingAPI:
25
20
  self._state = state
26
21
  self._client = client
27
22
 
28
- def classic_to_core(self, company_prefix: str, use_parent_property_name: bool = True) -> None:
23
+ def classic_to_core(self, company_prefix: str, use_parent_property_name: bool = True) -> IssueList:
29
24
  """Map classic types to core types.
30
25
 
31
26
  Note this automatically creates an extended CogniteCore model.
@@ -44,101 +39,18 @@ class DataModelMappingAPI:
44
39
  neat.mapping.classic_to_core(company_prefix="WindFarmX", use_parent_property_name=True)
45
40
  ```
46
41
  """
47
- source_id, rules = self._state.data_model.last_verified_dms_rules
48
-
49
- start = datetime.now(timezone.utc)
50
- transformer = RuleMapper(
51
- load_classic_to_core_mapping(company_prefix, rules.metadata.space, rules.metadata.version)
52
- )
53
- output = transformer.transform(rules)
54
- end = datetime.now(timezone.utc)
55
-
56
- change = Change.from_rules_activity(
57
- output,
58
- transformer.agent,
59
- start,
60
- end,
61
- "Mapping classic to core",
62
- self._state.data_model.provenance.source_entity(source_id)
63
- or self._state.data_model.provenance.target_entity(source_id),
64
- )
42
+ rules = self._state.rule_store.get_last_successful_entity().result
43
+ if not isinstance(rules, DMSRules):
44
+ # Todo better hint of what you should do.
45
+ raise NeatSessionError(f"Expected DMSRules, got {type(rules)}")
65
46
 
66
- self._state.data_model.write(output.rules, change)
67
-
68
- start = datetime.now(timezone.utc)
69
-
70
- source_id, rules = self._state.data_model.last_verified_dms_rules
71
- view_ids, container_ids = DMSValidation(rules, self._client).imported_views_and_containers_ids()
72
- if not (view_ids or container_ids):
73
- print(
74
- f"Data model {rules.metadata.as_data_model_id()} does not have any referenced views or containers."
75
- f"that is not already included in the data model."
76
- )
77
- return
78
47
  if self._client is None:
79
- raise NeatSessionError(
80
- "No client provided. You are referencing unknown views and containers in your data model, "
81
- "NEAT needs a client to lookup the definitions. "
82
- "Please set the client in the session, NeatSession(client=client)."
83
- )
84
- schema = self._client.schema.retrieve([v.as_id() for v in view_ids], [c.as_id() for c in container_ids])
85
- copy_ = rules.model_copy(deep=True)
86
- copy_.metadata.version = f"{rules.metadata.version}_completed"
87
- importer = DMSImporter(schema)
88
- imported = importer.to_rules()
89
- if imported.rules is None:
90
- self._state.data_model.issue_lists.append(imported.issues)
91
- raise NeatSessionError(
92
- "Could not import the referenced views and containers. "
93
- "See `neat.inspect.issues()` for more information."
94
- )
95
- verified = VerifyDMSRules("continue", validate=False).transform(imported.rules)
96
- if verified.rules is None:
97
- self._state.data_model.issue_lists.append(verified.issues)
98
- raise NeatSessionError(
99
- "Could not verify the referenced views and containers. "
100
- "See `neat.inspect.issues()` for more information."
101
- )
102
- if copy_.containers is None:
103
- copy_.containers = verified.rules.containers
104
- else:
105
- existing_containers = {c.container for c in copy_.containers}
106
- copy_.containers.extend(
107
- [c for c in verified.rules.containers or [] if c.container not in existing_containers]
108
- )
109
- existing_views = {v.view for v in copy_.views}
110
- copy_.views.extend([v for v in verified.rules.views if v.view not in existing_views])
111
- end = datetime.now(timezone.utc)
112
-
113
- change = Change.from_rules_activity(
114
- copy_,
115
- ProvenanceAgent(id_=DEFAULT_NAMESPACE["agent/"]),
116
- start,
117
- end,
118
- (f"Included referenced views and containers in the data model {rules.metadata.as_data_model_id()}"),
119
- self._state.data_model.provenance.source_entity(source_id)
120
- or self._state.data_model.provenance.target_entity(source_id),
121
- )
122
-
123
- self._state.data_model.write(copy_, change)
124
-
125
- if not use_parent_property_name:
126
- return
127
-
128
- source_id, rules = self._state.data_model.last_verified_dms_rules
129
- start = datetime.now(timezone.utc)
130
- transformer = AsParentPropertyId(self._client)
131
- output = transformer.transform(rules)
132
- end = datetime.now(timezone.utc)
133
-
134
- change = Change.from_rules_activity(
135
- output,
136
- transformer.agent,
137
- start,
138
- end,
139
- "Renaming property names to parent name",
140
- self._state.data_model.provenance.source_entity(source_id)
141
- or self._state.data_model.provenance.target_entity(source_id),
142
- )
143
-
144
- self._state.data_model.write(output.rules, change)
48
+ raise NeatSessionError("Client is required to map classic to core")
49
+
50
+ transformers = [
51
+ RuleMapper(load_classic_to_core_mapping(company_prefix, rules.metadata.space, rules.metadata.version)),
52
+ IncludeReferenced(self._client),
53
+ ]
54
+ if use_parent_property_name:
55
+ transformers.append(AsParentPropertyId(self._client))
56
+ return self._state.rule_transform(*transformers)