cognite-neat 0.123.18__py3-none-any.whl → 0.123.20__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/_version.py +1 -1
- cognite/neat/core/_data_model/_shared.py +2 -2
- cognite/neat/core/_data_model/importers/__init__.py +9 -1
- cognite/neat/core/_data_model/importers/_dict2data_model.py +1 -1
- cognite/neat/core/_data_model/importers/_dms2data_model.py +1 -1
- cognite/neat/core/_data_model/importers/_graph2data_model.py +299 -0
- cognite/neat/core/_data_model/importers/_rdf/_base.py +1 -1
- cognite/neat/core/_data_model/importers/_spreadsheet2data_model.py +3 -2
- cognite/neat/core/_data_model/models/_import_contexts.py +82 -0
- cognite/neat/core/_data_model/models/conceptual/_validation.py +3 -3
- cognite/neat/core/_data_model/models/physical/_validation.py +33 -3
- cognite/neat/core/_data_model/transformers/_converters.py +4 -4
- cognite/neat/core/_issues/_contextmanagers.py +8 -6
- cognite/neat/core/_issues/_factory.py +10 -7
- cognite/neat/core/_issues/warnings/_models.py +9 -0
- cognite/neat/core/_store/_instance.py +1 -1
- cognite/neat/core/_utils/auxiliary.py +1 -1
- cognite/neat/session/_base.py +4 -0
- cognite/neat/session/_session/__init__.py +0 -0
- cognite/neat/session/_session/_data_model.py +154 -0
- {cognite_neat-0.123.18.dist-info → cognite_neat-0.123.20.dist-info}/METADATA +1 -1
- {cognite_neat-0.123.18.dist-info → cognite_neat-0.123.20.dist-info}/RECORD +24 -20
- {cognite_neat-0.123.18.dist-info → cognite_neat-0.123.20.dist-info}/WHEEL +0 -0
- {cognite_neat-0.123.18.dist-info → cognite_neat-0.123.20.dist-info}/licenses/LICENSE +0 -0
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.123.
|
|
1
|
+
__version__ = "0.123.20"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -5,13 +5,13 @@ from cognite.neat.core._data_model.models import (
|
|
|
5
5
|
ConceptualDataModel,
|
|
6
6
|
PhysicalDataModel,
|
|
7
7
|
)
|
|
8
|
+
from cognite.neat.core._data_model.models._import_contexts import ImportContext
|
|
8
9
|
from cognite.neat.core._data_model.models.conceptual._unverified import (
|
|
9
10
|
UnverifiedConceptualDataModel,
|
|
10
11
|
)
|
|
11
12
|
from cognite.neat.core._data_model.models.physical._unverified import (
|
|
12
13
|
UnverifiedPhysicalDataModel,
|
|
13
14
|
)
|
|
14
|
-
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
15
15
|
|
|
16
16
|
VerifiedDataModel: TypeAlias = ConceptualDataModel | PhysicalDataModel
|
|
17
17
|
|
|
@@ -32,7 +32,7 @@ class ImportedDataModel(Generic[T_UnverifiedDataModel]):
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
unverified_data_model: T_UnverifiedDataModel | None
|
|
35
|
-
context:
|
|
35
|
+
context: ImportContext | None = None
|
|
36
36
|
|
|
37
37
|
@classmethod
|
|
38
38
|
def display_type_name(cls) -> str:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from ._base import BaseImporter
|
|
2
2
|
from ._dict2data_model import DictImporter
|
|
3
3
|
from ._dms2data_model import DMSImporter
|
|
4
|
+
from ._graph2data_model import GraphImporter
|
|
4
5
|
from ._rdf import InferenceImporter, OWLImporter, SubclassInferenceImporter
|
|
5
6
|
from ._spreadsheet2data_model import ExcelImporter
|
|
6
7
|
|
|
@@ -9,13 +10,20 @@ __all__ = [
|
|
|
9
10
|
"DMSImporter",
|
|
10
11
|
"DictImporter",
|
|
11
12
|
"ExcelImporter",
|
|
13
|
+
"GraphImporter",
|
|
12
14
|
"InferenceImporter",
|
|
13
15
|
"OWLImporter",
|
|
14
16
|
"SubclassInferenceImporter",
|
|
15
17
|
]
|
|
16
18
|
|
|
17
19
|
DataModelImporters = (
|
|
18
|
-
OWLImporter
|
|
20
|
+
OWLImporter
|
|
21
|
+
| DMSImporter
|
|
22
|
+
| ExcelImporter
|
|
23
|
+
| DictImporter
|
|
24
|
+
| InferenceImporter
|
|
25
|
+
| SubclassInferenceImporter
|
|
26
|
+
| GraphImporter
|
|
19
27
|
)
|
|
20
28
|
|
|
21
29
|
|
|
@@ -128,4 +128,4 @@ class DictImporter(BaseImporter[T_UnverifiedDataModel]):
|
|
|
128
128
|
if self._read_issues.has_errors:
|
|
129
129
|
raise MultiValueError(self._read_issues.errors)
|
|
130
130
|
|
|
131
|
-
return ImportedDataModel[T_UnverifiedDataModel](data_model
|
|
131
|
+
return ImportedDataModel[T_UnverifiedDataModel](data_model)
|
|
@@ -276,7 +276,7 @@ class DMSImporter(BaseImporter[UnverifiedPhysicalDataModel]):
|
|
|
276
276
|
self.issue_list.trigger_warnings()
|
|
277
277
|
if self.issue_list.has_errors:
|
|
278
278
|
raise MultiValueError(self.issue_list.errors)
|
|
279
|
-
return ImportedDataModel(user_data_model,
|
|
279
|
+
return ImportedDataModel(user_data_model, None)
|
|
280
280
|
|
|
281
281
|
def _create_data_model_components(
|
|
282
282
|
self,
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
import urllib.parse
|
|
3
|
+
import warnings
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
from collections.abc import Iterable
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from typing import cast
|
|
9
|
+
|
|
10
|
+
from cognite.client.data_classes.data_modeling import DataModelId, DataModelIdentifier
|
|
11
|
+
from rdflib import RDF, RDFS, Namespace, URIRef
|
|
12
|
+
from rdflib import Literal as RdfLiteral
|
|
13
|
+
from rdflib.query import ResultRow
|
|
14
|
+
|
|
15
|
+
from cognite.neat.core._config import GLOBAL_CONFIG
|
|
16
|
+
from cognite.neat.core._constants import NEAT
|
|
17
|
+
from cognite.neat.core._data_model._shared import ImportedDataModel
|
|
18
|
+
from cognite.neat.core._data_model.models import UnverifiedConceptualDataModel
|
|
19
|
+
from cognite.neat.core._data_model.models._import_contexts import GraphContext
|
|
20
|
+
from cognite.neat.core._data_model.models.conceptual import (
|
|
21
|
+
UnverifiedConcept,
|
|
22
|
+
UnverifiedConceptualMetadata,
|
|
23
|
+
UnverifiedConceptualProperty,
|
|
24
|
+
)
|
|
25
|
+
from cognite.neat.core._data_model.models.entities import UnknownEntity
|
|
26
|
+
from cognite.neat.core._issues.errors import NeatValueError
|
|
27
|
+
from cognite.neat.core._issues.warnings import NeatValueWarning
|
|
28
|
+
from cognite.neat.core._store import NeatInstanceStore
|
|
29
|
+
from cognite.neat.core._utils.collection_ import iterate_progress_bar
|
|
30
|
+
from cognite.neat.core._utils.rdf_ import split_uri
|
|
31
|
+
|
|
32
|
+
from ._base import BaseImporter
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Internal helper class
|
|
36
|
+
@dataclass
|
|
37
|
+
class _ReadProperties:
|
|
38
|
+
type_uri: URIRef
|
|
39
|
+
property_uri: URIRef
|
|
40
|
+
value_type: URIRef
|
|
41
|
+
parent_uri: URIRef | None
|
|
42
|
+
max_occurrence: int
|
|
43
|
+
instance_count: int
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class GraphImporter(BaseImporter[UnverifiedConceptualDataModel]):
|
|
47
|
+
"""Infers a data model from the triples in a Graph Store.
|
|
48
|
+
Args:
|
|
49
|
+
store: The graph store to read from.
|
|
50
|
+
data_model_id: The data model id to be used for the imported rules.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
_ORDERED_CONCEPTS_QUERY = """SELECT DISTINCT ?concept (count(?s) as ?instances )
|
|
54
|
+
WHERE { ?s a ?concept }
|
|
55
|
+
group by ?concept order by DESC(?instances)"""
|
|
56
|
+
|
|
57
|
+
_TYPE_PARENT_QUERY = f"""SELECT ?parent ?type
|
|
58
|
+
WHERE {{ ?s a ?type .
|
|
59
|
+
?type <{RDFS.subClassOf}> ?parent }}"""
|
|
60
|
+
|
|
61
|
+
_PROPERTIES_QUERY = """SELECT DISTINCT ?property ?valueType
|
|
62
|
+
WHERE {{
|
|
63
|
+
?s a <{type}> .
|
|
64
|
+
?s ?property ?object .
|
|
65
|
+
OPTIONAL {{ ?object a ?objectType }}
|
|
66
|
+
BIND(
|
|
67
|
+
IF(
|
|
68
|
+
isLiteral(?object), datatype(?object),
|
|
69
|
+
IF(BOUND(?objectType), ?objectType, <{unknown_type}>)
|
|
70
|
+
) AS ?valueType
|
|
71
|
+
)
|
|
72
|
+
}}"""
|
|
73
|
+
|
|
74
|
+
_MAX_OCCURRENCE_QUERY = """SELECT (MAX(?count) AS ?maxCount)
|
|
75
|
+
WHERE {{
|
|
76
|
+
{{
|
|
77
|
+
SELECT ?subject (COUNT(?object) AS ?count)
|
|
78
|
+
WHERE {{
|
|
79
|
+
?subject a <{type}> .
|
|
80
|
+
?subject <{property}> ?object .
|
|
81
|
+
}}
|
|
82
|
+
GROUP BY ?subject
|
|
83
|
+
}}
|
|
84
|
+
}}"""
|
|
85
|
+
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
store: NeatInstanceStore,
|
|
89
|
+
data_model_id: DataModelIdentifier = ("neat_space", "NeatInferredDataModel", "v1"),
|
|
90
|
+
) -> None:
|
|
91
|
+
self.store = store
|
|
92
|
+
self.data_model_id = DataModelId.load(data_model_id)
|
|
93
|
+
if self.data_model_id.version is None:
|
|
94
|
+
raise NeatValueError("Version is required when setting a Data Model ID")
|
|
95
|
+
|
|
96
|
+
def to_data_model(self) -> ImportedDataModel[UnverifiedConceptualDataModel]:
|
|
97
|
+
metadata = self._create_default_metadata()
|
|
98
|
+
if not self.store.queries.select.has_data():
|
|
99
|
+
warnings.warn(NeatValueWarning("Cannot infer data model. No data found in the graph."), stacklevel=2)
|
|
100
|
+
return ImportedDataModel(UnverifiedConceptualDataModel(metadata, [], [], {}), None)
|
|
101
|
+
|
|
102
|
+
parent_by_child = self._read_parent_by_child_from_graph()
|
|
103
|
+
count_by_type = self._read_types_with_counts_from_graph()
|
|
104
|
+
if not count_by_type:
|
|
105
|
+
warnings.warn(
|
|
106
|
+
NeatValueWarning("Cannot infer data model. No RDF.type triples found in the graph."), stacklevel=2
|
|
107
|
+
)
|
|
108
|
+
return ImportedDataModel(UnverifiedConceptualDataModel(metadata, [], [], {}), None)
|
|
109
|
+
|
|
110
|
+
read_properties = self._read_concept_properties_from_graph(count_by_type, parent_by_child)
|
|
111
|
+
|
|
112
|
+
prefixes: dict[str, Namespace] = {}
|
|
113
|
+
concepts, properties = self._create_concepts_properties(read_properties, prefixes)
|
|
114
|
+
|
|
115
|
+
return ImportedDataModel(
|
|
116
|
+
UnverifiedConceptualDataModel(
|
|
117
|
+
metadata=metadata,
|
|
118
|
+
concepts=concepts,
|
|
119
|
+
properties=properties,
|
|
120
|
+
prefixes=prefixes,
|
|
121
|
+
),
|
|
122
|
+
context=GraphContext({"inferred_from": count_by_type}),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def _read_parent_by_child_from_graph(self) -> dict[URIRef, URIRef]:
|
|
126
|
+
parent_by_child: dict[URIRef, URIRef] = {}
|
|
127
|
+
for result_row in self.store.dataset.query(self._TYPE_PARENT_QUERY):
|
|
128
|
+
parent_uri, child_uri = cast(tuple[URIRef, URIRef], result_row)
|
|
129
|
+
parent_by_child[child_uri] = parent_uri
|
|
130
|
+
return parent_by_child
|
|
131
|
+
|
|
132
|
+
def _read_types_with_counts_from_graph(self) -> dict[URIRef, int]:
|
|
133
|
+
count_by_type: dict[URIRef, int] = {}
|
|
134
|
+
# Reads all types and their instance counts from the graph
|
|
135
|
+
for result_row in self.store.dataset.query(self._ORDERED_CONCEPTS_QUERY):
|
|
136
|
+
type_uri, instance_count_literal = cast(tuple[URIRef, RdfLiteral], result_row)
|
|
137
|
+
count_by_type[type_uri] = instance_count_literal.toPython()
|
|
138
|
+
return count_by_type
|
|
139
|
+
|
|
140
|
+
def _read_concept_properties_from_graph(
|
|
141
|
+
self, count_by_type: dict[URIRef, int], parent_by_child: dict[URIRef, URIRef]
|
|
142
|
+
) -> list[_ReadProperties]:
|
|
143
|
+
read_properties: list[_ReadProperties] = []
|
|
144
|
+
|
|
145
|
+
total_instance_count = sum(count_by_type.values())
|
|
146
|
+
iterable = count_by_type.items()
|
|
147
|
+
if GLOBAL_CONFIG.use_iterate_bar_threshold and total_instance_count > GLOBAL_CONFIG.use_iterate_bar_threshold:
|
|
148
|
+
iterable = iterate_progress_bar(iterable, len(count_by_type), "Inferring types...") # type: ignore[assignment]
|
|
149
|
+
|
|
150
|
+
for type_uri, instance_count in iterable:
|
|
151
|
+
property_query = self._PROPERTIES_QUERY.format(type=type_uri, unknown_type=NEAT.UnknownType)
|
|
152
|
+
for result_row in self.store.dataset.query(property_query):
|
|
153
|
+
property_uri, value_type_uri = cast(tuple[URIRef, URIRef], result_row)
|
|
154
|
+
if property_uri == RDF.type:
|
|
155
|
+
continue
|
|
156
|
+
occurrence_query = self._MAX_OCCURRENCE_QUERY.format(type=type_uri, property=property_uri)
|
|
157
|
+
max_occurrence = 1 # default value
|
|
158
|
+
# We know that the _MAX_OCCURRENCE_QUERY will return a ResultRow
|
|
159
|
+
occurrence_results = list(cast(ResultRow, self.store.dataset.query(occurrence_query)))
|
|
160
|
+
if occurrence_results and occurrence_results[0] and occurrence_results[0][0]:
|
|
161
|
+
max_occurrence_literal = cast(RdfLiteral, occurrence_results[0][0])
|
|
162
|
+
max_occurrence = int(max_occurrence_literal.toPython())
|
|
163
|
+
read_properties.append(
|
|
164
|
+
_ReadProperties(
|
|
165
|
+
type_uri=type_uri,
|
|
166
|
+
property_uri=property_uri,
|
|
167
|
+
parent_uri=parent_by_child.get(type_uri),
|
|
168
|
+
value_type=value_type_uri,
|
|
169
|
+
max_occurrence=max_occurrence,
|
|
170
|
+
instance_count=instance_count,
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
return read_properties
|
|
174
|
+
|
|
175
|
+
def _create_concepts_properties(
|
|
176
|
+
self, read_properties: list[_ReadProperties], prefixes: dict[str, Namespace]
|
|
177
|
+
) -> tuple[list[UnverifiedConcept], list[UnverifiedConceptualProperty]]:
|
|
178
|
+
concepts: list[UnverifiedConcept] = []
|
|
179
|
+
properties: list[UnverifiedConceptualProperty] = []
|
|
180
|
+
|
|
181
|
+
# Help for IDE
|
|
182
|
+
type_uri: URIRef
|
|
183
|
+
parent_uri: URIRef
|
|
184
|
+
for parent_uri, parent_concepts_properties_iterable in itertools.groupby(
|
|
185
|
+
sorted(read_properties, key=lambda x: x.parent_uri or NEAT.EmptyType),
|
|
186
|
+
key=lambda x: x.parent_uri or NEAT.EmptyType,
|
|
187
|
+
):
|
|
188
|
+
parent_str: str | None = None
|
|
189
|
+
if parent_uri != NEAT.EmptyType:
|
|
190
|
+
parent_str, parent_cls = self._create_concept(parent_uri, set_instance_source=False, prefixes=prefixes)
|
|
191
|
+
concepts.append(parent_cls)
|
|
192
|
+
|
|
193
|
+
properties_by_concept_by_property = self._get_properties_by_concept_by_property(
|
|
194
|
+
parent_concepts_properties_iterable
|
|
195
|
+
)
|
|
196
|
+
for type_uri, properties_by_property_uri in properties_by_concept_by_property.items():
|
|
197
|
+
concept_str, concept = self._create_concept(
|
|
198
|
+
type_uri, set_instance_source=True, prefixes=prefixes, implements=parent_str
|
|
199
|
+
)
|
|
200
|
+
concepts.append(concept)
|
|
201
|
+
for property_uri, read_properties in properties_by_property_uri.items():
|
|
202
|
+
namespace, property_suffix = split_uri(property_uri)
|
|
203
|
+
(self._add_uri_namespace_to_prefixes(namespace, prefixes),)
|
|
204
|
+
properties.append(
|
|
205
|
+
self._create_property(
|
|
206
|
+
read_properties, concept_str, property_uri, urllib.parse.unquote(property_suffix), prefixes
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
return concepts, properties
|
|
210
|
+
|
|
211
|
+
@staticmethod
|
|
212
|
+
def _get_properties_by_concept_by_property(
|
|
213
|
+
parent_concept_properties_iterable: Iterable[_ReadProperties],
|
|
214
|
+
) -> dict[URIRef, dict[URIRef, list[_ReadProperties]]]:
|
|
215
|
+
properties_by_concept_by_property: dict[URIRef, dict[URIRef, list[_ReadProperties]]] = {}
|
|
216
|
+
for concept_uri, concept_properties_iterable in itertools.groupby(
|
|
217
|
+
sorted(parent_concept_properties_iterable, key=lambda x: x.type_uri), key=lambda x: x.type_uri
|
|
218
|
+
):
|
|
219
|
+
properties_by_concept_by_property[concept_uri] = defaultdict(list)
|
|
220
|
+
for read_prop in concept_properties_iterable:
|
|
221
|
+
properties_by_concept_by_property[concept_uri][read_prop.property_uri].append(read_prop)
|
|
222
|
+
return properties_by_concept_by_property
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def _create_concept(
|
|
226
|
+
cls, type_uri: URIRef, set_instance_source: bool, prefixes: dict[str, Namespace], implements: str | None = None
|
|
227
|
+
) -> tuple[str, UnverifiedConcept]:
|
|
228
|
+
namespace, suffix = split_uri(type_uri)
|
|
229
|
+
cls._add_uri_namespace_to_prefixes(namespace, prefixes)
|
|
230
|
+
concept_str = urllib.parse.unquote(suffix)
|
|
231
|
+
return concept_str, UnverifiedConcept(
|
|
232
|
+
concept=concept_str, implements=implements, instance_source=type_uri if set_instance_source else None
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def _create_property(
|
|
236
|
+
self,
|
|
237
|
+
read_properties: list[_ReadProperties],
|
|
238
|
+
concept_str: str,
|
|
239
|
+
property_uri: URIRef,
|
|
240
|
+
property_id: str,
|
|
241
|
+
prefixes: dict[str, Namespace],
|
|
242
|
+
) -> UnverifiedConceptualProperty:
|
|
243
|
+
first = read_properties[0]
|
|
244
|
+
value_type = self._get_value_type(read_properties, prefixes)
|
|
245
|
+
return UnverifiedConceptualProperty(
|
|
246
|
+
concept=concept_str,
|
|
247
|
+
property_=property_id,
|
|
248
|
+
max_count=first.max_occurrence,
|
|
249
|
+
value_type=value_type,
|
|
250
|
+
instance_source=[property_uri],
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
@classmethod
|
|
254
|
+
def _get_value_type(
|
|
255
|
+
cls, read_properties: list[_ReadProperties], prefixes: dict[str, Namespace]
|
|
256
|
+
) -> str | UnknownEntity:
|
|
257
|
+
value_types = {prop.value_type for prop in read_properties}
|
|
258
|
+
if len(value_types) == 1:
|
|
259
|
+
uri_ref = value_types.pop()
|
|
260
|
+
if uri_ref == NEAT.UnknownType:
|
|
261
|
+
return UnknownEntity()
|
|
262
|
+
namespace, suffix = split_uri(uri_ref)
|
|
263
|
+
cls._add_uri_namespace_to_prefixes(namespace, prefixes)
|
|
264
|
+
return suffix
|
|
265
|
+
uri_refs: list[str] = []
|
|
266
|
+
for uri_ref in value_types:
|
|
267
|
+
if uri_ref == NEAT.UnknownType:
|
|
268
|
+
return UnknownEntity()
|
|
269
|
+
namespace, suffix = split_uri(uri_ref)
|
|
270
|
+
cls._add_uri_namespace_to_prefixes(namespace, prefixes)
|
|
271
|
+
uri_refs.append(suffix)
|
|
272
|
+
# Sort the URIs to ensure deterministic output
|
|
273
|
+
return ", ".join(sorted(uri_refs))
|
|
274
|
+
|
|
275
|
+
def _create_default_metadata(self) -> UnverifiedConceptualMetadata:
|
|
276
|
+
now = datetime.now(timezone.utc)
|
|
277
|
+
name = self.data_model_id.external_id.replace("_", " ").title()
|
|
278
|
+
return UnverifiedConceptualMetadata(
|
|
279
|
+
space=self.data_model_id.space,
|
|
280
|
+
external_id=self.data_model_id.external_id,
|
|
281
|
+
# Validated in the constructor
|
|
282
|
+
version=cast(str, self.data_model_id.version),
|
|
283
|
+
name=name,
|
|
284
|
+
creator="NEAT",
|
|
285
|
+
created=now,
|
|
286
|
+
updated=now,
|
|
287
|
+
description="Inferred model from knowledge graph",
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
@classmethod
|
|
291
|
+
def _add_uri_namespace_to_prefixes(cls, namespace: str, prefixes: dict[str, Namespace]) -> None:
|
|
292
|
+
"""Add URI to prefixes dict if not already present
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
URI: URI from which namespace is being extracted
|
|
296
|
+
prefixes: Dict of prefixes and namespaces
|
|
297
|
+
"""
|
|
298
|
+
if Namespace(namespace) not in prefixes.values():
|
|
299
|
+
prefixes[f"prefix_{len(prefixes) + 1}"] = Namespace(namespace)
|
|
@@ -130,7 +130,7 @@ class BaseRDFImporter(BaseImporter[UnverifiedConceptualDataModel]):
|
|
|
130
130
|
|
|
131
131
|
data_model = UnverifiedConceptualDataModel.load(data_model_dict)
|
|
132
132
|
self.issue_list.trigger_warnings()
|
|
133
|
-
return ImportedDataModel(data_model
|
|
133
|
+
return ImportedDataModel(data_model)
|
|
134
134
|
|
|
135
135
|
def _to_data_model_components(self) -> dict:
|
|
136
136
|
raise NotImplementedError()
|
|
@@ -22,6 +22,7 @@ from cognite.neat.core._data_model.models import (
|
|
|
22
22
|
RoleTypes,
|
|
23
23
|
SchemaCompleteness,
|
|
24
24
|
)
|
|
25
|
+
from cognite.neat.core._data_model.models._import_contexts import SpreadsheetContext
|
|
25
26
|
from cognite.neat.core._issues import IssueList, MultiValueError
|
|
26
27
|
from cognite.neat.core._issues.errors import (
|
|
27
28
|
FileMissingRequiredFieldError,
|
|
@@ -271,7 +272,7 @@ class ExcelImporter(BaseImporter[T_UnverifiedDataModel]):
|
|
|
271
272
|
raise MultiValueError(issue_list.errors)
|
|
272
273
|
|
|
273
274
|
if user_read is None:
|
|
274
|
-
return ImportedDataModel(None,
|
|
275
|
+
return ImportedDataModel(None, None)
|
|
275
276
|
|
|
276
277
|
sheets = user_read.sheets
|
|
277
278
|
original_role = user_read.role
|
|
@@ -287,7 +288,7 @@ class ExcelImporter(BaseImporter[T_UnverifiedDataModel]):
|
|
|
287
288
|
except Exception as e:
|
|
288
289
|
issue_list.append(FileReadError(self.filepath, f"Failed to delete temporary file: {e}"))
|
|
289
290
|
|
|
290
|
-
return ImportedDataModel(data_model, read_info_by_sheet)
|
|
291
|
+
return ImportedDataModel(data_model, SpreadsheetContext(read_info_by_sheet))
|
|
291
292
|
|
|
292
293
|
@property
|
|
293
294
|
def description(self) -> str:
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from collections.abc import Hashable, ItemsView, Iterator, KeysView, Mapping, ValuesView
|
|
2
|
+
from typing import TypeVar
|
|
3
|
+
|
|
4
|
+
from rdflib import URIRef
|
|
5
|
+
|
|
6
|
+
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
7
|
+
|
|
8
|
+
T_Key = TypeVar("T_Key", bound=Hashable)
|
|
9
|
+
T_Value = TypeVar("T_Value")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ImportContext(dict, Mapping[T_Key, T_Value]):
|
|
13
|
+
def __init__(self, data: Mapping[T_Key, T_Value] | None = None) -> None:
|
|
14
|
+
super().__init__(data or {})
|
|
15
|
+
|
|
16
|
+
# The below methods are included to make better type hints in the IDE
|
|
17
|
+
def __getitem__(self, k: T_Key) -> T_Value:
|
|
18
|
+
return super().__getitem__(k)
|
|
19
|
+
|
|
20
|
+
def __setitem__(self, k: T_Key, v: T_Value) -> None:
|
|
21
|
+
super().__setitem__(k, v)
|
|
22
|
+
|
|
23
|
+
def __delitem__(self, k: T_Key) -> None:
|
|
24
|
+
super().__delitem__(k)
|
|
25
|
+
|
|
26
|
+
def __iter__(self) -> Iterator[T_Key]:
|
|
27
|
+
return super().__iter__()
|
|
28
|
+
|
|
29
|
+
def keys(self) -> KeysView[T_Key]: # type: ignore[override]
|
|
30
|
+
return super().keys()
|
|
31
|
+
|
|
32
|
+
def values(self) -> ValuesView[T_Value]: # type: ignore[override]
|
|
33
|
+
return super().values()
|
|
34
|
+
|
|
35
|
+
def items(self) -> ItemsView[T_Key, T_Value]: # type: ignore[override]
|
|
36
|
+
return super().items()
|
|
37
|
+
|
|
38
|
+
def get(self, __key: T_Key, __default: T_Value | None = None) -> T_Value: # type: ignore[override]
|
|
39
|
+
return super().get(__key, __default)
|
|
40
|
+
|
|
41
|
+
def pop(self, __key: T_Key, __default: T_Value | None = None) -> T_Value: # type: ignore[override]
|
|
42
|
+
return super().pop(__key, __default)
|
|
43
|
+
|
|
44
|
+
def popitem(self) -> tuple[T_Key, T_Value]:
|
|
45
|
+
return super().popitem()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class SpreadsheetContext(ImportContext[str, SpreadsheetRead]):
|
|
49
|
+
def __init__(self, data: dict[str, SpreadsheetRead] | None = None) -> None:
|
|
50
|
+
"""Initialize the SpreadsheetContext with a dictionary of SpreadsheetRead objects.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
data (dict[str, SpreadsheetRead]): A dictionary where keys are sheet names and values are
|
|
54
|
+
SpreadsheetRead objects containing the read data.
|
|
55
|
+
"""
|
|
56
|
+
super().__init__(data or {})
|
|
57
|
+
for k, v in self.items():
|
|
58
|
+
if not isinstance(k, str):
|
|
59
|
+
raise TypeError(f"Expected string key, got {type(k).__name__}")
|
|
60
|
+
if not isinstance(v, SpreadsheetRead):
|
|
61
|
+
raise TypeError(f"Expected SpreadsheetRead for key '{k}', got {type(v).__name__}")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class GraphContext(ImportContext[str, Mapping[URIRef, int]]):
|
|
65
|
+
def __init__(self, data: dict[str, Mapping[URIRef, int]] | None = None) -> None:
|
|
66
|
+
"""Initialize the GraphContext with a dictionary of mappings from URIRef to int.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
data (dict[str, Mapping[URIRef, int]]): A dictionary where keys are graph names and values are
|
|
70
|
+
mappings of URIRef to integer identifiers.
|
|
71
|
+
"""
|
|
72
|
+
super().__init__(data or {})
|
|
73
|
+
for k, v in self.items():
|
|
74
|
+
if not isinstance(k, str):
|
|
75
|
+
raise TypeError(f"Expected string key, got {type(k).__name__}")
|
|
76
|
+
if not isinstance(v, Mapping):
|
|
77
|
+
raise TypeError(f"Expected Mapping[URIRef, int] for key '{k}', got {type(v).__name__}")
|
|
78
|
+
for uri, value in v.items():
|
|
79
|
+
if not isinstance(uri, URIRef):
|
|
80
|
+
raise TypeError(f"Expected URIRef key in mapping for '{k}', got {type(uri).__name__}")
|
|
81
|
+
if not isinstance(value, int):
|
|
82
|
+
raise TypeError(f"Expected int value in mapping for '{k}', got {type(value).__name__}")
|
|
@@ -3,6 +3,7 @@ from collections import Counter, defaultdict
|
|
|
3
3
|
|
|
4
4
|
from cognite.neat.core._constants import get_base_concepts
|
|
5
5
|
from cognite.neat.core._data_model._constants import PATTERNS, EntityTypes
|
|
6
|
+
from cognite.neat.core._data_model.models._import_contexts import ImportContext, SpreadsheetContext
|
|
6
7
|
from cognite.neat.core._data_model.models.entities import ConceptEntity, UnknownEntity
|
|
7
8
|
from cognite.neat.core._data_model.models.entities._multi_value import MultiValueTypeInfo
|
|
8
9
|
from cognite.neat.core._issues import IssueList
|
|
@@ -21,7 +22,6 @@ from cognite.neat.core._issues.warnings._resources import (
|
|
|
21
22
|
ResourceNotDefinedWarning,
|
|
22
23
|
ResourceRegexViolationWarning,
|
|
23
24
|
)
|
|
24
|
-
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
25
25
|
from cognite.neat.core._utils.text import humanize_collection
|
|
26
26
|
|
|
27
27
|
from ._verified import ConceptualDataModel
|
|
@@ -34,14 +34,14 @@ class ConceptualValidation:
|
|
|
34
34
|
def __init__(
|
|
35
35
|
self,
|
|
36
36
|
data_model: ConceptualDataModel,
|
|
37
|
-
|
|
37
|
+
context: ImportContext | None = None,
|
|
38
38
|
):
|
|
39
39
|
# import here to avoid circular import issues
|
|
40
40
|
from cognite.neat.core._data_model.analysis._base import DataModelAnalysis
|
|
41
41
|
|
|
42
42
|
self.data_model = data_model
|
|
43
43
|
self.analysis = DataModelAnalysis(self.data_model)
|
|
44
|
-
self._read_info_by_spreadsheet =
|
|
44
|
+
self._read_info_by_spreadsheet = context if isinstance(context, SpreadsheetContext) else SpreadsheetContext({})
|
|
45
45
|
self._metadata = data_model.metadata
|
|
46
46
|
self._properties = data_model.properties
|
|
47
47
|
self._concepts = data_model.concepts
|
|
@@ -21,7 +21,9 @@ from cognite.neat.core._constants import (
|
|
|
21
21
|
COGNITE_SPACES,
|
|
22
22
|
DMS_CONTAINER_PROPERTY_SIZE_LIMIT,
|
|
23
23
|
DMS_VIEW_CONTAINER_SIZE_LIMIT,
|
|
24
|
+
get_base_concepts,
|
|
24
25
|
)
|
|
26
|
+
from cognite.neat.core._data_model.models._import_contexts import ImportContext, SpreadsheetContext
|
|
25
27
|
from cognite.neat.core._data_model.models.data_types import DataType
|
|
26
28
|
from cognite.neat.core._data_model.models.entities import ContainerEntity, RawFilter
|
|
27
29
|
from cognite.neat.core._data_model.models.entities._single_value import (
|
|
@@ -47,12 +49,12 @@ from cognite.neat.core._issues.warnings import (
|
|
|
47
49
|
UndefinedViewWarning,
|
|
48
50
|
user_modeling,
|
|
49
51
|
)
|
|
52
|
+
from cognite.neat.core._issues.warnings._models import ViewWithoutPropertiesWarning
|
|
50
53
|
from cognite.neat.core._issues.warnings.user_modeling import (
|
|
51
54
|
ContainerPropertyLimitWarning,
|
|
52
55
|
DirectRelationMissingSourceWarning,
|
|
53
56
|
NotNeatSupportedFilterWarning,
|
|
54
57
|
)
|
|
55
|
-
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
56
58
|
from cognite.neat.core._utils.text import humanize_collection
|
|
57
59
|
|
|
58
60
|
from ._verified import PhysicalDataModel, PhysicalProperty
|
|
@@ -81,15 +83,23 @@ class PhysicalValidation:
|
|
|
81
83
|
self,
|
|
82
84
|
data_model: PhysicalDataModel,
|
|
83
85
|
client: NeatClient | None = None,
|
|
84
|
-
|
|
86
|
+
context: ImportContext | None = None,
|
|
85
87
|
) -> None:
|
|
88
|
+
# import here to avoid circular import issues
|
|
89
|
+
from cognite.neat.core._data_model.analysis._base import DataModelAnalysis
|
|
90
|
+
|
|
86
91
|
self._data_model = data_model
|
|
87
92
|
self._client = client
|
|
88
93
|
self._metadata = data_model.metadata
|
|
89
94
|
self._properties = data_model.properties
|
|
90
95
|
self._containers = data_model.containers
|
|
91
96
|
self._views = data_model.views
|
|
92
|
-
self._read_info_by_spreadsheet =
|
|
97
|
+
self._read_info_by_spreadsheet = context if isinstance(context, SpreadsheetContext) else SpreadsheetContext()
|
|
98
|
+
|
|
99
|
+
self.analysis = DataModelAnalysis(physical=self._data_model)
|
|
100
|
+
self._cdf_concepts = {
|
|
101
|
+
ViewEntity.load(concept_as_string) for concept_as_string in get_base_concepts(base_model="CogniteCore")
|
|
102
|
+
}
|
|
93
103
|
|
|
94
104
|
def imported_views_and_containers_ids(
|
|
95
105
|
self, include_views_with_no_properties: bool = True
|
|
@@ -170,6 +180,9 @@ class PhysicalValidation:
|
|
|
170
180
|
# Validated for duplicated resource
|
|
171
181
|
issue_list.extend(self._duplicated_resources())
|
|
172
182
|
|
|
183
|
+
# Validate if views are defined (i.e. have at least one property defined, or inherited)
|
|
184
|
+
issue_list.extend(self._views_without_properties_exist())
|
|
185
|
+
|
|
173
186
|
# Neat DMS classes Validation
|
|
174
187
|
# These are errors that can only happen due to the format of the Neat DMS classes
|
|
175
188
|
issue_list.extend(self._validate_raw_filter())
|
|
@@ -192,6 +205,23 @@ class PhysicalValidation:
|
|
|
192
205
|
issue_list.extend(self._same_space_views_and_data_model())
|
|
193
206
|
return issue_list
|
|
194
207
|
|
|
208
|
+
def _views_without_properties_exist(self) -> IssueList:
|
|
209
|
+
"""Check if there are views that do not have any properties defined directly or inherited."""
|
|
210
|
+
issue_list = IssueList()
|
|
211
|
+
views = {view.view for view in self._views}
|
|
212
|
+
ancestors_by_view = self.analysis.implements_by_view(include_ancestors=True, include_different_space=True)
|
|
213
|
+
views_with_properties = self.analysis.defined_views().union(self._cdf_concepts)
|
|
214
|
+
|
|
215
|
+
if candidate_views := views.difference(views_with_properties):
|
|
216
|
+
for view in candidate_views:
|
|
217
|
+
# Here we check if at least one of the ancestors of the view has properties
|
|
218
|
+
if (ancestors := ancestors_by_view.get(view)) and ancestors.intersection(views_with_properties):
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
issue_list.append_if_not_exist(ViewWithoutPropertiesWarning(view_id=view.as_id()))
|
|
222
|
+
|
|
223
|
+
return issue_list
|
|
224
|
+
|
|
195
225
|
def _same_space_views_and_data_model(self) -> IssueList:
|
|
196
226
|
issue_list = IssueList()
|
|
197
227
|
|
|
@@ -31,6 +31,7 @@ from cognite.neat.core._constants import (
|
|
|
31
31
|
)
|
|
32
32
|
from cognite.neat.core._data_model._constants import PATTERNS, get_reserved_words
|
|
33
33
|
from cognite.neat.core._data_model._shared import (
|
|
34
|
+
ImportContext,
|
|
34
35
|
ImportedDataModel,
|
|
35
36
|
ImportedUnverifiedDataModel,
|
|
36
37
|
VerifiedDataModel,
|
|
@@ -93,7 +94,6 @@ from cognite.neat.core._issues.warnings._models import (
|
|
|
93
94
|
SolutionModelBuildOnTopOfCDMWarning,
|
|
94
95
|
)
|
|
95
96
|
from cognite.neat.core._utils.rdf_ import get_inheritance_path
|
|
96
|
-
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
97
97
|
from cognite.neat.core._utils.text import (
|
|
98
98
|
NamingStandardization,
|
|
99
99
|
humanize_collection,
|
|
@@ -2412,13 +2412,13 @@ class AddCogniteProperties(
|
|
|
2412
2412
|
concepts=new_classes,
|
|
2413
2413
|
prefixes=input_.prefixes,
|
|
2414
2414
|
),
|
|
2415
|
-
context=
|
|
2415
|
+
context=None,
|
|
2416
2416
|
)
|
|
2417
2417
|
|
|
2418
2418
|
@staticmethod
|
|
2419
2419
|
def _get_properties_by_concepts(
|
|
2420
2420
|
properties: list[UnverifiedConceptualProperty],
|
|
2421
|
-
read_context:
|
|
2421
|
+
read_context: ImportContext | None,
|
|
2422
2422
|
default_space: str,
|
|
2423
2423
|
) -> dict[ConceptEntity, dict[str, UnverifiedConceptualProperty]]:
|
|
2424
2424
|
issues = IssueList()
|
|
@@ -2438,7 +2438,7 @@ class AddCogniteProperties(
|
|
|
2438
2438
|
@staticmethod
|
|
2439
2439
|
def _get_dependencies_by_concepts(
|
|
2440
2440
|
concepts: list[UnverifiedConcept],
|
|
2441
|
-
read_context:
|
|
2441
|
+
read_context: ImportContext | None,
|
|
2442
2442
|
default_space: str,
|
|
2443
2443
|
) -> dict[ConceptEntity, set[ConceptEntity]]:
|
|
2444
2444
|
dependencies_by_concepts: dict[ConceptEntity, set[ConceptEntity]] = {}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from collections.abc import Iterator
|
|
3
3
|
from contextlib import contextmanager
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from pydantic import ValidationError
|
|
6
7
|
|
|
7
|
-
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
8
|
-
|
|
9
8
|
from ._base import IssueList, MultiValueError, NeatError
|
|
10
9
|
from ._factory import from_pydantic_errors, from_warning
|
|
11
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from cognite.neat.core._data_model.models._import_contexts import ImportContext
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
@contextmanager
|
|
14
16
|
def catch_warnings() -> Iterator[IssueList]:
|
|
@@ -26,12 +28,12 @@ def catch_warnings() -> Iterator[IssueList]:
|
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
@contextmanager
|
|
29
|
-
def catch_issues(
|
|
31
|
+
def catch_issues(context: "ImportContext | None" = None) -> Iterator[IssueList]:
|
|
30
32
|
"""This is an internal help function to handle issues and warnings.
|
|
31
33
|
|
|
32
34
|
Args:
|
|
33
|
-
|
|
34
|
-
the row numbers in the errors/warnings.
|
|
35
|
+
context (ImportContext): The read context. This is used to adjust
|
|
36
|
+
the row numbers in the errors/warnings if the data is read from a spreadsheet.
|
|
35
37
|
|
|
36
38
|
Returns:
|
|
37
39
|
IssueList: The list of issues.
|
|
@@ -41,7 +43,7 @@ def catch_issues(read_info_by_sheet: dict[str, SpreadsheetRead] | None = None) -
|
|
|
41
43
|
try:
|
|
42
44
|
yield issues
|
|
43
45
|
except ValidationError as e:
|
|
44
|
-
issues.extend(from_pydantic_errors(e.errors(),
|
|
46
|
+
issues.extend(from_pydantic_errors(e.errors(), context))
|
|
45
47
|
except NeatError as single:
|
|
46
48
|
issues.append(single)
|
|
47
49
|
except MultiValueError as multi:
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
from typing import cast
|
|
1
|
+
from typing import TYPE_CHECKING, cast
|
|
2
2
|
from warnings import WarningMessage
|
|
3
3
|
|
|
4
4
|
from pydantic_core import ErrorDetails
|
|
5
5
|
|
|
6
6
|
from cognite.neat.core._issues._base import NeatError, NeatWarning
|
|
7
|
-
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
8
7
|
|
|
9
8
|
from .errors import NeatValueError, SpreadsheetError
|
|
10
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from cognite.neat.core._data_model.models._import_contexts import ImportContext, SpreadsheetContext
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
def from_pydantic_errors(errors: list[ErrorDetails], context: "ImportContext | None" = None) -> list[NeatError]:
|
|
15
|
+
# To avoid circular import, we import SpreadsheetContext here.
|
|
16
|
+
from cognite.neat.core._data_model.models._import_contexts import SpreadsheetContext
|
|
17
|
+
|
|
18
|
+
read_info_by_sheet = context if isinstance(context, SpreadsheetContext) else SpreadsheetContext({})
|
|
16
19
|
return [
|
|
17
20
|
_from_pydantic_error(error, read_info_by_sheet)
|
|
18
21
|
for error in errors
|
|
@@ -29,7 +32,7 @@ def from_warning(warning: WarningMessage) -> NeatWarning | None:
|
|
|
29
32
|
return None
|
|
30
33
|
|
|
31
34
|
|
|
32
|
-
def _from_pydantic_error(error: ErrorDetails, read_info_by_sheet:
|
|
35
|
+
def _from_pydantic_error(error: ErrorDetails, read_info_by_sheet: "SpreadsheetContext") -> NeatError:
|
|
33
36
|
neat_error = _create_neat_value_error(error)
|
|
34
37
|
location = error["loc"]
|
|
35
38
|
|
|
@@ -92,6 +92,15 @@ class NotSupportedHasDataFilterLimitWarning(CDFNotSupportedWarning):
|
|
|
92
92
|
limit: int = DMS_VIEW_CONTAINER_SIZE_LIMIT
|
|
93
93
|
|
|
94
94
|
|
|
95
|
+
@dataclass(unsafe_hash=True)
|
|
96
|
+
class ViewWithoutPropertiesWarning(UserModelingWarning):
|
|
97
|
+
"""View {view_id} has neither explicit properties nor implements views that have properties."""
|
|
98
|
+
|
|
99
|
+
fix = "Define properties for view or inherit properties by implementing view(s) that has properties."
|
|
100
|
+
|
|
101
|
+
view_id: ViewId
|
|
102
|
+
|
|
103
|
+
|
|
95
104
|
@dataclass(unsafe_hash=True)
|
|
96
105
|
class UndefinedConceptWarning(UserModelingWarning):
|
|
97
106
|
"""Concept {concept_id} has no explicit properties neither implements concepts that have properties."""
|
|
@@ -347,7 +347,7 @@ class NeatInstanceStore:
|
|
|
347
347
|
)
|
|
348
348
|
return issue_list
|
|
349
349
|
_start = datetime.now(timezone.utc)
|
|
350
|
-
with catch_issues(
|
|
350
|
+
with catch_issues() as transform_issues:
|
|
351
351
|
transformer.transform(self.graph(named_graph))
|
|
352
352
|
issue_list.extend(transform_issues)
|
|
353
353
|
self.provenance.append(
|
|
@@ -11,7 +11,7 @@ from typing import Any
|
|
|
11
11
|
|
|
12
12
|
from cognite.client.exceptions import CogniteDuplicatedError, CogniteReadTimeout
|
|
13
13
|
|
|
14
|
-
from cognite.neat.core._issues.errors import NeatImportError
|
|
14
|
+
from cognite.neat.core._issues.errors._general import NeatImportError
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def local_import(module: str, extra: str) -> ModuleType:
|
cognite/neat/session/_base.py
CHANGED
|
@@ -33,6 +33,7 @@ from ._mapping import MappingAPI
|
|
|
33
33
|
from ._plugin import PluginAPI
|
|
34
34
|
from ._prepare import PrepareAPI
|
|
35
35
|
from ._read import ReadAPI
|
|
36
|
+
from ._session._data_model import DataModelAPI
|
|
36
37
|
from ._set import SetAPI
|
|
37
38
|
from ._show import ShowAPI
|
|
38
39
|
from ._state import SessionState
|
|
@@ -115,6 +116,9 @@ class NeatSession:
|
|
|
115
116
|
if load_engine != "skip" and (engine_version := load_neat_engine(client, load_engine)):
|
|
116
117
|
print(f"Neat Engine {engine_version} loaded.")
|
|
117
118
|
|
|
119
|
+
# new API for data model operations
|
|
120
|
+
self.data_model = DataModelAPI(self._state)
|
|
121
|
+
|
|
118
122
|
def _select_most_performant_store(self) -> Literal["memory", "oxigraph"]:
|
|
119
123
|
"""Select the most performant store based on the current environment."""
|
|
120
124
|
|
|
File without changes
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
from zipfile import Path
|
|
3
|
+
|
|
4
|
+
from cognite.neat.core._data_model import importers
|
|
5
|
+
from cognite.neat.core._data_model.importers._base import BaseImporter
|
|
6
|
+
from cognite.neat.core._issues._base import IssueList
|
|
7
|
+
from cognite.neat.core._issues.errors._general import NeatValueError
|
|
8
|
+
from cognite.neat.core._issues.warnings._general import MissingCogniteClientWarning
|
|
9
|
+
from cognite.neat.core._utils.reader._base import NeatReader
|
|
10
|
+
from cognite.neat.plugins._manager import get_plugin_manager
|
|
11
|
+
from cognite.neat.plugins.data_model.importers._base import DataModelImporterPlugin
|
|
12
|
+
from cognite.neat.session._state import SessionState
|
|
13
|
+
from cognite.neat.session.exceptions import NeatSessionError, session_class_wrapper
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@session_class_wrapper
|
|
17
|
+
class DataModelAPI:
|
|
18
|
+
"""API for managing data models in NEAT session."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, state: SessionState) -> None:
|
|
21
|
+
self._state = state
|
|
22
|
+
self.read = ReadAPI(state)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@session_class_wrapper
|
|
26
|
+
class ReadAPI:
|
|
27
|
+
def __init__(self, state: SessionState) -> None:
|
|
28
|
+
self._state = state
|
|
29
|
+
|
|
30
|
+
def __call__(self, name: str, io: str | Path, **kwargs: Any) -> IssueList:
|
|
31
|
+
"""Provides access to the external plugins for data model importing.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
name (str): The name of format (e.g. Excel) plugin is handling.
|
|
35
|
+
io (str | Path | None): The input/output interface for the plugin.
|
|
36
|
+
**kwargs (Any): Additional keyword arguments for the plugin.
|
|
37
|
+
|
|
38
|
+
!!! note "kwargs"
|
|
39
|
+
Users must consult the documentation of the plugin to understand
|
|
40
|
+
what keyword arguments are supported.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
# These are internal readers that are not plugins
|
|
44
|
+
if name.strip().lower() == "excel":
|
|
45
|
+
return self.excel(io, **kwargs)
|
|
46
|
+
elif name.strip().lower() == "ontology":
|
|
47
|
+
return self.ontology(io)
|
|
48
|
+
elif name.strip().lower() == "yaml":
|
|
49
|
+
return self.yaml(io, **kwargs)
|
|
50
|
+
else:
|
|
51
|
+
return self._plugin(name, io, **kwargs)
|
|
52
|
+
|
|
53
|
+
def _plugin(self, name: str, io: str | Path, **kwargs: Any) -> IssueList:
|
|
54
|
+
"""Provides access to the external plugins for data model importing.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
name (str): The name of format (e.g. Excel) plugin is handling.
|
|
58
|
+
io (str | Path | None): The input/output interface for the plugin.
|
|
59
|
+
**kwargs (Any): Additional keyword arguments for the plugin.
|
|
60
|
+
|
|
61
|
+
!!! note "kwargs"
|
|
62
|
+
Users must consult the documentation of the plugin to understand
|
|
63
|
+
what keyword arguments are supported.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
# Some plugins may not support the io argument
|
|
67
|
+
reader = NeatReader.create(io)
|
|
68
|
+
path = reader.materialize_path()
|
|
69
|
+
|
|
70
|
+
self._state._raise_exception_if_condition_not_met(
|
|
71
|
+
"Data Model Read",
|
|
72
|
+
empty_data_model_store_required=True,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
plugin_manager = get_plugin_manager()
|
|
76
|
+
plugin = plugin_manager.get(name, DataModelImporterPlugin)
|
|
77
|
+
|
|
78
|
+
print(
|
|
79
|
+
f"You are using an external plugin {plugin.__name__}, which is not developed by the NEAT team."
|
|
80
|
+
"\nUse it at your own risk."
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return self._state.data_model_import(plugin().configure(io=path, **kwargs))
|
|
84
|
+
|
|
85
|
+
def excel(self, io: str | Path, *, enable_manual_edit: bool = False) -> IssueList:
|
|
86
|
+
"""Reads a Neat Excel Data Model to the data model store.
|
|
87
|
+
The data model spreadsheets may contain conceptual or physical data model definitions.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
io: file path to the Excel sheet
|
|
91
|
+
enable_manual_edit: If True, the user will be able to re-import data model
|
|
92
|
+
which where edit outside of NeatSession
|
|
93
|
+
"""
|
|
94
|
+
reader = NeatReader.create(io)
|
|
95
|
+
path = reader.materialize_path()
|
|
96
|
+
|
|
97
|
+
self._state._raise_exception_if_condition_not_met(
|
|
98
|
+
"Read Excel Data Model",
|
|
99
|
+
empty_data_model_store_required=not enable_manual_edit,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return self._state.data_model_import(importers.ExcelImporter(path), enable_manual_edit)
|
|
103
|
+
|
|
104
|
+
def ontology(self, io: str | Path) -> IssueList:
|
|
105
|
+
"""Reads an OWL ontology source into NeatSession.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
io: file path or url to the OWL file
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
self._state._raise_exception_if_condition_not_met(
|
|
112
|
+
"Read Ontology",
|
|
113
|
+
empty_data_model_store_required=True,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
reader = NeatReader.create(io)
|
|
117
|
+
importer = importers.OWLImporter.from_file(reader.materialize_path(), source_name=f"file {reader!s}")
|
|
118
|
+
return self._state.data_model_import(importer)
|
|
119
|
+
|
|
120
|
+
def yaml(self, io: str | Path, *, format: Literal["neat", "toolkit"] = "neat") -> IssueList:
|
|
121
|
+
"""Reads a yaml with either neat data mode, or several toolkit yaml files to
|
|
122
|
+
import Data Model(s) into NeatSession.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
io: File path to the Yaml file in the case of "neat" yaml, or path to a zip folder or directory with several
|
|
126
|
+
Yaml files in the case of "toolkit".
|
|
127
|
+
format: The format of the yaml file(s). Can be either "neat" or "toolkit".
|
|
128
|
+
|
|
129
|
+
Example:
|
|
130
|
+
```python
|
|
131
|
+
neat.read.yaml("path_to_toolkit_yamls")
|
|
132
|
+
```
|
|
133
|
+
"""
|
|
134
|
+
self._state._raise_exception_if_condition_not_met(
|
|
135
|
+
"Read YAML data model",
|
|
136
|
+
empty_data_model_store_required=True,
|
|
137
|
+
)
|
|
138
|
+
reader = NeatReader.create(io)
|
|
139
|
+
path = reader.materialize_path()
|
|
140
|
+
importer: BaseImporter
|
|
141
|
+
if format == "neat":
|
|
142
|
+
importer = importers.DictImporter.from_yaml_file(path, source_name=f"{reader!s}")
|
|
143
|
+
elif format == "toolkit":
|
|
144
|
+
dms_importer = importers.DMSImporter.from_path(path, self._state.client)
|
|
145
|
+
if dms_importer.issue_list.has_warning_type(MissingCogniteClientWarning):
|
|
146
|
+
raise NeatSessionError(
|
|
147
|
+
"No client provided. You are referencing Cognite containers in your data model, "
|
|
148
|
+
"NEAT needs a client to lookup the container definitions. "
|
|
149
|
+
"Please set the client in the session, NeatSession(client=client)."
|
|
150
|
+
)
|
|
151
|
+
importer = dms_importer
|
|
152
|
+
else:
|
|
153
|
+
raise NeatValueError(f"Unsupported YAML format: {format}")
|
|
154
|
+
return self._state.data_model_import(importer)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cognite-neat
|
|
3
|
-
Version: 0.123.
|
|
3
|
+
Version: 0.123.20
|
|
4
4
|
Summary: Knowledge graph transformation
|
|
5
5
|
Project-URL: Documentation, https://cognite-neat.readthedocs-hosted.com/
|
|
6
6
|
Project-URL: Homepage, https://cognite-neat.readthedocs-hosted.com/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
cognite/neat/__init__.py,sha256=12StS1dzH9_MElqxGvLWrNsxCJl9Hv8A2a9D0E5OD_U,193
|
|
2
|
-
cognite/neat/_version.py,sha256=
|
|
2
|
+
cognite/neat/_version.py,sha256=tUfZIhsXsTuZtKqqfKwmQe_3linzeB0aoFlEj2fZHAQ,47
|
|
3
3
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
cognite/neat/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
cognite/neat/core/_config.py,sha256=WT1BS8uADcFvGoUYOOfwFOVq_VBl472TisdoA3wLick,280
|
|
@@ -20,7 +20,7 @@ cognite/neat/core/_client/data_classes/schema.py,sha256=SpkBGbC2SUJG38Ixf1vYJINI
|
|
|
20
20
|
cognite/neat/core/_client/data_classes/statistics.py,sha256=GU-u41cOTig0Y5pYhW5KqzCsuAUIX9tOmdizMEveYuw,4487
|
|
21
21
|
cognite/neat/core/_data_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
cognite/neat/core/_data_model/_constants.py,sha256=ssiOprhd4bamglQnLTNjmqYn9mCBW-VOUbn08qDBbsM,5857
|
|
23
|
-
cognite/neat/core/_data_model/_shared.py,sha256=
|
|
23
|
+
cognite/neat/core/_data_model/_shared.py,sha256=at3-TT6pkdwtsjuz94P1lj1W7dO6_Sb3nQ3JSDBNLCY,2088
|
|
24
24
|
cognite/neat/core/_data_model/analysis/__init__.py,sha256=v3hSfz7AEEqcmdjL71I09tP8Hl-gPZYOiDYMp_CW4vg,70
|
|
25
25
|
cognite/neat/core/_data_model/analysis/_base.py,sha256=VT1orVf0xSSZrKnJoc-cJR1F1mtMn9Ybjk7UDO71aFA,24448
|
|
26
26
|
cognite/neat/core/_data_model/catalog/__init__.py,sha256=zWG1-GONe8m05lV3gLAK_Xp7EJvcy6qLLl2B-RHHBjw,260
|
|
@@ -34,25 +34,27 @@ cognite/neat/core/_data_model/exporters/_data_model2excel.py,sha256=88ReyrsRqoIR
|
|
|
34
34
|
cognite/neat/core/_data_model/exporters/_data_model2instance_template.py,sha256=9k8A70b1paeOHjvJRtbl6Xror1GD8AIMdo3cCx5aejE,6103
|
|
35
35
|
cognite/neat/core/_data_model/exporters/_data_model2ontology.py,sha256=sZRxvbnv2reav3xUUZl6NIX-KqngoKr4qLmzTUvkhYk,22615
|
|
36
36
|
cognite/neat/core/_data_model/exporters/_data_model2yaml.py,sha256=1dlb-v4sV8BArnX_6J4wpjQT7r-FinFAvoPDoMNkHYw,3284
|
|
37
|
-
cognite/neat/core/_data_model/importers/__init__.py,sha256=
|
|
37
|
+
cognite/neat/core/_data_model/importers/__init__.py,sha256=jkDKSGv5VdJgl44lmn7VQtD6-rqo09VFOr-tTB5Lfyc,1290
|
|
38
38
|
cognite/neat/core/_data_model/importers/_base.py,sha256=pKe2OK86Wdj6CTj5bUgjY33ejZhRfD2eJbjcCapHD58,2013
|
|
39
39
|
cognite/neat/core/_data_model/importers/_base_file_reader.py,sha256=m7CwMujEybYMfHWbTQOb7wBvLl2X1TmROkPelJMSaDA,1621
|
|
40
|
-
cognite/neat/core/_data_model/importers/_dict2data_model.py,sha256
|
|
41
|
-
cognite/neat/core/_data_model/importers/_dms2data_model.py,sha256=
|
|
42
|
-
cognite/neat/core/_data_model/importers/
|
|
40
|
+
cognite/neat/core/_data_model/importers/_dict2data_model.py,sha256=GEAD0Gs69rH-i-TjHV3Px-7Wo1Z7PfUqESsZt_58xUU,4705
|
|
41
|
+
cognite/neat/core/_data_model/importers/_dms2data_model.py,sha256=X2iQ2VQvrruj1lEFVYN3Hl7J1R7NK3WT6FyXyl-ruyE,29134
|
|
42
|
+
cognite/neat/core/_data_model/importers/_graph2data_model.py,sha256=yWi6Vlrc8rrcFM8hxHOVesr9D3etwJ0rbL6TJULrW9U,13684
|
|
43
|
+
cognite/neat/core/_data_model/importers/_spreadsheet2data_model.py,sha256=wPb1ie_nmWNuHO0X6NW53pvqUDYGvNkHLvT8_UKFJIw,12079
|
|
43
44
|
cognite/neat/core/_data_model/importers/_rdf/__init__.py,sha256=1yOjV2PKCxwH7uCTXVZhSdxtn5etmFX40cksvwtKcZ8,199
|
|
44
|
-
cognite/neat/core/_data_model/importers/_rdf/_base.py,sha256=
|
|
45
|
+
cognite/neat/core/_data_model/importers/_rdf/_base.py,sha256=XTdKqN4nf0d2Vvk56LShrDoyCQCg9MXvKwxXT0uMnGg,6016
|
|
45
46
|
cognite/neat/core/_data_model/importers/_rdf/_inference2rdata_model.py,sha256=PCgM9-qGSLlupN7tYCFLHjivgICtMiahNry1ub8JCYk,28934
|
|
46
47
|
cognite/neat/core/_data_model/importers/_rdf/_owl2data_model.py,sha256=l_89N1LewZVjSttcJkFAJj63JW8wI-THKJYjAxcNiDg,3093
|
|
47
48
|
cognite/neat/core/_data_model/importers/_rdf/_shared.py,sha256=qibq94dFoy_g1ED5nIFYwHC_LYI4jI67HFVcMy7abrM,6665
|
|
48
49
|
cognite/neat/core/_data_model/models/__init__.py,sha256=hmF7MDR1XmpLxYdMkOEuPuHUqOQKE4AgsuUqdc-ySSQ,1249
|
|
49
50
|
cognite/neat/core/_data_model/models/_base_unverified.py,sha256=1Wfbp-tJaEF6hd1bFdp2FhTgPkInf-1ZokuEoVJRPxQ,6842
|
|
50
51
|
cognite/neat/core/_data_model/models/_base_verified.py,sha256=nzPrlj7ZvYull_Fdh2zeDXz98hux-eQOdTGy9jhUtYA,15127
|
|
52
|
+
cognite/neat/core/_data_model/models/_import_contexts.py,sha256=LAQbgwTbyIAY3at2hk6OksfK_CKavBwgwPcRFcszJcc,3436
|
|
51
53
|
cognite/neat/core/_data_model/models/_types.py,sha256=70E8fiLdZkVF2sDUGPuDhzXNA5niVECkVDI7YN0NF60,5488
|
|
52
54
|
cognite/neat/core/_data_model/models/data_types.py,sha256=uQ_u9KxCetLjxo-VtFzOXSxQuuf97Kg-9lfTTGzY6hc,10150
|
|
53
55
|
cognite/neat/core/_data_model/models/conceptual/__init__.py,sha256=9A6myEV8s0-LqdXejaljqPj8S0pIpUL75rNdRDZzyR8,585
|
|
54
56
|
cognite/neat/core/_data_model/models/conceptual/_unverified.py,sha256=VswgnTSjSCRzBX3z5HvintBGaWBPexxIs-7z7S4J57c,6298
|
|
55
|
-
cognite/neat/core/_data_model/models/conceptual/_validation.py,sha256=
|
|
57
|
+
cognite/neat/core/_data_model/models/conceptual/_validation.py,sha256=CF1jYALTCQFAr5KUwplAzOLdxJGknIeJo-HpxVZsgMY,13859
|
|
56
58
|
cognite/neat/core/_data_model/models/conceptual/_verified.py,sha256=BUB4Ur4kpBoWiwTf57tjxJ2l0tDTSbY7zGrg1g0yVNQ,13716
|
|
57
59
|
cognite/neat/core/_data_model/models/entities/__init__.py,sha256=UsW-_6fwd-TW0WcnShPKf40h75l1elVn80VurUwRAic,1567
|
|
58
60
|
cognite/neat/core/_data_model/models/entities/_constants.py,sha256=GXRzVfArwxF3C67VCkzy0JWTZRkRJUYXBQaaecrqcWc,351
|
|
@@ -67,11 +69,11 @@ cognite/neat/core/_data_model/models/mapping/_classic2core.yaml,sha256=ei-nuivNW
|
|
|
67
69
|
cognite/neat/core/_data_model/models/physical/__init__.py,sha256=ONE_xLw1cxfw88rICG_RtbjCYUZm8yS2kBQ4Di3EGnA,987
|
|
68
70
|
cognite/neat/core/_data_model/models/physical/_exporter.py,sha256=DPOytV-sIzpGJtfDEfi7G4RWnSCVNRLWe1KzY26ewmc,30083
|
|
69
71
|
cognite/neat/core/_data_model/models/physical/_unverified.py,sha256=VyI-JULAu6kHJygUclDPH1JYjhf_XcO58tI9BkXORC0,18430
|
|
70
|
-
cognite/neat/core/_data_model/models/physical/_validation.py,sha256=
|
|
72
|
+
cognite/neat/core/_data_model/models/physical/_validation.py,sha256=AuBAecOTAVRbGh9VXZ6W91HsU7-B75ko7oaxlX4Mmqw,41140
|
|
71
73
|
cognite/neat/core/_data_model/models/physical/_verified.py,sha256=4_7XUj6-x74DhL8qe-duXhlNnq6ANmShB7UpICjbQW4,26783
|
|
72
74
|
cognite/neat/core/_data_model/transformers/__init__.py,sha256=N6yRBplAkrwwxoTAre_1BE_fdSZL5jihr7xTQjW3KnM,1876
|
|
73
75
|
cognite/neat/core/_data_model/transformers/_base.py,sha256=7adUBJgDkXgRq_h7l1q2VsLQo3lE7-xmzmHdcF4QHq8,3133
|
|
74
|
-
cognite/neat/core/_data_model/transformers/_converters.py,sha256=
|
|
76
|
+
cognite/neat/core/_data_model/transformers/_converters.py,sha256=Nyq2Iy2BYV0QMwpqLtdwHqpftl9sF1KvX5YVkIMPguc,111519
|
|
75
77
|
cognite/neat/core/_data_model/transformers/_mapping.py,sha256=GwmTRnhiUPIG37CgUSIbjT7ZpWOwdWuBZ_HAIIBiKYY,19024
|
|
76
78
|
cognite/neat/core/_data_model/transformers/_union_conceptual.py,sha256=sg-VGjrK7PwZS1U18ov-8Or00uR3pFLOaPOYT1edD8Q,8852
|
|
77
79
|
cognite/neat/core/_data_model/transformers/_verification.py,sha256=yyPK6irhMGjVtwKxRIElSsPLUvLLVfk1lBAGny6jN5w,5193
|
|
@@ -120,8 +122,8 @@ cognite/neat/core/_instances/transformers/_rdfpath.py,sha256=4PIVpjlng59oTjoToS6
|
|
|
120
122
|
cognite/neat/core/_instances/transformers/_value_type.py,sha256=-d18yefiGrx8CaVNLgJe0dF0zsMxtCQxlD2q2ZFGJ8U,15820
|
|
121
123
|
cognite/neat/core/_issues/__init__.py,sha256=NQ-PN3fqp-hBPlpG2AZEND4cDn3_3UXAPfhLNtF5mtc,457
|
|
122
124
|
cognite/neat/core/_issues/_base.py,sha256=LZhTF_QOQvCxFrGUnWmF9gQnuyr7nM3MqXf_r8KG7GY,12003
|
|
123
|
-
cognite/neat/core/_issues/_contextmanagers.py,sha256=
|
|
124
|
-
cognite/neat/core/_issues/_factory.py,sha256=
|
|
125
|
+
cognite/neat/core/_issues/_contextmanagers.py,sha256=EiLW9h60ZJ80GAsbEGvwf9LoID1ZPAUh-7KNn6i9cGk,1621
|
|
126
|
+
cognite/neat/core/_issues/_factory.py,sha256=mcBaIF1H5SPkw9X80VsTgL1SHlZN6P2kXE75k3Y1WN8,3079
|
|
125
127
|
cognite/neat/core/_issues/formatters.py,sha256=k2h_6wHW0ve52gXeuRoEcGwrxqqSe5sYFa_HycPiqW8,3323
|
|
126
128
|
cognite/neat/core/_issues/errors/__init__.py,sha256=YkJeNnB1FDhYYTUbsb6iIm2rzI7usDYdjQDb4qrfFR4,2492
|
|
127
129
|
cognite/neat/core/_issues/errors/_external.py,sha256=AaKwO5-AvX01d7Hd83vqYl1qNmMtgsmShmvyH8ioZAM,2354
|
|
@@ -132,18 +134,18 @@ cognite/neat/core/_issues/errors/_wrapper.py,sha256=clhuSwUuHy-FQXQopFIQRY8c_NZM
|
|
|
132
134
|
cognite/neat/core/_issues/warnings/__init__.py,sha256=3MQS_elyRD3SG3iEWMWLRJDabth7upT3oX4WD0xxOh4,3263
|
|
133
135
|
cognite/neat/core/_issues/warnings/_external.py,sha256=w-1R7ea6DXTIWqwlwMMjY0YxKDMSJ8gKAbp_nIIM1AI,1324
|
|
134
136
|
cognite/neat/core/_issues/warnings/_general.py,sha256=_6dAFaMz-LIv7GsBBIBq2d-kmbuxVXKvU4jZeb7tjAo,972
|
|
135
|
-
cognite/neat/core/_issues/warnings/_models.py,sha256=
|
|
137
|
+
cognite/neat/core/_issues/warnings/_models.py,sha256=3AGdCteVRq7iK4TcGUYy7RxLIKGgc32NyigG8G489jA,5795
|
|
136
138
|
cognite/neat/core/_issues/warnings/_properties.py,sha256=I3vqc1aL-ce_FRQNgQQy34RW7kQxcjbwhZIIVtGVmg8,3807
|
|
137
139
|
cognite/neat/core/_issues/warnings/_resources.py,sha256=_iPRq0pRMmRu3LFjqZTaG3OqOzw4f8-Vc9G4Im__FHc,3578
|
|
138
140
|
cognite/neat/core/_issues/warnings/user_modeling.py,sha256=Qn_S8TLw7MMYQaJcZBScJA48kz_PrTWz0NaepSR70Fk,4144
|
|
139
141
|
cognite/neat/core/_store/__init__.py,sha256=wpsF8xjIQ5V21NOh45XQV813n_EzgyPOt0VVinYjnDI,140
|
|
140
142
|
cognite/neat/core/_store/_data_model.py,sha256=6Eg_QH1ZlS4AO3c0_Ye8M-Y4_Ycf3mQPJBKyardGu9w,19646
|
|
141
|
-
cognite/neat/core/_store/_instance.py,sha256=
|
|
143
|
+
cognite/neat/core/_store/_instance.py,sha256=FzNtu_G9_VavrZLIhUZUqBGUs5Mknbbfi1hC0qFs5yQ,17404
|
|
142
144
|
cognite/neat/core/_store/_provenance.py,sha256=aMEsq27dZ4NZ6XEC8hA0fIDF13i1ZP3QwnclLCRaNk4,7326
|
|
143
145
|
cognite/neat/core/_store/exceptions.py,sha256=jcd1Gv65mfTdC4cipFAMWUNghEmdLS_lwPH1FB_ebxI,1656
|
|
144
146
|
cognite/neat/core/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
145
147
|
cognite/neat/core/_utils/auth.py,sha256=tP_diUZdtacUkM8TLlbSOyHlNcq9VGh-4o_7myWRU_o,14763
|
|
146
|
-
cognite/neat/core/_utils/auxiliary.py,sha256=
|
|
148
|
+
cognite/neat/core/_utils/auxiliary.py,sha256=nQAvIysrtigDTefuxTRGFiNUUBYy-iSDJPhvw-6RB50,6859
|
|
147
149
|
cognite/neat/core/_utils/collection_.py,sha256=zVrSmm4045pjw6Pt6y4VPTIJ4dXdMJPyOV70LdFyDBM,2376
|
|
148
150
|
cognite/neat/core/_utils/graph_transformations_report.py,sha256=ORVH7lw357TPOq4elU5lH46Qx6GCLVrSj-1nX6Ggk1U,1235
|
|
149
151
|
cognite/neat/core/_utils/io_.py,sha256=D2Mg8sOxfBoDg3fC0jBzaxO3vkXmr0QvZSgYIv6xRkM,386
|
|
@@ -163,7 +165,7 @@ cognite/neat/plugins/data_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
|
|
|
163
165
|
cognite/neat/plugins/data_model/importers/__init__.py,sha256=d4UJNCFR1DXPY7lv5LdCW2hiStEhvXiu2g_bRSIp1y0,89
|
|
164
166
|
cognite/neat/plugins/data_model/importers/_base.py,sha256=M9zXp7tEu1SfJZRAJAtLmqpssdFcoi2X-5e25q_n_h8,1034
|
|
165
167
|
cognite/neat/session/__init__.py,sha256=fxQ5URVlUnmEGYyB8Baw7IDq-uYacqkigbc4b-Pr9Fw,58
|
|
166
|
-
cognite/neat/session/_base.py,sha256=
|
|
168
|
+
cognite/neat/session/_base.py,sha256=yxAItY6663wcmlrwxmzWkJorrrrm9oahpYOP-5RGwvQ,13081
|
|
167
169
|
cognite/neat/session/_collector.py,sha256=-icWXOT9YBjAOVZfpPtBx-D39kpRP2RaQKdPtcr7Xm8,4233
|
|
168
170
|
cognite/neat/session/_drop.py,sha256=ipD8RS_ZebPNpeIkhC7yqSSeo7e57TXMRxrh5_6IRik,4239
|
|
169
171
|
cognite/neat/session/_experimental.py,sha256=0peZPZ9JpmzQE05wHbng2tWmPPLLTAVfWZEEUhdnI6o,1274
|
|
@@ -182,12 +184,14 @@ cognite/neat/session/_template.py,sha256=NCgrrwLT98DpLYoo3Wybr_OUXrEXpsJZjrJ83Kq
|
|
|
182
184
|
cognite/neat/session/_to.py,sha256=_R-UB3iEIQoa12kTD7tuSrRDdbySQXQg_mzbn5t-7bg,19399
|
|
183
185
|
cognite/neat/session/_wizard.py,sha256=hARNNzD5Zfkk_V147rIjOLVvrFaqzXGXWhZuH1NJG3M,1486
|
|
184
186
|
cognite/neat/session/exceptions.py,sha256=z5jxwfVTXDCCFZKTTYVIaksNKqb9CMa2tyIZgyNL3Us,3475
|
|
187
|
+
cognite/neat/session/_session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
188
|
+
cognite/neat/session/_session/_data_model.py,sha256=id2chqUIA8tkxc9tTT7RiGWs-GzHC4LnzNkq-mfBIW4,6347
|
|
185
189
|
cognite/neat/session/_state/README.md,sha256=o6N7EL98lgyWffw8IoEUf2KG5uSKveD5__TW45YzVjA,902
|
|
186
190
|
cognite/neat/session/engine/__init__.py,sha256=D3MxUorEs6-NtgoICqtZ8PISQrjrr4dvca6n48bu_bI,120
|
|
187
191
|
cognite/neat/session/engine/_import.py,sha256=1QxA2_EK613lXYAHKQbZyw2yjo5P9XuiX4Z6_6-WMNQ,169
|
|
188
192
|
cognite/neat/session/engine/_interface.py,sha256=3W-cYr493c_mW3P5O6MKN1xEQg3cA7NHR_ev3zdF9Vk,533
|
|
189
193
|
cognite/neat/session/engine/_load.py,sha256=g52uYakQM03VqHt_RDHtpHso1-mFFifH5M4T2ScuH8A,5198
|
|
190
|
-
cognite_neat-0.123.
|
|
191
|
-
cognite_neat-0.123.
|
|
192
|
-
cognite_neat-0.123.
|
|
193
|
-
cognite_neat-0.123.
|
|
194
|
+
cognite_neat-0.123.20.dist-info/METADATA,sha256=O8qdN1hncWgpZrnj6h4aeeoZlbtTG2Loe7qTGpHUuzA,9172
|
|
195
|
+
cognite_neat-0.123.20.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
196
|
+
cognite_neat-0.123.20.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
|
|
197
|
+
cognite_neat-0.123.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|