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.
- cognite/neat/__init__.py +1 -1
- cognite/neat/_app/api/routers/crud.py +1 -1
- cognite/neat/_client/__init__.py +1 -1
- cognite/neat/_client/_api/data_modeling_loaders.py +1 -1
- cognite/neat/_client/_api/schema.py +1 -1
- cognite/neat/_constants.py +5 -1
- cognite/neat/_graph/_tracking/__init__.py +1 -1
- cognite/neat/_graph/extractors/__init__.py +8 -8
- cognite/neat/_graph/extractors/_mock_graph_generator.py +2 -3
- cognite/neat/_graph/loaders/_base.py +1 -1
- cognite/neat/_graph/loaders/_rdf2dms.py +165 -47
- cognite/neat/_graph/queries/_base.py +22 -2
- cognite/neat/_graph/queries/_shared.py +4 -4
- cognite/neat/_graph/transformers/__init__.py +25 -9
- cognite/neat/_graph/transformers/_base.py +1 -1
- cognite/neat/_graph/transformers/_iodd.py +2 -2
- cognite/neat/_graph/transformers/_prune_graph.py +98 -24
- cognite/neat/_graph/transformers/_value_type.py +196 -2
- cognite/neat/_issues/__init__.py +6 -6
- cognite/neat/_issues/_base.py +4 -4
- cognite/neat/_issues/errors/__init__.py +22 -22
- cognite/neat/_issues/formatters.py +1 -1
- cognite/neat/_issues/warnings/__init__.py +20 -18
- cognite/neat/_issues/warnings/_properties.py +7 -0
- cognite/neat/_issues/warnings/user_modeling.py +2 -2
- cognite/neat/_rules/analysis/__init__.py +1 -1
- cognite/neat/_rules/catalog/__init__.py +1 -0
- cognite/neat/_rules/catalog/hello_world_pump.xlsx +0 -0
- cognite/neat/_rules/exporters/__init__.py +5 -5
- cognite/neat/_rules/exporters/_rules2excel.py +12 -6
- cognite/neat/_rules/importers/__init__.py +4 -4
- cognite/neat/_rules/importers/_base.py +7 -3
- cognite/neat/_rules/importers/_dms2rules.py +51 -19
- cognite/neat/_rules/importers/_rdf/__init__.py +1 -1
- cognite/neat/_rules/importers/_rdf/_base.py +2 -2
- cognite/neat/_rules/models/__init__.py +5 -5
- cognite/neat/_rules/models/_base_rules.py +1 -1
- cognite/neat/_rules/models/dms/__init__.py +11 -11
- cognite/neat/_rules/models/dms/_validation.py +16 -10
- cognite/neat/_rules/models/entities/__init__.py +26 -26
- cognite/neat/_rules/models/information/__init__.py +5 -5
- cognite/neat/_rules/models/information/_rules.py +3 -3
- cognite/neat/_rules/models/mapping/_classic2core.yaml +54 -8
- cognite/neat/_rules/transformers/__init__.py +12 -12
- cognite/neat/_rules/transformers/_pipelines.py +10 -5
- cognite/neat/_session/_base.py +71 -0
- cognite/neat/_session/_collector.py +3 -1
- cognite/neat/_session/_drop.py +10 -0
- cognite/neat/_session/_inspect.py +35 -1
- cognite/neat/_session/_mapping.py +5 -0
- cognite/neat/_session/_prepare.py +196 -7
- cognite/neat/_session/_read.py +180 -20
- cognite/neat/_session/_set.py +11 -1
- cognite/neat/_session/_show.py +41 -2
- cognite/neat/_session/_to.py +58 -10
- cognite/neat/_session/engine/__init__.py +1 -1
- cognite/neat/_session/engine/_load.py +3 -1
- cognite/neat/_store/__init__.py +3 -2
- cognite/neat/_store/{_base.py → _graph_store.py} +56 -2
- cognite/neat/_store/_provenance.py +11 -1
- cognite/neat/_store/_rules_store.py +20 -0
- cognite/neat/_utils/auth.py +7 -5
- cognite/neat/_utils/reader/__init__.py +1 -1
- cognite/neat/_version.py +2 -2
- cognite/neat/_workflows/__init__.py +3 -3
- cognite/neat/_workflows/steps/lib/current/graph_extractor.py +1 -1
- cognite/neat/_workflows/steps/lib/current/rules_exporter.py +1 -1
- cognite/neat/_workflows/steps/lib/current/rules_importer.py +2 -2
- cognite/neat/_workflows/steps/lib/io/io_steps.py +3 -3
- {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/METADATA +1 -1
- {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/RECORD +74 -72
- {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/LICENSE +0 -0
- {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/WHEEL +0 -0
- {cognite_neat-0.101.0.dist-info → cognite_neat-0.103.0.dist-info}/entry_points.txt +0 -0
cognite/neat/_session/_show.py
CHANGED
|
@@ -21,6 +21,30 @@ from .exceptions import session_class_wrapper
|
|
|
21
21
|
|
|
22
22
|
@session_class_wrapper
|
|
23
23
|
class ShowAPI:
|
|
24
|
+
"""Visualise a verified data model or instances contained in the graph store.
|
|
25
|
+
See, for example, `.data_model()` or `.instances()` for more.
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
Show instances
|
|
29
|
+
```python
|
|
30
|
+
from cognite.neat import NeatSession
|
|
31
|
+
from cognite.neat import get_cognite_client
|
|
32
|
+
|
|
33
|
+
client = get_cognite_client(env_file_path=".env")
|
|
34
|
+
neat = NeatSession(client, storage="oxigraph") # Storage optimised for storage visualisation
|
|
35
|
+
|
|
36
|
+
# .... intermediate steps of reading, infering verifying and converting a data model and instances
|
|
37
|
+
|
|
38
|
+
neat.show.instances()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
Show data model
|
|
43
|
+
```python
|
|
44
|
+
neat.show.data_model()
|
|
45
|
+
```
|
|
46
|
+
"""
|
|
47
|
+
|
|
24
48
|
def __init__(self, state: SessionState) -> None:
|
|
25
49
|
self._state = state
|
|
26
50
|
self.data_model = ShowDataModelAPI(self._state)
|
|
@@ -65,6 +89,8 @@ class ShowBaseAPI:
|
|
|
65
89
|
|
|
66
90
|
@session_class_wrapper
|
|
67
91
|
class ShowDataModelAPI(ShowBaseAPI):
|
|
92
|
+
"""Visualises the verified data model."""
|
|
93
|
+
|
|
68
94
|
def __init__(self, state: SessionState) -> None:
|
|
69
95
|
super().__init__(state)
|
|
70
96
|
self._state = state
|
|
@@ -97,9 +123,18 @@ class ShowDataModelAPI(ShowBaseAPI):
|
|
|
97
123
|
"""Generate a DiGraph from the last verified DMS rules."""
|
|
98
124
|
di_graph = nx.DiGraph()
|
|
99
125
|
|
|
126
|
+
# Views with properties or used as ValueType
|
|
127
|
+
# If a view is not used in properties or as ValueType, it is not added to the graph
|
|
128
|
+
# as we typically do not have the properties for it.
|
|
129
|
+
used_views = {prop_.view for prop_ in rules.properties} | {
|
|
130
|
+
prop_.value_type for prop_ in rules.properties if isinstance(prop_.value_type, ViewEntity)
|
|
131
|
+
}
|
|
132
|
+
|
|
100
133
|
# Add nodes and edges from Views sheet
|
|
101
134
|
for view in rules.views:
|
|
102
|
-
|
|
135
|
+
if view.view not in used_views:
|
|
136
|
+
continue
|
|
137
|
+
# if possible use humanreadable label coming from the view name
|
|
103
138
|
if not di_graph.has_node(view.view.suffix):
|
|
104
139
|
di_graph.add_node(view.view.suffix, label=view.view.suffix)
|
|
105
140
|
|
|
@@ -123,7 +158,7 @@ class ShowDataModelAPI(ShowBaseAPI):
|
|
|
123
158
|
|
|
124
159
|
# Add nodes and edges from Views sheet
|
|
125
160
|
for class_ in rules.classes:
|
|
126
|
-
# if possible use
|
|
161
|
+
# if possible use humanreadable label coming from the view name
|
|
127
162
|
if not di_graph.has_node(class_.class_.suffix):
|
|
128
163
|
di_graph.add_node(
|
|
129
164
|
class_.class_.suffix,
|
|
@@ -228,6 +263,8 @@ class ShowDataModelImplementsAPI(ShowBaseAPI):
|
|
|
228
263
|
|
|
229
264
|
@session_class_wrapper
|
|
230
265
|
class ShowDataModelProvenanceAPI(ShowBaseAPI):
|
|
266
|
+
"""Visualises the provenance or steps that have been executed in the NeatSession."""
|
|
267
|
+
|
|
231
268
|
def __init__(self, state: SessionState) -> None:
|
|
232
269
|
super().__init__(state)
|
|
233
270
|
self._state = state
|
|
@@ -288,6 +325,8 @@ class ShowDataModelProvenanceAPI(ShowBaseAPI):
|
|
|
288
325
|
|
|
289
326
|
@session_class_wrapper
|
|
290
327
|
class ShowInstanceAPI(ShowBaseAPI):
|
|
328
|
+
"""Visualise the instances contained in the graph store."""
|
|
329
|
+
|
|
291
330
|
def __init__(self, state: SessionState) -> None:
|
|
292
331
|
super().__init__(state)
|
|
293
332
|
self._state = state
|
cognite/neat/_session/_to.py
CHANGED
|
@@ -19,6 +19,11 @@ from .exceptions import NeatSessionError, session_class_wrapper
|
|
|
19
19
|
|
|
20
20
|
@session_class_wrapper
|
|
21
21
|
class ToAPI:
|
|
22
|
+
"""API used to write the contents of a NeatSession to a specified destination. For instance writing information
|
|
23
|
+
rules or DMS rules to a NEAT rules Excel spreadsheet, or writing a verified data model to CDF.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
22
27
|
def __init__(self, state: SessionState, client: NeatClient | None, verbose: bool) -> None:
|
|
23
28
|
self._state = state
|
|
24
29
|
self._verbose = verbose
|
|
@@ -34,8 +39,22 @@ class ToAPI:
|
|
|
34
39
|
Args:
|
|
35
40
|
io: The file path or file-like object to write the Excel file to.
|
|
36
41
|
model: The format of the data model to export. Defaults to None.
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
Export information model to excel rules sheet
|
|
45
|
+
```python
|
|
46
|
+
information_rules_file_name = "information_rules.xlsx"
|
|
47
|
+
neat.to.excel(information_rules_file_name, model="information")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
Export data model to excel rules sheet
|
|
52
|
+
```python
|
|
53
|
+
dms_rules_file_name = "dms_rules.xlsx"
|
|
54
|
+
neat.to.excel(information_rules_file_name, model="dms")
|
|
55
|
+
```
|
|
37
56
|
"""
|
|
38
|
-
exporter = exporters.ExcelExporter()
|
|
57
|
+
exporter = exporters.ExcelExporter(styling="maximal")
|
|
39
58
|
rules: VerifiedRules
|
|
40
59
|
if model == "information" or model == "logical":
|
|
41
60
|
rules = self._state.data_model.last_verified_information_rules[1]
|
|
@@ -63,13 +82,33 @@ class ToAPI:
|
|
|
63
82
|
format: The format of the YAML file. Defaults to "neat".
|
|
64
83
|
skip_system_spaces: If True, system spaces will be skipped. Defaults to True.
|
|
65
84
|
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
!!! note "YAML formats"
|
|
68
86
|
- "neat": This is the format Neat uses to store the data model.
|
|
69
87
|
- "toolkit": This is the format used by Cognite Toolkit, that matches the CDF API.
|
|
70
88
|
|
|
71
89
|
Returns:
|
|
72
90
|
str | None: If io is None, the YAML string will be returned. Otherwise, None will be returned.
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
Export to yaml file in the case of "neat" format
|
|
94
|
+
```python
|
|
95
|
+
your_yaml_file_name = "neat_rules.yaml"
|
|
96
|
+
neat.to.yaml(your_yaml_file_name, format="neat")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Example:
|
|
100
|
+
Export yaml files as a zip folder in the case of "toolkit" format
|
|
101
|
+
```python
|
|
102
|
+
your_zip_folder_name = "toolkit_data_model_files.zip"
|
|
103
|
+
neat.to.yaml(your_zip_folder_name, format="toolkit")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
Export yaml files to a folder in the case of "toolkit" format
|
|
108
|
+
```python
|
|
109
|
+
your_folder_name = "my_project/data_model_files"
|
|
110
|
+
neat.to.yaml(your_folder_name, format="toolkit")
|
|
111
|
+
```
|
|
73
112
|
"""
|
|
74
113
|
if format == "neat":
|
|
75
114
|
exporter = exporters.YAMLExporter()
|
|
@@ -97,12 +136,21 @@ class ToAPI:
|
|
|
97
136
|
|
|
98
137
|
@session_class_wrapper
|
|
99
138
|
class CDFToAPI:
|
|
139
|
+
"""Write a verified Data Model and Instances to CDF."""
|
|
140
|
+
|
|
100
141
|
def __init__(self, state: SessionState, client: NeatClient | None, verbose: bool) -> None:
|
|
101
142
|
self._client = client
|
|
102
143
|
self._state = state
|
|
103
144
|
self._verbose = verbose
|
|
104
145
|
|
|
105
146
|
def instances(self, space: str | None = None) -> UploadResultList:
|
|
147
|
+
"""Export the verified DMS instances to CDF.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
space: Name of instance space to use. Default is to suffix the schema space with '_instances'.
|
|
151
|
+
Note this space is required to be different than the space with the data model.
|
|
152
|
+
|
|
153
|
+
"""
|
|
106
154
|
if not self._client:
|
|
107
155
|
raise NeatSessionError("No CDF client provided!")
|
|
108
156
|
|
|
@@ -120,6 +168,7 @@ class CDFToAPI:
|
|
|
120
168
|
self._state.data_model.last_verified_dms_rules[1],
|
|
121
169
|
self._state.instances.store,
|
|
122
170
|
instance_space=space,
|
|
171
|
+
client=self._client,
|
|
123
172
|
)
|
|
124
173
|
result = loader.load_into_cdf(self._client)
|
|
125
174
|
self._state.instances.outcome.append(result)
|
|
@@ -144,13 +193,12 @@ class CDFToAPI:
|
|
|
144
193
|
Note this only applies to spaces and containers if they contain data.
|
|
145
194
|
components: The components to export. If None, all components will be exported. Defaults to None.
|
|
146
195
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
- "recreate": All components will be deleted and recreated. The exception is spaces, which will be updated.
|
|
196
|
+
!!! note "Data Model creation modes"
|
|
197
|
+
- "fail": If any component already exists, the export will fail.
|
|
198
|
+
- "skip": If any component already exists, it will be skipped.
|
|
199
|
+
- "update": If any component already exists, it will be updated.
|
|
200
|
+
- "force": If any component already exists, and the update fails, it will be deleted and recreated.
|
|
201
|
+
- "recreate": All components will be deleted and recreated. The exception is spaces, which will be updated.
|
|
154
202
|
|
|
155
203
|
"""
|
|
156
204
|
|
|
@@ -41,8 +41,10 @@ def load_neat_engine(client: CogniteClient | None, location: Literal["newest", "
|
|
|
41
41
|
|
|
42
42
|
if location == "newest" or not candidates:
|
|
43
43
|
# Loading in reverse order of priority
|
|
44
|
-
#
|
|
44
|
+
# 4. Downloads folder
|
|
45
45
|
candidates = _load_from_path(Path.home() / "Downloads", pattern, lower_bound, upper_bound)
|
|
46
|
+
# 3. Current working directory
|
|
47
|
+
candidates.update(_load_from_path(Path.cwd(), pattern, lower_bound, upper_bound))
|
|
46
48
|
# 2. CDF
|
|
47
49
|
if client:
|
|
48
50
|
candidates.update(_load_from_cdf(client, pattern, lower_bound, upper_bound, cache_dir))
|
cognite/neat/_store/__init__.py
CHANGED
|
@@ -195,8 +195,13 @@ class NeatGraphStore:
|
|
|
195
195
|
self, class_neat_id: URIRef, property_link_pairs: dict[str, URIRef] | None
|
|
196
196
|
) -> Iterable[tuple[str, dict[str | InstanceType, list[str]]]]:
|
|
197
197
|
if self.rules is None:
|
|
198
|
-
warnings.warn("Rules not found in graph store!", stacklevel=2)
|
|
198
|
+
warnings.warn("Rules not found in graph store! Aborting!", stacklevel=2)
|
|
199
199
|
return
|
|
200
|
+
if self.multi_type_instances:
|
|
201
|
+
warnings.warn(
|
|
202
|
+
"Multi typed instances detected, issues with loading can occur!",
|
|
203
|
+
stacklevel=2,
|
|
204
|
+
)
|
|
200
205
|
|
|
201
206
|
if cls := InformationAnalysis(self.rules).classes_by_neat_id.get(class_neat_id):
|
|
202
207
|
if property_link_pairs:
|
|
@@ -225,6 +230,11 @@ class NeatGraphStore:
|
|
|
225
230
|
if self.rules is None:
|
|
226
231
|
warnings.warn("Rules not found in graph store!", stacklevel=2)
|
|
227
232
|
return
|
|
233
|
+
if self.multi_type_instances:
|
|
234
|
+
warnings.warn(
|
|
235
|
+
"Multi typed instances detected, issues with loading can occur!",
|
|
236
|
+
stacklevel=2,
|
|
237
|
+
)
|
|
228
238
|
|
|
229
239
|
if class_entity not in [definition.class_ for definition in self.rules.classes]:
|
|
230
240
|
warnings.warn("Desired type not found in graph!", stacklevel=2)
|
|
@@ -267,7 +277,6 @@ class NeatGraphStore:
|
|
|
267
277
|
|
|
268
278
|
# get property types to guide process of removing or not namespaces from results
|
|
269
279
|
property_types = InformationAnalysis(self.rules).property_types(class_entity)
|
|
270
|
-
|
|
271
280
|
for instance_id in instance_ids:
|
|
272
281
|
if res := self.queries.describe(
|
|
273
282
|
instance_id=instance_id,
|
|
@@ -292,6 +301,11 @@ class NeatGraphStore:
|
|
|
292
301
|
if not self.rules:
|
|
293
302
|
warnings.warn("Rules not found in graph store!", stacklevel=2)
|
|
294
303
|
return
|
|
304
|
+
if self.multi_type_instances:
|
|
305
|
+
warnings.warn(
|
|
306
|
+
"Multi typed instances detected, issues with loading can occur!",
|
|
307
|
+
stacklevel=2,
|
|
308
|
+
)
|
|
295
309
|
|
|
296
310
|
class_entity = ClassEntity(prefix=self.rules.metadata.prefix, suffix=class_)
|
|
297
311
|
|
|
@@ -301,6 +315,39 @@ class NeatGraphStore:
|
|
|
301
315
|
|
|
302
316
|
yield from self._read_via_class_entity(class_entity)
|
|
303
317
|
|
|
318
|
+
def count_of_id(self, neat_id: URIRef) -> int:
|
|
319
|
+
"""Count the number of instances of a given type
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
neat_id: Type for which instances are to be counted
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
Number of instances
|
|
326
|
+
"""
|
|
327
|
+
if not self.rules:
|
|
328
|
+
warnings.warn("Rules not found in graph store!", stacklevel=2)
|
|
329
|
+
return 0
|
|
330
|
+
|
|
331
|
+
class_entity = next(
|
|
332
|
+
(definition.class_ for definition in self.rules.classes if definition.neatId == neat_id), None
|
|
333
|
+
)
|
|
334
|
+
if not class_entity:
|
|
335
|
+
warnings.warn("Desired type not found in graph!", stacklevel=2)
|
|
336
|
+
return 0
|
|
337
|
+
|
|
338
|
+
if not (class_uri := InformationAnalysis(self.rules).class_uri(class_entity)):
|
|
339
|
+
warnings.warn(
|
|
340
|
+
f"Class {class_entity.suffix} does not have namespace defined for prefix {class_entity.prefix} Rules!",
|
|
341
|
+
stacklevel=2,
|
|
342
|
+
)
|
|
343
|
+
return 0
|
|
344
|
+
|
|
345
|
+
return self.count_of_type(class_uri)
|
|
346
|
+
|
|
347
|
+
def count_of_type(self, class_uri: URIRef) -> int:
|
|
348
|
+
query = f"SELECT (COUNT(?instance) AS ?instanceCount) WHERE {{ ?instance a <{class_uri}> }}"
|
|
349
|
+
return int(next(iter(self.graph.query(query)))[0]) # type: ignore[arg-type, index]
|
|
350
|
+
|
|
304
351
|
def _parse_file(
|
|
305
352
|
self,
|
|
306
353
|
filepath: Path,
|
|
@@ -390,6 +437,10 @@ class NeatGraphStore:
|
|
|
390
437
|
def summary(self) -> pd.DataFrame:
|
|
391
438
|
return pd.DataFrame(self.queries.summarize_instances(), columns=["Type", "Occurrence"])
|
|
392
439
|
|
|
440
|
+
@property
|
|
441
|
+
def multi_type_instances(self) -> dict[str, list[str]]:
|
|
442
|
+
return self.queries.multi_type_instances()
|
|
443
|
+
|
|
393
444
|
def _repr_html_(self) -> str:
|
|
394
445
|
provenance = self.provenance._repr_html_()
|
|
395
446
|
summary: pd.DataFrame = self.summary
|
|
@@ -404,6 +455,9 @@ class NeatGraphStore:
|
|
|
404
455
|
f"{cast(pd.DataFrame, self._shorten_summary(summary))._repr_html_()}" # type: ignore[operator]
|
|
405
456
|
)
|
|
406
457
|
|
|
458
|
+
if self.multi_type_instances:
|
|
459
|
+
summary_text += "<br><strong>Multi value instances detected! Loading could have issues!</strong></br>" # type: ignore
|
|
460
|
+
|
|
407
461
|
return f"{summary_text}" f"{provenance}"
|
|
408
462
|
|
|
409
463
|
def _shorten_summary(self, summary: pd.DataFrame) -> pd.DataFrame:
|
|
@@ -20,12 +20,13 @@ 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 Optional, TypeVar
|
|
23
|
+
from typing import Generic, Optional, TypeVar
|
|
24
24
|
|
|
25
25
|
from cognite.client.data_classes.data_modeling import DataModelId, DataModelIdentifier
|
|
26
26
|
from rdflib import PROV, RDF, Literal, URIRef
|
|
27
27
|
|
|
28
28
|
from cognite.neat._constants import CDF_NAMESPACE, DEFAULT_NAMESPACE
|
|
29
|
+
from cognite.neat._issues import IssueList
|
|
29
30
|
from cognite.neat._rules._shared import JustRules, ReadRules, VerifiedRules
|
|
30
31
|
from cognite.neat._shared import FrozenNeatObject, NeatList, Triple
|
|
31
32
|
|
|
@@ -50,6 +51,7 @@ UNKNOWN_AGENT = Agent(acted_on_behalf_of="UNKNOWN", id_=DEFAULT_NAMESPACE["unkno
|
|
|
50
51
|
@dataclass(frozen=True)
|
|
51
52
|
class Entity:
|
|
52
53
|
was_attributed_to: Agent
|
|
54
|
+
issues: IssueList = field(default_factory=IssueList)
|
|
53
55
|
was_generated_by: Optional["Activity"] = field(default=None, repr=False)
|
|
54
56
|
id_: URIRef = DEFAULT_NAMESPACE["graph-store"]
|
|
55
57
|
|
|
@@ -117,6 +119,14 @@ class Entity:
|
|
|
117
119
|
)
|
|
118
120
|
|
|
119
121
|
|
|
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
|
+
|
|
120
130
|
INSTANCES_ENTITY = Entity(was_attributed_to=NEAT_AGENT, id_=CDF_NAMESPACE["instances"])
|
|
121
131
|
|
|
122
132
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from cognite.neat._issues import IssueList
|
|
2
|
+
from cognite.neat._rules.exporters import BaseExporter
|
|
3
|
+
from cognite.neat._rules.importers import BaseImporter
|
|
4
|
+
from cognite.neat._rules.transformers import RulesTransformer
|
|
5
|
+
|
|
6
|
+
from ._provenance import Provenance
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NeatRulesStore:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self._provenance = Provenance()
|
|
12
|
+
|
|
13
|
+
def write(self, importer: BaseImporter) -> IssueList:
|
|
14
|
+
raise NotImplementedError()
|
|
15
|
+
|
|
16
|
+
def transform(self, transformer: RulesTransformer) -> IssueList:
|
|
17
|
+
raise NotImplementedError()
|
|
18
|
+
|
|
19
|
+
def read(self, exporter: BaseExporter) -> IssueList:
|
|
20
|
+
raise NotImplementedError()
|
cognite/neat/_utils/auth.py
CHANGED
|
@@ -11,7 +11,7 @@ from cognite.client.credentials import CredentialProvider, OAuthClientCredential
|
|
|
11
11
|
from cognite.neat import _version
|
|
12
12
|
from cognite.neat._utils.auxiliary import local_import
|
|
13
13
|
|
|
14
|
-
__all__ = ["
|
|
14
|
+
__all__ = ["EnvironmentVariables", "get_cognite_client"]
|
|
15
15
|
|
|
16
16
|
_LOGIN_FLOW: TypeAlias = Literal["infer", "client_credentials", "interactive", "token"]
|
|
17
17
|
_VALID_LOGIN_FLOWS = get_args(_LOGIN_FLOW)
|
|
@@ -32,10 +32,7 @@ def get_cognite_client(env_file_name: str) -> CogniteClient:
|
|
|
32
32
|
"""
|
|
33
33
|
if not env_file_name.endswith(".env"):
|
|
34
34
|
raise ValueError("env_file_name must end with '.env'")
|
|
35
|
-
|
|
36
|
-
variables = EnvironmentVariables.create_from_environ()
|
|
37
|
-
return variables.get_client()
|
|
38
|
-
|
|
35
|
+
# First try to load from .env file in repository root
|
|
39
36
|
repo_root = _repo_root()
|
|
40
37
|
if repo_root:
|
|
41
38
|
with suppress(KeyError, FileNotFoundError, TypeError):
|
|
@@ -43,6 +40,11 @@ def get_cognite_client(env_file_name: str) -> CogniteClient:
|
|
|
43
40
|
client = variables.get_client()
|
|
44
41
|
print(f"Found {env_file_name} file in repository root. Loaded variables from {env_file_name} file.")
|
|
45
42
|
return client
|
|
43
|
+
# Then try to load from environment variables
|
|
44
|
+
with suppress(KeyError):
|
|
45
|
+
variables = EnvironmentVariables.create_from_environ()
|
|
46
|
+
return variables.get_client()
|
|
47
|
+
# If not found, prompt the user
|
|
46
48
|
variables = _prompt_user()
|
|
47
49
|
if repo_root and _env_in_gitignore(repo_root, env_file_name):
|
|
48
50
|
local_import("rich", "jupyter")
|
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.
|
|
2
|
-
__engine__ = "^2.0.
|
|
1
|
+
__version__ = "0.103.0"
|
|
2
|
+
__engine__ = "^2.0.3"
|
|
@@ -9,9 +9,9 @@ from cognite.neat._workflows.model import (
|
|
|
9
9
|
|
|
10
10
|
__all__ = [
|
|
11
11
|
"BaseWorkflow",
|
|
12
|
-
"
|
|
12
|
+
"FlowMessage",
|
|
13
|
+
"WorkflowFullStateReport",
|
|
13
14
|
"WorkflowManager",
|
|
15
|
+
"WorkflowStepDefinition",
|
|
14
16
|
"WorkflowStepEvent",
|
|
15
|
-
"WorkflowFullStateReport",
|
|
16
|
-
"FlowMessage",
|
|
17
17
|
]
|
|
@@ -10,7 +10,7 @@ from cognite.neat._workflows.model import FlowMessage, StepExecutionStatus
|
|
|
10
10
|
from cognite.neat._workflows.steps.data_contracts import MultiRuleData, NeatGraph
|
|
11
11
|
from cognite.neat._workflows.steps.step_model import Configurable, Step
|
|
12
12
|
|
|
13
|
-
__all__ = ["
|
|
13
|
+
__all__ = ["GraphFromMockData", "GraphFromRdfFile"]
|
|
14
14
|
|
|
15
15
|
CATEGORY = __name__.split(".")[-1].replace("_", " ").title()
|
|
16
16
|
|
|
@@ -16,12 +16,12 @@ from cognite.neat._workflows.steps.data_contracts import CogniteClient, MultiRul
|
|
|
16
16
|
from cognite.neat._workflows.steps.step_model import Configurable, Step
|
|
17
17
|
|
|
18
18
|
__all__ = [
|
|
19
|
+
"DeleteDataModelFromCDF",
|
|
19
20
|
"RulesToDMS",
|
|
20
21
|
"RulesToExcel",
|
|
21
22
|
"RulesToOntology",
|
|
22
23
|
"RulesToSHACL",
|
|
23
24
|
"RulesToSemanticDataModel",
|
|
24
|
-
"DeleteDataModelFromCDF",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
|
|
@@ -19,10 +19,10 @@ from cognite.neat._workflows.steps.step_model import Configurable, Step
|
|
|
19
19
|
CATEGORY = __name__.split(".")[-1].replace("_", " ").title()
|
|
20
20
|
|
|
21
21
|
__all__ = [
|
|
22
|
+
"DMSToRules",
|
|
22
23
|
"ExcelToRules",
|
|
23
|
-
"OntologyToRules",
|
|
24
24
|
"IMFToRules",
|
|
25
|
-
"
|
|
25
|
+
"OntologyToRules",
|
|
26
26
|
"RulesInferenceFromRdfFile",
|
|
27
27
|
]
|
|
28
28
|
|
|
@@ -14,11 +14,11 @@ CATEGORY = "IO Steps"
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
__all__ = [
|
|
17
|
-
"
|
|
18
|
-
"UploadFileToGitHub",
|
|
17
|
+
"DownloadDataFromRestApiToFile",
|
|
19
18
|
"DownloadFileFromCDF",
|
|
19
|
+
"DownloadFileFromGitHub",
|
|
20
20
|
"UploadFileToCDF",
|
|
21
|
-
"
|
|
21
|
+
"UploadFileToGitHub",
|
|
22
22
|
]
|
|
23
23
|
|
|
24
24
|
|