cognite-neat 0.89.0__py3-none-any.whl → 0.90.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- cognite/neat/_version.py +1 -1
- cognite/neat/constants.py +3 -3
- cognite/neat/graph/extractors/__init__.py +2 -0
- cognite/neat/graph/extractors/_classic_cdf/_base.py +2 -2
- cognite/neat/graph/extractors/_dms.py +158 -0
- cognite/neat/graph/extractors/_mock_graph_generator.py +49 -9
- cognite/neat/graph/loaders/_rdf2dms.py +16 -13
- cognite/neat/graph/models.py +1 -0
- cognite/neat/graph/queries/_base.py +4 -2
- cognite/neat/issues/_base.py +1 -0
- cognite/neat/issues/warnings/__init__.py +2 -0
- cognite/neat/issues/warnings/_properties.py +12 -0
- cognite/neat/rules/importers/_dms2rules.py +1 -1
- cognite/neat/rules/importers/_rdf/_inference2rules.py +27 -32
- cognite/neat/rules/models/dms/_exporter.py +16 -19
- cognite/neat/rules/transformers/_converters.py +11 -2
- cognite/neat/store/_base.py +2 -2
- cognite/neat/workflows/steps/lib/current/graph_extractor.py +5 -9
- cognite/neat/workflows/steps/lib/current/graph_loader.py +2 -2
- {cognite_neat-0.89.0.dist-info → cognite_neat-0.90.1.dist-info}/METADATA +1 -1
- {cognite_neat-0.89.0.dist-info → cognite_neat-0.90.1.dist-info}/RECORD +24 -23
- {cognite_neat-0.89.0.dist-info → cognite_neat-0.90.1.dist-info}/LICENSE +0 -0
- {cognite_neat-0.89.0.dist-info → cognite_neat-0.90.1.dist-info}/WHEEL +0 -0
- {cognite_neat-0.89.0.dist-info → cognite_neat-0.90.1.dist-info}/entry_points.txt +0 -0
cognite/neat/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.90.1"
|
cognite/neat/constants.py
CHANGED
|
@@ -7,11 +7,11 @@ from cognite import neat
|
|
|
7
7
|
PACKAGE_DIRECTORY = Path(neat.__file__).parent
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
EXAMPLE_RULES = PACKAGE_DIRECTORY / "
|
|
11
|
-
EXAMPLE_GRAPHS = PACKAGE_DIRECTORY / "
|
|
12
|
-
_OLD_WORKFLOWS = PACKAGE_DIRECTORY / "legacy" / "workflows" / "examples"
|
|
10
|
+
EXAMPLE_RULES = PACKAGE_DIRECTORY / "rules" / "examples"
|
|
11
|
+
EXAMPLE_GRAPHS = PACKAGE_DIRECTORY / "graph" / "examples"
|
|
13
12
|
EXAMPLE_WORKFLOWS = PACKAGE_DIRECTORY / "workflows" / "examples"
|
|
14
13
|
|
|
14
|
+
DEFAULT_SPACE_URI = "http://purl.org/cognite/{space}#"
|
|
15
15
|
DEFAULT_NAMESPACE = Namespace("http://purl.org/cognite/neat#")
|
|
16
16
|
|
|
17
17
|
|
|
@@ -7,6 +7,7 @@ from ._classic_cdf._relationships import RelationshipsExtractor
|
|
|
7
7
|
from ._classic_cdf._sequences import SequencesExtractor
|
|
8
8
|
from ._classic_cdf._timeseries import TimeSeriesExtractor
|
|
9
9
|
from ._dexpi import DexpiExtractor
|
|
10
|
+
from ._dms import DMSExtractor
|
|
10
11
|
from ._mock_graph_generator import MockGraphGenerator
|
|
11
12
|
from ._rdf_file import RdfFileExtractor
|
|
12
13
|
|
|
@@ -22,6 +23,7 @@ __all__ = [
|
|
|
22
23
|
"LabelsExtractor",
|
|
23
24
|
"RdfFileExtractor",
|
|
24
25
|
"DexpiExtractor",
|
|
26
|
+
"DMSExtractor",
|
|
25
27
|
]
|
|
26
28
|
|
|
27
29
|
|
|
@@ -5,7 +5,7 @@ from collections.abc import Callable, Iterable, Set
|
|
|
5
5
|
from typing import Generic, TypeVar
|
|
6
6
|
|
|
7
7
|
from cognite.client.data_classes._base import CogniteResource
|
|
8
|
-
from rdflib import Literal, Namespace, URIRef
|
|
8
|
+
from rdflib import XSD, Literal, Namespace, URIRef
|
|
9
9
|
|
|
10
10
|
from cognite.neat.constants import DEFAULT_NAMESPACE
|
|
11
11
|
from cognite.neat.graph.extractors._base import BaseExtractor
|
|
@@ -93,7 +93,7 @@ class ClassicCDFExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
|
|
|
93
93
|
Literal(string_to_ideal_type(value)),
|
|
94
94
|
)
|
|
95
95
|
else:
|
|
96
|
-
yield id_, self.namespace.metadata, Literal(json.dumps(metadata))
|
|
96
|
+
yield id_, self.namespace.metadata, Literal(json.dumps(metadata), datatype=XSD._NS["json"])
|
|
97
97
|
|
|
98
98
|
def _get_rdf_type(self, item: T_CogniteResource) -> str:
|
|
99
99
|
type_ = self._default_rdf_type
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
from collections.abc import Iterable, Iterator
|
|
2
|
+
from typing import cast
|
|
3
|
+
|
|
4
|
+
from cognite.client import CogniteClient
|
|
5
|
+
from cognite.client import data_modeling as dm
|
|
6
|
+
from cognite.client.data_classes.data_modeling import DataModelIdentifier
|
|
7
|
+
from cognite.client.data_classes.data_modeling.instances import Instance, PropertyValue
|
|
8
|
+
from rdflib import RDF, XSD, Literal, Namespace, URIRef
|
|
9
|
+
|
|
10
|
+
from cognite.neat.constants import DEFAULT_SPACE_URI
|
|
11
|
+
from cognite.neat.graph.models import Triple
|
|
12
|
+
from cognite.neat.issues.errors import ResourceRetrievalError
|
|
13
|
+
|
|
14
|
+
from ._base import BaseExtractor
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DMSExtractor(BaseExtractor):
|
|
18
|
+
"""Extract data from Cognite Data Fusion DMS instances into Neat.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
items: The items to extract.
|
|
22
|
+
total: The total number of items to extract. If provided, this will be used to estimate the progress.
|
|
23
|
+
limit: The maximum number of items to extract.
|
|
24
|
+
overwrite_namespace: If provided, this will overwrite the space of the extracted items.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
items: Iterable[Instance],
|
|
30
|
+
total: int | None = None,
|
|
31
|
+
limit: int | None = None,
|
|
32
|
+
overwrite_namespace: Namespace | None = None,
|
|
33
|
+
) -> None:
|
|
34
|
+
self.items = items
|
|
35
|
+
self.total = total
|
|
36
|
+
self.limit = limit
|
|
37
|
+
self.overwrite_namespace = overwrite_namespace
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def from_data_model(
|
|
41
|
+
cls, client: CogniteClient, data_model: DataModelIdentifier, limit: int | None = None
|
|
42
|
+
) -> "DMSExtractor":
|
|
43
|
+
"""Create an extractor from a data model.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
client: The Cognite client to use.
|
|
47
|
+
data_model: The data model to extract.
|
|
48
|
+
limit: The maximum number of instances to extract.
|
|
49
|
+
"""
|
|
50
|
+
retrieved = client.data_modeling.data_models.retrieve(data_model, inline_views=True)
|
|
51
|
+
if not retrieved:
|
|
52
|
+
raise ResourceRetrievalError(dm.DataModelId.load(data_model), "data model", "Data Model is missing in CDF")
|
|
53
|
+
return cls.from_views(client, retrieved.latest_version().views, limit)
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def from_views(cls, client: CogniteClient, views: Iterable[dm.View], limit: int | None = None) -> "DMSExtractor":
|
|
57
|
+
"""Create an extractor from a set of views.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
client: The Cognite client to use.
|
|
61
|
+
views: The views to extract.
|
|
62
|
+
limit: The maximum number of instances to extract.
|
|
63
|
+
"""
|
|
64
|
+
return cls(_InstanceIterator(client, views), total=None, limit=limit)
|
|
65
|
+
|
|
66
|
+
def extract(self) -> Iterable[Triple]:
|
|
67
|
+
for count, item in enumerate(self.items, 1):
|
|
68
|
+
if self.limit and count > self.limit:
|
|
69
|
+
break
|
|
70
|
+
yield from self._extract_instance(item)
|
|
71
|
+
|
|
72
|
+
def _extract_instance(self, instance: Instance) -> Iterable[Triple]:
|
|
73
|
+
if isinstance(instance, dm.Edge):
|
|
74
|
+
if not instance.properties:
|
|
75
|
+
yield (
|
|
76
|
+
self._as_uri_ref(instance.start_node),
|
|
77
|
+
self._as_uri_ref(instance.type),
|
|
78
|
+
self._as_uri_ref(instance.end_node),
|
|
79
|
+
)
|
|
80
|
+
return
|
|
81
|
+
else:
|
|
82
|
+
# If the edge has properties, we create a node for the edge and connect it to the start and end nodes.
|
|
83
|
+
id_ = self._as_uri_ref(instance)
|
|
84
|
+
yield id_, RDF.type, self._as_uri_ref(instance.type)
|
|
85
|
+
yield id_, RDF.type, self._get_namespace(instance.space).Edge
|
|
86
|
+
yield (
|
|
87
|
+
id_,
|
|
88
|
+
self._as_uri_ref(dm.DirectRelationReference(instance.space, "startNode")),
|
|
89
|
+
self._as_uri_ref(instance.start_node),
|
|
90
|
+
)
|
|
91
|
+
yield (
|
|
92
|
+
id_,
|
|
93
|
+
self._as_uri_ref(dm.DirectRelationReference(instance.space, "endNode")),
|
|
94
|
+
self._as_uri_ref(instance.end_node),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
elif isinstance(instance, dm.Node):
|
|
98
|
+
id_ = self._as_uri_ref(instance)
|
|
99
|
+
if instance.type:
|
|
100
|
+
type_ = self._as_uri_ref(cast(dm.DirectRelationReference, instance.type))
|
|
101
|
+
else:
|
|
102
|
+
type_ = self._get_namespace(instance.space).Node
|
|
103
|
+
|
|
104
|
+
yield id_, RDF.type, type_
|
|
105
|
+
else:
|
|
106
|
+
raise NotImplementedError(f"Unknown instance type {type(instance)}")
|
|
107
|
+
|
|
108
|
+
for view_id, properties in instance.properties.items():
|
|
109
|
+
namespace = self._get_namespace(view_id.space)
|
|
110
|
+
for key, value in properties.items():
|
|
111
|
+
for object_ in self._get_objects(value):
|
|
112
|
+
yield id_, namespace[key], object_
|
|
113
|
+
|
|
114
|
+
def _get_objects(self, value: PropertyValue) -> Iterable[Literal | URIRef]:
|
|
115
|
+
if isinstance(value, str | float | bool | int):
|
|
116
|
+
yield Literal(value)
|
|
117
|
+
elif isinstance(value, dict) and "space" in value and "externalId" in value:
|
|
118
|
+
yield self._as_uri_ref(dm.DirectRelationReference.load(value))
|
|
119
|
+
elif isinstance(value, dict):
|
|
120
|
+
# This object is a json object.
|
|
121
|
+
yield Literal(str(value), datatype=XSD._NS["json"])
|
|
122
|
+
elif isinstance(value, list):
|
|
123
|
+
for item in value:
|
|
124
|
+
yield from self._get_objects(item)
|
|
125
|
+
|
|
126
|
+
def _as_uri_ref(self, instance: Instance | dm.DirectRelationReference) -> URIRef:
|
|
127
|
+
return self._get_namespace(instance.space)[instance.external_id]
|
|
128
|
+
|
|
129
|
+
def _get_namespace(self, space: str) -> Namespace:
|
|
130
|
+
if self.overwrite_namespace:
|
|
131
|
+
return self.overwrite_namespace
|
|
132
|
+
return Namespace(DEFAULT_SPACE_URI.format(space=space))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class _InstanceIterator(Iterator[Instance]):
|
|
136
|
+
def __init__(self, client: CogniteClient, views: Iterable[dm.View]):
|
|
137
|
+
self.client = client
|
|
138
|
+
self.views = views
|
|
139
|
+
|
|
140
|
+
def __iter__(self) -> Iterator[Instance]:
|
|
141
|
+
return self
|
|
142
|
+
|
|
143
|
+
def __next__(self) -> Instance: # type: ignore[misc]
|
|
144
|
+
for view in self.views:
|
|
145
|
+
# All nodes and edges with properties
|
|
146
|
+
yield from self.client.data_modeling.instances(chunk_size=None, instance_type="node", sources=[view])
|
|
147
|
+
yield from self.client.data_modeling.instances(chunk_size=None, instance_type="edge", sources=[view])
|
|
148
|
+
|
|
149
|
+
for prop in view.properties.values():
|
|
150
|
+
if isinstance(prop, dm.EdgeConnection):
|
|
151
|
+
# Get all edges with properties
|
|
152
|
+
yield from self.client.data_modeling.instances(
|
|
153
|
+
chunk_size=None,
|
|
154
|
+
instance_type="edge",
|
|
155
|
+
filter=dm.filters.Equals(
|
|
156
|
+
["edge", "type"], {"space": prop.type.space, "externalId": prop.type.external_id}
|
|
157
|
+
),
|
|
158
|
+
)
|
|
@@ -17,7 +17,6 @@ from cognite.neat.rules.models import DMSRules, InformationRules
|
|
|
17
17
|
from cognite.neat.rules.models.data_types import DataType
|
|
18
18
|
from cognite.neat.rules.models.entities import ClassEntity, EntityTypes
|
|
19
19
|
from cognite.neat.rules.models.information import InformationProperty
|
|
20
|
-
from cognite.neat.rules.transformers import DMSToInformation
|
|
21
20
|
from cognite.neat.utils.rdf_ import remove_namespace_from_uri
|
|
22
21
|
|
|
23
22
|
from ._base import BaseExtractor
|
|
@@ -43,6 +42,9 @@ class MockGraphGenerator(BaseExtractor):
|
|
|
43
42
|
allow_isolated_classes: bool = True,
|
|
44
43
|
):
|
|
45
44
|
if isinstance(rules, DMSRules):
|
|
45
|
+
# fixes potential issues with circular dependencies
|
|
46
|
+
from cognite.neat.rules.transformers import DMSToInformation
|
|
47
|
+
|
|
46
48
|
self.rules = DMSToInformation().transform(rules).rules
|
|
47
49
|
elif isinstance(rules, InformationRules):
|
|
48
50
|
self.rules = rules
|
|
@@ -152,21 +154,33 @@ def generate_triples(
|
|
|
152
154
|
# generate triples for connected classes
|
|
153
155
|
for class_ in generation_order:
|
|
154
156
|
triples += _generate_triples_per_class(
|
|
155
|
-
class_,
|
|
157
|
+
class_,
|
|
158
|
+
class_property_pairs,
|
|
159
|
+
sym_pairs,
|
|
160
|
+
instance_ids,
|
|
161
|
+
namespace,
|
|
162
|
+
stop_on_exception,
|
|
156
163
|
)
|
|
157
164
|
|
|
158
165
|
# generate triples for isolated classes
|
|
159
166
|
if allow_isolated_classes:
|
|
160
167
|
for class_ in set(class_count.keys()) - set(generation_order):
|
|
161
168
|
triples += _generate_triples_per_class(
|
|
162
|
-
class_,
|
|
169
|
+
class_,
|
|
170
|
+
class_property_pairs,
|
|
171
|
+
sym_pairs,
|
|
172
|
+
instance_ids,
|
|
173
|
+
namespace,
|
|
174
|
+
stop_on_exception,
|
|
163
175
|
)
|
|
164
176
|
|
|
165
177
|
return triples
|
|
166
178
|
|
|
167
179
|
|
|
168
180
|
def _get_generation_order(
|
|
169
|
-
class_linkage: pd.DataFrame,
|
|
181
|
+
class_linkage: pd.DataFrame,
|
|
182
|
+
parent_col: str = "source_class",
|
|
183
|
+
child_col: str = "target_class",
|
|
170
184
|
) -> dict:
|
|
171
185
|
parent_child_list: list[list[str]] = class_linkage[[parent_col, child_col]].values.tolist()
|
|
172
186
|
# Build a directed graph and a list of all names that have no parent
|
|
@@ -244,7 +258,10 @@ def _remove_non_requested_sym_pairs(class_linkage: pd.DataFrame, class_count: di
|
|
|
244
258
|
|
|
245
259
|
|
|
246
260
|
def _generate_mock_data_property_triples(
|
|
247
|
-
instance_ids: list[URIRef],
|
|
261
|
+
instance_ids: list[URIRef],
|
|
262
|
+
property_: str,
|
|
263
|
+
namespace: Namespace,
|
|
264
|
+
value_type: DataType,
|
|
248
265
|
) -> list[tuple[URIRef, URIRef, Literal]]:
|
|
249
266
|
"""Generates triples for data properties."""
|
|
250
267
|
|
|
@@ -254,7 +271,13 @@ def _generate_mock_data_property_triples(
|
|
|
254
271
|
if python_type is int:
|
|
255
272
|
triples.append((id_, URIRef(namespace[property_]), Literal(random.randint(1, 1983))))
|
|
256
273
|
elif python_type is float:
|
|
257
|
-
triples.append(
|
|
274
|
+
triples.append(
|
|
275
|
+
(
|
|
276
|
+
id_,
|
|
277
|
+
URIRef(namespace[property_]),
|
|
278
|
+
Literal(numpy.float32(random.uniform(1, 1983))),
|
|
279
|
+
)
|
|
280
|
+
)
|
|
258
281
|
# generate string
|
|
259
282
|
else:
|
|
260
283
|
triples.append(
|
|
@@ -293,7 +316,12 @@ def _generate_mock_object_property_triples(
|
|
|
293
316
|
|
|
294
317
|
if tuple((class_, property_definition.value_type)) in sym_pairs:
|
|
295
318
|
symmetric_class_properties = class_property_pairs[cast(ClassEntity, property_definition.value_type)]
|
|
296
|
-
candidates = list(
|
|
319
|
+
candidates = list(
|
|
320
|
+
filter(
|
|
321
|
+
lambda instance: instance.value_type == class_,
|
|
322
|
+
symmetric_class_properties,
|
|
323
|
+
)
|
|
324
|
+
)
|
|
297
325
|
symmetric_property = candidates[0]
|
|
298
326
|
if len(candidates) > 1:
|
|
299
327
|
warnings.warn(
|
|
@@ -310,10 +338,22 @@ def _generate_mock_object_property_triples(
|
|
|
310
338
|
target = instance_ids[cast(ClassEntity, property_definition.value_type)][
|
|
311
339
|
i % len(instance_ids[cast(ClassEntity, property_definition.value_type)])
|
|
312
340
|
]
|
|
313
|
-
triples += [
|
|
341
|
+
triples += [
|
|
342
|
+
(
|
|
343
|
+
URIRef(source),
|
|
344
|
+
URIRef(namespace[property_definition.property_]),
|
|
345
|
+
URIRef(target),
|
|
346
|
+
)
|
|
347
|
+
]
|
|
314
348
|
|
|
315
349
|
if symmetric_property:
|
|
316
|
-
triples += [
|
|
350
|
+
triples += [
|
|
351
|
+
(
|
|
352
|
+
URIRef(target),
|
|
353
|
+
URIRef(namespace[symmetric_property.property_]),
|
|
354
|
+
URIRef(source),
|
|
355
|
+
)
|
|
356
|
+
]
|
|
317
357
|
|
|
318
358
|
if symmetric_property:
|
|
319
359
|
class_property_pairs[cast(ClassEntity, property_definition.value_type)].remove(symmetric_property)
|
|
@@ -13,8 +13,10 @@ from cognite.client.data_classes.data_modeling.ids import InstanceId
|
|
|
13
13
|
from cognite.client.data_classes.data_modeling.views import SingleEdgeConnection
|
|
14
14
|
from cognite.client.exceptions import CogniteAPIError
|
|
15
15
|
from pydantic import BaseModel, ValidationInfo, create_model, field_validator
|
|
16
|
+
from rdflib import RDF
|
|
16
17
|
|
|
17
18
|
from cognite.neat.graph._tracking import LogTracker, Tracker
|
|
19
|
+
from cognite.neat.graph.models import InstanceType
|
|
18
20
|
from cognite.neat.issues import IssueList, NeatIssue, NeatIssueList
|
|
19
21
|
from cognite.neat.issues.errors import (
|
|
20
22
|
ResourceConvertionError,
|
|
@@ -108,7 +110,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
108
110
|
for view in self.data_model.views:
|
|
109
111
|
view_id = view.as_id()
|
|
110
112
|
tracker.start(repr(view_id))
|
|
111
|
-
pydantic_cls,
|
|
113
|
+
pydantic_cls, edge_by_type, issues = self._create_validation_classes(view) # type: ignore[var-annotated]
|
|
112
114
|
yield from issues
|
|
113
115
|
tracker.issue(issues)
|
|
114
116
|
class_name = self.class_by_view_id.get(view.as_id(), view.external_id)
|
|
@@ -122,7 +124,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
122
124
|
if stop_on_exception:
|
|
123
125
|
raise error from e
|
|
124
126
|
yield error
|
|
125
|
-
yield from self._create_edges(identifier, properties,
|
|
127
|
+
yield from self._create_edges(identifier, properties, edge_by_type, tracker)
|
|
126
128
|
tracker.finish(repr(view_id))
|
|
127
129
|
|
|
128
130
|
def write_to_file(self, filepath: Path) -> None:
|
|
@@ -147,16 +149,16 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
147
149
|
|
|
148
150
|
def _create_validation_classes(
|
|
149
151
|
self, view: dm.View
|
|
150
|
-
) -> tuple[type[BaseModel], dict[str, dm.EdgeConnection], NeatIssueList]:
|
|
152
|
+
) -> tuple[type[BaseModel], dict[str, tuple[str, dm.EdgeConnection]], NeatIssueList]:
|
|
151
153
|
issues = IssueList()
|
|
152
154
|
field_definitions: dict[str, tuple[type, Any]] = {}
|
|
153
|
-
edge_by_property: dict[str, dm.EdgeConnection] = {}
|
|
155
|
+
edge_by_property: dict[str, tuple[str, dm.EdgeConnection]] = {}
|
|
154
156
|
validators: dict[str, classmethod] = {}
|
|
155
157
|
direct_relation_by_property: dict[str, dm.DirectRelation] = {}
|
|
156
158
|
json_fields: list[str] = []
|
|
157
159
|
for prop_name, prop in view.properties.items():
|
|
158
160
|
if isinstance(prop, dm.EdgeConnection):
|
|
159
|
-
edge_by_property[
|
|
161
|
+
edge_by_property[prop.type.external_id] = prop_name, prop
|
|
160
162
|
if isinstance(prop, dm.MappedProperty):
|
|
161
163
|
if isinstance(prop.type, dm.DirectRelation):
|
|
162
164
|
direct_relation_by_property[prop_name] = prop.type
|
|
@@ -215,7 +217,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
215
217
|
|
|
216
218
|
def parse_direct_relation(cls, value: list, info: ValidationInfo) -> dict | list[dict]:
|
|
217
219
|
# We validate above that we only get one value for single direct relations.
|
|
218
|
-
if
|
|
220
|
+
if list.__name__ in _get_field_value_types(cls, info):
|
|
219
221
|
return [{"space": self.instance_space, "externalId": v} for v in value]
|
|
220
222
|
elif value:
|
|
221
223
|
return {"space": self.instance_space, "externalId": value[0]}
|
|
@@ -231,16 +233,17 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
231
233
|
def _create_node(
|
|
232
234
|
self,
|
|
233
235
|
identifier: str,
|
|
234
|
-
properties: dict[str, list[str]],
|
|
236
|
+
properties: dict[str | InstanceType, list[str]],
|
|
235
237
|
pydantic_cls: type[BaseModel],
|
|
236
238
|
view_id: dm.ViewId,
|
|
237
239
|
) -> dm.InstanceApply:
|
|
240
|
+
type_ = properties.pop(RDF.type, [None])[0]
|
|
238
241
|
created = pydantic_cls.model_validate(properties)
|
|
239
242
|
|
|
240
243
|
return dm.NodeApply(
|
|
241
244
|
space=self.instance_space,
|
|
242
245
|
external_id=identifier,
|
|
243
|
-
|
|
246
|
+
type=dm.DirectRelationReference(view_id.space, type_) if type_ is not None else None,
|
|
244
247
|
sources=[dm.NodeOrEdgeData(source=view_id, properties=dict(created.model_dump().items()))],
|
|
245
248
|
)
|
|
246
249
|
|
|
@@ -248,13 +251,13 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
248
251
|
self,
|
|
249
252
|
identifier: str,
|
|
250
253
|
properties: dict[str, list[str]],
|
|
251
|
-
|
|
254
|
+
edge_by_type: dict[str, tuple[str, dm.EdgeConnection]],
|
|
252
255
|
tracker: Tracker,
|
|
253
256
|
) -> Iterable[dm.EdgeApply | NeatIssue]:
|
|
254
|
-
for
|
|
255
|
-
if
|
|
257
|
+
for predicate, values in properties.items():
|
|
258
|
+
if predicate not in edge_by_type:
|
|
256
259
|
continue
|
|
257
|
-
edge =
|
|
260
|
+
prop_id, edge = edge_by_type[predicate]
|
|
258
261
|
if isinstance(edge, SingleEdgeConnection) and len(values) > 1:
|
|
259
262
|
error = ResourceDuplicatedError(
|
|
260
263
|
resource_type="edge",
|
|
@@ -264,7 +267,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
264
267
|
tracker.issue(error)
|
|
265
268
|
yield error
|
|
266
269
|
for target in values:
|
|
267
|
-
external_id = f"{identifier}.{
|
|
270
|
+
external_id = f"{identifier}.{prop_id}.{target}"
|
|
268
271
|
yield dm.EdgeApply(
|
|
269
272
|
space=self.instance_space,
|
|
270
273
|
external_id=(external_id if len(external_id) < 256 else create_sha256_hash(external_id)),
|
cognite/neat/graph/models.py
CHANGED
|
@@ -6,6 +6,7 @@ from rdflib import RDF, Graph, URIRef
|
|
|
6
6
|
from rdflib import Literal as RdfLiteral
|
|
7
7
|
from rdflib.query import ResultRow
|
|
8
8
|
|
|
9
|
+
from cognite.neat.graph.models import InstanceType
|
|
9
10
|
from cognite.neat.rules.models.entities import ClassEntity
|
|
10
11
|
from cognite.neat.rules.models.information import InformationRules
|
|
11
12
|
from cognite.neat.utils.rdf_ import remove_namespace_from_uri
|
|
@@ -98,7 +99,7 @@ class Queries:
|
|
|
98
99
|
self,
|
|
99
100
|
instance_id: URIRef,
|
|
100
101
|
property_renaming_config: dict | None = None,
|
|
101
|
-
) -> tuple[str, dict[str, list[str]]] | None:
|
|
102
|
+
) -> tuple[str, dict[str | InstanceType, list[str]]] | None:
|
|
102
103
|
"""DESCRIBE instance for a given class from the graph store
|
|
103
104
|
|
|
104
105
|
Args:
|
|
@@ -126,7 +127,8 @@ class Queries:
|
|
|
126
127
|
# losing the namespace from the predicate!
|
|
127
128
|
if not property_renaming_config and predicate != RDF.type:
|
|
128
129
|
property_values[remove_namespace_from_uri(predicate, validation="prefix")].append(value)
|
|
129
|
-
|
|
130
|
+
elif predicate == RDF.type:
|
|
131
|
+
property_values[RDF.type].append(value)
|
|
130
132
|
# use-case: calling describe with renaming properties
|
|
131
133
|
# renaming the property to the new name, if the property is defined
|
|
132
134
|
# in the RULES sheet
|
cognite/neat/issues/_base.py
CHANGED
|
@@ -26,6 +26,7 @@ from ._properties import (
|
|
|
26
26
|
PropertyDefinitionDuplicatedWarning,
|
|
27
27
|
PropertyNotFoundWarning,
|
|
28
28
|
PropertyTypeNotSupportedWarning,
|
|
29
|
+
PropertyValueTypeUndefinedWarning,
|
|
29
30
|
)
|
|
30
31
|
from ._resources import (
|
|
31
32
|
ResourceNeatWarning,
|
|
@@ -49,6 +50,7 @@ __all__ = [
|
|
|
49
50
|
"PropertyDefinitionDuplicatedWarning",
|
|
50
51
|
"PropertyTypeNotSupportedWarning",
|
|
51
52
|
"PropertyNotFoundWarning",
|
|
53
|
+
"PropertyValueTypeUndefinedWarning",
|
|
52
54
|
"ResourceNeatWarning",
|
|
53
55
|
"ResourcesDuplicatedWarning",
|
|
54
56
|
"RegexViolationWarning",
|
|
@@ -42,3 +42,15 @@ class PropertyDefinitionDuplicatedWarning(PropertyWarning[T_Identifier]):
|
|
|
42
42
|
values: frozenset[str]
|
|
43
43
|
default_action: str
|
|
44
44
|
recommended_action: str | None = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class PropertyValueTypeUndefinedWarning(PropertyWarning[T_Identifier]):
|
|
49
|
+
"""The {resource_type} with identifier {identifier} has a property {property_name}
|
|
50
|
+
which has undefined value type. This may result in unexpected behavior when exporting rules.
|
|
51
|
+
{default_action}"""
|
|
52
|
+
|
|
53
|
+
extra = "Recommended action: {recommended_action}"
|
|
54
|
+
|
|
55
|
+
default_action: str
|
|
56
|
+
recommended_action: str | None = None
|
|
@@ -113,7 +113,7 @@ class DMSImporter(BaseImporter[DMSInputRules]):
|
|
|
113
113
|
DMSSchema(),
|
|
114
114
|
[
|
|
115
115
|
ResourceRetrievalError(
|
|
116
|
-
dm.DataModelId.load(
|
|
116
|
+
dm.DataModelId.load(data_model_id), # type: ignore[arg-type]
|
|
117
117
|
"data model",
|
|
118
118
|
"Data Model is missing in CDF",
|
|
119
119
|
)
|
|
@@ -3,15 +3,17 @@ from datetime import datetime
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import cast
|
|
5
5
|
|
|
6
|
-
from rdflib import Graph, Namespace, URIRef
|
|
6
|
+
from rdflib import RDF, Graph, Namespace, URIRef
|
|
7
7
|
from rdflib import Literal as RdfLiteral
|
|
8
8
|
|
|
9
9
|
from cognite.neat.constants import DEFAULT_NAMESPACE, get_default_prefixes
|
|
10
10
|
from cognite.neat.issues import IssueList
|
|
11
11
|
from cognite.neat.issues.errors import FileReadError
|
|
12
|
+
from cognite.neat.issues.warnings import PropertyValueTypeUndefinedWarning
|
|
12
13
|
from cognite.neat.rules._shared import ReadRules
|
|
13
14
|
from cognite.neat.rules.importers._base import BaseImporter
|
|
14
15
|
from cognite.neat.rules.models._base_rules import MatchType
|
|
16
|
+
from cognite.neat.rules.models.entities._single_value import UnknownEntity
|
|
15
17
|
from cognite.neat.rules.models.information import (
|
|
16
18
|
InformationInputRules,
|
|
17
19
|
InformationMetadata,
|
|
@@ -25,16 +27,6 @@ ORDERED_CLASSES_QUERY = """SELECT ?class (count(?s) as ?instances )
|
|
|
25
27
|
|
|
26
28
|
INSTANCES_OF_CLASS_QUERY = """SELECT ?s WHERE { ?s a <class> . }"""
|
|
27
29
|
|
|
28
|
-
INSTANCE_PROPERTIES_JSON_DEFINITION = """SELECT ?property (count(?property) as ?occurrence) ?dataType ?objectType
|
|
29
|
-
WHERE {<instance_id> ?property ?value .
|
|
30
|
-
|
|
31
|
-
BIND(IF(REGEX(?value, "^\u007b(.*)\u007d$"),
|
|
32
|
-
<http://www.w3.org/2001/XMLSchema#json>,
|
|
33
|
-
datatype(?value)) AS ?dataType)
|
|
34
|
-
|
|
35
|
-
OPTIONAL {?value rdf:type ?objectType .}}
|
|
36
|
-
GROUP BY ?property ?dataType ?objectType"""
|
|
37
|
-
|
|
38
30
|
INSTANCE_PROPERTIES_DEFINITION = """SELECT ?property (count(?property) as ?occurrence) ?dataType ?objectType
|
|
39
31
|
WHERE {<instance_id> ?property ?value .
|
|
40
32
|
|
|
@@ -56,7 +48,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
56
48
|
graph: Knowledge graph
|
|
57
49
|
max_number_of_instance: Maximum number of instances to be used in inference
|
|
58
50
|
prefix: Prefix to be used for the inferred model
|
|
59
|
-
check_for_json_string: Check if values are JSON strings
|
|
60
51
|
"""
|
|
61
52
|
|
|
62
53
|
def __init__(
|
|
@@ -65,15 +56,11 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
65
56
|
graph: Graph,
|
|
66
57
|
max_number_of_instance: int = -1,
|
|
67
58
|
prefix: str = "inferred",
|
|
68
|
-
check_for_json_string: bool = False,
|
|
69
59
|
) -> None:
|
|
70
60
|
self.issue_list = issue_list
|
|
71
61
|
self.graph = graph
|
|
72
62
|
self.max_number_of_instance = max_number_of_instance
|
|
73
63
|
self.prefix = prefix
|
|
74
|
-
self.check_for_json_string = (
|
|
75
|
-
check_for_json_string if graph.store.__class__.__name__ != "OxigraphStore" else False
|
|
76
|
-
)
|
|
77
64
|
|
|
78
65
|
@classmethod
|
|
79
66
|
def from_graph_store(
|
|
@@ -81,7 +68,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
81
68
|
store: NeatGraphStore,
|
|
82
69
|
max_number_of_instance: int = -1,
|
|
83
70
|
prefix: str = "inferred",
|
|
84
|
-
check_for_json_string: bool = False,
|
|
85
71
|
) -> "InferenceImporter":
|
|
86
72
|
issue_list = IssueList(title="Inferred from graph store")
|
|
87
73
|
|
|
@@ -90,7 +76,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
90
76
|
store.graph,
|
|
91
77
|
max_number_of_instance=max_number_of_instance,
|
|
92
78
|
prefix=prefix,
|
|
93
|
-
check_for_json_string=check_for_json_string,
|
|
94
79
|
)
|
|
95
80
|
|
|
96
81
|
@classmethod
|
|
@@ -99,7 +84,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
99
84
|
filepath: Path,
|
|
100
85
|
max_number_of_instance: int = -1,
|
|
101
86
|
prefix: str = "inferred",
|
|
102
|
-
check_for_json_string: bool = False,
|
|
103
87
|
) -> "InferenceImporter":
|
|
104
88
|
issue_list = IssueList(title=f"'{filepath.name}'")
|
|
105
89
|
|
|
@@ -114,7 +98,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
114
98
|
graph,
|
|
115
99
|
max_number_of_instance=max_number_of_instance,
|
|
116
100
|
prefix=prefix,
|
|
117
|
-
check_for_json_string=check_for_json_string,
|
|
118
101
|
)
|
|
119
102
|
|
|
120
103
|
@classmethod
|
|
@@ -123,7 +106,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
123
106
|
filepath: Path,
|
|
124
107
|
max_number_of_instance: int = -1,
|
|
125
108
|
prefix: str = "inferred",
|
|
126
|
-
check_for_json_string: bool = False,
|
|
127
109
|
) -> "InferenceImporter":
|
|
128
110
|
raise NotImplementedError("JSON file format is not supported yet.")
|
|
129
111
|
|
|
@@ -133,7 +115,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
133
115
|
filepath: Path,
|
|
134
116
|
max_number_of_instance: int = -1,
|
|
135
117
|
prefix: str = "inferred",
|
|
136
|
-
check_for_json_string: bool = False,
|
|
137
118
|
) -> "InferenceImporter":
|
|
138
119
|
raise NotImplementedError("YAML file format is not supported yet.")
|
|
139
120
|
|
|
@@ -143,7 +124,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
143
124
|
filepath: Path,
|
|
144
125
|
max_number_of_instance: int = -1,
|
|
145
126
|
prefix: str = "inferred",
|
|
146
|
-
check_for_json_string: bool = False,
|
|
147
127
|
) -> "InferenceImporter":
|
|
148
128
|
raise NotImplementedError("JSON file format is not supported yet.")
|
|
149
129
|
|
|
@@ -180,7 +160,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
180
160
|
prefixes: dict[str, Namespace] = get_default_prefixes()
|
|
181
161
|
count_by_value_type_by_property: dict[str, dict[str, int]] = defaultdict(Counter)
|
|
182
162
|
|
|
183
|
-
query = INSTANCE_PROPERTIES_JSON_DEFINITION if self.check_for_json_string else INSTANCE_PROPERTIES_DEFINITION
|
|
184
163
|
# Adds default namespace to prefixes
|
|
185
164
|
prefixes[self._default_metadata().prefix] = self._default_metadata().namespace
|
|
186
165
|
|
|
@@ -208,19 +187,35 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
208
187
|
+ f" LIMIT {self.max_number_of_instance}"
|
|
209
188
|
):
|
|
210
189
|
for property_uri, occurrence, data_type_uri, object_type_uri in self.graph.query( # type: ignore[misc]
|
|
211
|
-
|
|
190
|
+
INSTANCE_PROPERTIES_DEFINITION.replace("instance_id", instance)
|
|
212
191
|
): # type: ignore[misc]
|
|
192
|
+
# this is to skip rdf:type property
|
|
193
|
+
if property_uri == RDF.type:
|
|
194
|
+
continue
|
|
195
|
+
|
|
213
196
|
property_id = remove_namespace_from_uri(property_uri)
|
|
214
197
|
|
|
215
198
|
self._add_uri_namespace_to_prefixes(cast(URIRef, property_uri), prefixes)
|
|
216
|
-
value_type_uri = data_type_uri if data_type_uri else object_type_uri
|
|
217
199
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
200
|
+
if value_type_uri := (data_type_uri or object_type_uri):
|
|
201
|
+
self._add_uri_namespace_to_prefixes(cast(URIRef, value_type_uri), prefixes)
|
|
202
|
+
|
|
203
|
+
value_type_id = remove_namespace_from_uri(value_type_uri)
|
|
204
|
+
|
|
205
|
+
# this handles situations when property points to node that is not present in graph
|
|
206
|
+
else:
|
|
207
|
+
value_type_id = str(UnknownEntity())
|
|
208
|
+
|
|
209
|
+
self.issue_list.append(
|
|
210
|
+
PropertyValueTypeUndefinedWarning(
|
|
211
|
+
resource_type="Property",
|
|
212
|
+
identifier=f"{class_id}{property_id}",
|
|
213
|
+
property_name=property_id,
|
|
214
|
+
default_action="Remove the property from the rules",
|
|
215
|
+
recommended_action="Make sure that graph is complete",
|
|
216
|
+
)
|
|
217
|
+
)
|
|
221
218
|
|
|
222
|
-
self._add_uri_namespace_to_prefixes(cast(URIRef, value_type_uri), prefixes)
|
|
223
|
-
value_type_id = remove_namespace_from_uri(value_type_uri)
|
|
224
219
|
id_ = f"{class_id}:{property_id}"
|
|
225
220
|
|
|
226
221
|
definition = {
|
|
@@ -265,7 +260,7 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
|
|
|
265
260
|
if len(count_list) == 1:
|
|
266
261
|
type_, count = count_list[0]
|
|
267
262
|
counts_str = f"with value type {base_string.format(value_type=type_, count=count)} in the graph"
|
|
268
|
-
elif len(count_list) ==
|
|
263
|
+
elif len(count_list) == 2:
|
|
269
264
|
first = base_string.format(value_type=count_list[0][0], count=count_list[0][1])
|
|
270
265
|
second = base_string.format(value_type=count_list[1][0], count=count_list[1][1])
|
|
271
266
|
counts_str = f"with value types {first} and {second} in the graph"
|
|
@@ -344,7 +344,8 @@ class _DMSExporter:
|
|
|
344
344
|
# If not set, nullable is True and immutable is False
|
|
345
345
|
nullable=prop.nullable if prop.nullable is not None else True,
|
|
346
346
|
immutable=prop.immutable if prop.immutable is not None else False,
|
|
347
|
-
|
|
347
|
+
# Guarding against default value being set for connection properties
|
|
348
|
+
default_value=prop.default if not prop.connection else None,
|
|
348
349
|
name=prop.name,
|
|
349
350
|
description=prop.description,
|
|
350
351
|
)
|
|
@@ -535,23 +536,17 @@ class _DMSExporter:
|
|
|
535
536
|
"If this error occurs it is a bug in NEAT, please report"
|
|
536
537
|
f"Debug Info, Invalid valueType reverse connection: {prop.model_dump_json()}"
|
|
537
538
|
)
|
|
538
|
-
reverse_prop: DMSProperty | None = None
|
|
539
539
|
edge_source = None
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
reverse_prop
|
|
551
|
-
and isinstance(reverse_prop.connection, EdgeEntity)
|
|
552
|
-
and reverse_prop.connection.properties is not None
|
|
553
|
-
):
|
|
554
|
-
edge_source = reverse_prop.connection.properties.as_id()
|
|
540
|
+
reverse_prop = next(
|
|
541
|
+
(prop for prop in view_properties_by_id.get(source_view_id, []) if prop.property_ == reverse_prop_id),
|
|
542
|
+
None,
|
|
543
|
+
)
|
|
544
|
+
if (
|
|
545
|
+
reverse_prop
|
|
546
|
+
and isinstance(reverse_prop.connection, EdgeEntity)
|
|
547
|
+
and reverse_prop.connection.properties is not None
|
|
548
|
+
):
|
|
549
|
+
edge_source = reverse_prop.connection.properties.as_id()
|
|
555
550
|
|
|
556
551
|
if reverse_prop is None:
|
|
557
552
|
warnings.warn(
|
|
@@ -577,9 +572,11 @@ class _DMSExporter:
|
|
|
577
572
|
direction="inwards",
|
|
578
573
|
edge_source=edge_source,
|
|
579
574
|
)
|
|
580
|
-
elif
|
|
575
|
+
elif reverse_prop and reverse_prop.connection == "direct":
|
|
581
576
|
reverse_direct_cls = (
|
|
582
|
-
dm.MultiReverseDirectRelationApply
|
|
577
|
+
dm.MultiReverseDirectRelationApply
|
|
578
|
+
if prop.is_list in [True, None]
|
|
579
|
+
else SingleReverseDirectRelationApply
|
|
583
580
|
)
|
|
584
581
|
return reverse_direct_cls(
|
|
585
582
|
source=source_view_id,
|
|
@@ -62,8 +62,11 @@ class ConversionTransformer(RulesTransformer[T_VerifiedInRules, T_VerifiedOutRul
|
|
|
62
62
|
class InformationToDMS(ConversionTransformer[InformationRules, DMSRules]):
|
|
63
63
|
"""Converts InformationRules to DMSRules."""
|
|
64
64
|
|
|
65
|
+
def __init__(self, ignore_undefined_value_types: bool = False):
|
|
66
|
+
self.ignore_undefined_value_types = ignore_undefined_value_types
|
|
67
|
+
|
|
65
68
|
def _transform(self, rules: InformationRules) -> DMSRules:
|
|
66
|
-
return _InformationRulesConverter(rules).as_dms_rules()
|
|
69
|
+
return _InformationRulesConverter(rules).as_dms_rules(self.ignore_undefined_value_types)
|
|
67
70
|
|
|
68
71
|
|
|
69
72
|
class InformationToAsset(ConversionTransformer[InformationRules, AssetRules]):
|
|
@@ -153,7 +156,7 @@ class _InformationRulesConverter:
|
|
|
153
156
|
prefixes=self.rules.prefixes,
|
|
154
157
|
)
|
|
155
158
|
|
|
156
|
-
def as_dms_rules(self) -> "DMSRules":
|
|
159
|
+
def as_dms_rules(self, ignore_undefined_value_types: bool = False) -> "DMSRules":
|
|
157
160
|
from cognite.neat.rules.models.dms._rules import (
|
|
158
161
|
DMSContainer,
|
|
159
162
|
DMSProperty,
|
|
@@ -169,6 +172,8 @@ class _InformationRulesConverter:
|
|
|
169
172
|
properties_by_class: dict[ClassEntity, list[DMSProperty]] = defaultdict(list)
|
|
170
173
|
referenced_containers: dict[ContainerEntity, Counter[ClassEntity]] = defaultdict(Counter)
|
|
171
174
|
for prop in self.rules.properties:
|
|
175
|
+
if ignore_undefined_value_types and isinstance(prop.value_type, UnknownEntity):
|
|
176
|
+
continue
|
|
172
177
|
dms_property = self._as_dms_property(prop, default_space, default_version)
|
|
173
178
|
properties_by_class[prop.class_].append(dms_property)
|
|
174
179
|
if dms_property.container:
|
|
@@ -290,6 +295,10 @@ class _InformationRulesConverter:
|
|
|
290
295
|
# Default connection type.
|
|
291
296
|
connection = EdgeEntity() if prop.is_list else "direct"
|
|
292
297
|
|
|
298
|
+
# defaulting to direct connection
|
|
299
|
+
elif isinstance(value_type, DMSUnknownEntity):
|
|
300
|
+
connection = "direct"
|
|
301
|
+
|
|
293
302
|
container: ContainerEntity | None = None
|
|
294
303
|
container_property: str | None = None
|
|
295
304
|
is_list: bool | None = prop.is_list
|
cognite/neat/store/_base.py
CHANGED
|
@@ -12,7 +12,7 @@ from rdflib.plugins.stores.sparqlstore import SPARQLUpdateStore
|
|
|
12
12
|
from cognite.neat.constants import DEFAULT_NAMESPACE
|
|
13
13
|
from cognite.neat.graph._shared import MIMETypes
|
|
14
14
|
from cognite.neat.graph.extractors import RdfFileExtractor, TripleExtractors
|
|
15
|
-
from cognite.neat.graph.models import Triple
|
|
15
|
+
from cognite.neat.graph.models import InstanceType, Triple
|
|
16
16
|
from cognite.neat.graph.queries import Queries
|
|
17
17
|
from cognite.neat.graph.transformers import Transformers
|
|
18
18
|
from cognite.neat.rules.analysis import InformationAnalysis
|
|
@@ -173,7 +173,7 @@ class NeatGraphStore:
|
|
|
173
173
|
)
|
|
174
174
|
)
|
|
175
175
|
|
|
176
|
-
def read(self, class_: str) -> Iterable[tuple[str, dict[str, list[str]]]]:
|
|
176
|
+
def read(self, class_: str) -> Iterable[tuple[str, dict[str | InstanceType, list[str]]]]:
|
|
177
177
|
"""Read instances for given view from the graph store."""
|
|
178
178
|
|
|
179
179
|
if not self.rules:
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import logging
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from typing import ClassVar, cast
|
|
5
4
|
|
|
@@ -42,7 +41,7 @@ class GraphFromMockData(Step):
|
|
|
42
41
|
]
|
|
43
42
|
|
|
44
43
|
def run( # type: ignore[override, syntax]
|
|
45
|
-
self, rules: MultiRuleData,
|
|
44
|
+
self, rules: MultiRuleData, store: NeatGraph
|
|
46
45
|
) -> FlowMessage:
|
|
47
46
|
if self.configs is None:
|
|
48
47
|
raise WorkflowStepNotInitializedError(type(self).__name__)
|
|
@@ -53,9 +52,6 @@ class GraphFromMockData(Step):
|
|
|
53
52
|
step_execution_status=StepExecutionStatus.ABORT_AND_FAIL,
|
|
54
53
|
)
|
|
55
54
|
|
|
56
|
-
logging.info(50 * "#")
|
|
57
|
-
logging.info(50 * "#")
|
|
58
|
-
logging.info(self.configs["Class count"])
|
|
59
55
|
try:
|
|
60
56
|
class_count = json.loads(self.configs["Class count"]) if self.configs["Class count"] else {}
|
|
61
57
|
except Exception:
|
|
@@ -69,9 +65,9 @@ class GraphFromMockData(Step):
|
|
|
69
65
|
class_count,
|
|
70
66
|
)
|
|
71
67
|
|
|
72
|
-
|
|
68
|
+
store.graph.write(extractor)
|
|
73
69
|
|
|
74
|
-
return FlowMessage(output_text=f"Instances loaded to the {
|
|
70
|
+
return FlowMessage(output_text=f"Instances loaded to the {store.__class__.__name__}")
|
|
75
71
|
|
|
76
72
|
|
|
77
73
|
class GraphFromRdfFile(Step):
|
|
@@ -108,12 +104,12 @@ class GraphFromRdfFile(Step):
|
|
|
108
104
|
),
|
|
109
105
|
]
|
|
110
106
|
|
|
111
|
-
def run(self,
|
|
107
|
+
def run(self, store: NeatGraph) -> FlowMessage: # type: ignore[override, syntax]
|
|
112
108
|
if self.configs is None or self.data_store_path is None:
|
|
113
109
|
raise WorkflowStepNotInitializedError(type(self).__name__)
|
|
114
110
|
|
|
115
111
|
if source_file := self.configs["File path"]:
|
|
116
|
-
|
|
112
|
+
store.graph.write(
|
|
117
113
|
RdfFileExtractor( # type: ignore[abstract]
|
|
118
114
|
filepath=self.data_store_path / Path(source_file),
|
|
119
115
|
mime_type=self.configs["MIME type"], # type: ignore[arg-type]
|
|
@@ -31,7 +31,7 @@ class GraphToRdfFile(Step):
|
|
|
31
31
|
]
|
|
32
32
|
|
|
33
33
|
def run( # type: ignore[override, syntax]
|
|
34
|
-
self,
|
|
34
|
+
self, store: NeatGraph
|
|
35
35
|
) -> FlowMessage: # type: ignore[syntax]
|
|
36
36
|
if self.configs is None or self.data_store_path is None:
|
|
37
37
|
raise WorkflowStepNotInitializedError(type(self).__name__)
|
|
@@ -39,7 +39,7 @@ class GraphToRdfFile(Step):
|
|
|
39
39
|
storage_path = self.data_store_path / Path(self.configs["File path"])
|
|
40
40
|
relative_graph_file_path = str(storage_path).split("/data/")[1]
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
store.graph.graph.serialize(str(storage_path), format="turtle")
|
|
43
43
|
|
|
44
44
|
output_text = (
|
|
45
45
|
"<p></p>"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cognite/neat/__init__.py,sha256=AiexNcHdAHFbrrbo9c65gtil1dqx_SGraDH1PSsXjKE,126
|
|
2
2
|
cognite/neat/_shared.py,sha256=RSaHm2eJceTlvb-hMMe4nHgoHdPYDfN3XcxDXo24k3A,1530
|
|
3
|
-
cognite/neat/_version.py,sha256=
|
|
3
|
+
cognite/neat/_version.py,sha256=araU2bbf8DwRBsZfRETG4oRqnPYvWai2WeyP-zS9jUM,23
|
|
4
4
|
cognite/neat/app/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
cognite/neat/app/api/asgi/metrics.py,sha256=nxFy7L5cChTI0a-zkCiJ59Aq8yLuIJp5c9Dg0wRXtV0,152
|
|
6
6
|
cognite/neat/app/api/configuration.py,sha256=L1DCtLZ1HZku8I2z-JWd5RDsXhIsboFsKwAMhkrm-bY,3600
|
|
@@ -39,7 +39,7 @@ cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt,sha256
|
|
|
39
39
|
cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.map,sha256=Lf93Q5-M2-Yc8NTq59fJ7floyiT9f-ayFYFKDvnVZqU,3161888
|
|
40
40
|
cognite/neat/app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg,sha256=EYf9q9JoVJ1L1np-XloeEZXCmaibzKmmpXCKn_44xzA,240334
|
|
41
41
|
cognite/neat/config.py,sha256=MbYOvlibOjODEPcCHNKwZHVjg9ft8kZSojnW4gQCiHQ,10116
|
|
42
|
-
cognite/neat/constants.py,sha256=
|
|
42
|
+
cognite/neat/constants.py,sha256=mhyB61-IKwREbq_8IL6Y0pNfZhCiceWlgwtWW42bkBE,913
|
|
43
43
|
cognite/neat/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
44
|
cognite/neat/graph/_shared.py,sha256=9QRETdm7hvqIeiHv_n1xi1DUq91Nq7oRRpnPKE0Pnag,181
|
|
45
45
|
cognite/neat/graph/_tracking/__init__.py,sha256=pYj7c-YAUIP4hvN-4mlWnwaeZFerzL9_gM-oZhex7cE,91
|
|
@@ -49,11 +49,11 @@ cognite/neat/graph/examples/Knowledge-Graph-Nordic44-dirty.xml,sha256=ujJip6XBs5
|
|
|
49
49
|
cognite/neat/graph/examples/Knowledge-Graph-Nordic44.xml,sha256=U2Ns-M4LRjT1fBkhmRj63ur7jDzlRtHK9yOLf_npZ_g,1437996
|
|
50
50
|
cognite/neat/graph/examples/__init__.py,sha256=yAjHVY3b5jOjmbW-iLbhvu7BG014TpGi3K4igkDqW5I,368
|
|
51
51
|
cognite/neat/graph/examples/skos-capturing-sheet-wind-topics.xlsx,sha256=CV_yK5ZSbYS_ktfIZUPD8Sevs47zpswLXQUDFkGE4Gw,45798
|
|
52
|
-
cognite/neat/graph/extractors/__init__.py,sha256=
|
|
52
|
+
cognite/neat/graph/extractors/__init__.py,sha256=timbuOI3YBPBFu1lY42KDAN5aDJ32gIseKsjT7e0fgU,1698
|
|
53
53
|
cognite/neat/graph/extractors/_base.py,sha256=8IWygpkQTwo0UOmbbwWVI7540_klTVdUVX2JjVPFRIs,498
|
|
54
54
|
cognite/neat/graph/extractors/_classic_cdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
55
|
cognite/neat/graph/extractors/_classic_cdf/_assets.py,sha256=xVqWC_lyqX5RKGfTxX0Gb96A0GAyM13d6YIjd1xEbpI,6524
|
|
56
|
-
cognite/neat/graph/extractors/_classic_cdf/_base.py,sha256=
|
|
56
|
+
cognite/neat/graph/extractors/_classic_cdf/_base.py,sha256=oLqYxNkAgYCZlAGMqfOVTDbRnouyf72m54d1BfcpeAA,4494
|
|
57
57
|
cognite/neat/graph/extractors/_classic_cdf/_events.py,sha256=8shnrQD9LZCrKPIt7xeU6ac0-lSkIwGe9KB0DdJ7Eik,5600
|
|
58
58
|
cognite/neat/graph/extractors/_classic_cdf/_files.py,sha256=wa2jzbpOj4BssVY7PbgdGymFZGSrvd1GZaRVN-JjOXQ,6588
|
|
59
59
|
cognite/neat/graph/extractors/_classic_cdf/_labels.py,sha256=Xvyv22jebq4s94Sl1h2SMEeBvOkoTIPujB9tczRgcDo,4359
|
|
@@ -61,15 +61,16 @@ cognite/neat/graph/extractors/_classic_cdf/_relationships.py,sha256=VxmwnZ_vN_P1
|
|
|
61
61
|
cognite/neat/graph/extractors/_classic_cdf/_sequences.py,sha256=sTtVPngffQw2fyvoRG1ABC2yFkepA6skFT1XdCzg4cU,5086
|
|
62
62
|
cognite/neat/graph/extractors/_classic_cdf/_timeseries.py,sha256=zmVf5pO-G4ro3elKt0sCTfTtLulkEFoEahLgP9J5kKE,6581
|
|
63
63
|
cognite/neat/graph/extractors/_dexpi.py,sha256=Q3whJpEi3uFMzJGAAeUfgRnAzz6ZHmtuEdVBWqsZsTM,9384
|
|
64
|
-
cognite/neat/graph/extractors/
|
|
64
|
+
cognite/neat/graph/extractors/_dms.py,sha256=NbqY1nrisn-dJq8_qeCatpgJwm6-cKFsTISDR5afdbU,6688
|
|
65
|
+
cognite/neat/graph/extractors/_mock_graph_generator.py,sha256=ES-7__o750BJFC9rNWt5HRO5M53iZuzv-8lBqLIXdC0,15365
|
|
65
66
|
cognite/neat/graph/extractors/_rdf_file.py,sha256=ialMCLv9WH5k6v1YMfozfcmAYhz8OVo9jVhsKMyQkDA,763
|
|
66
67
|
cognite/neat/graph/loaders/__init__.py,sha256=TbeJqifd16JLOglPVNOeb6pN_w060UYag50KquBM_r0,769
|
|
67
68
|
cognite/neat/graph/loaders/_base.py,sha256=5CpNsSj3WGCCjT2dC4GhnbArSD7DlWg_kXtze_ediLg,3614
|
|
68
69
|
cognite/neat/graph/loaders/_rdf2asset.py,sha256=Opq7BNAzrAYq-ffF2ayAqNVopyBDrayn0hj07KVFsyI,17504
|
|
69
|
-
cognite/neat/graph/loaders/_rdf2dms.py,sha256=
|
|
70
|
-
cognite/neat/graph/models.py,sha256=
|
|
70
|
+
cognite/neat/graph/loaders/_rdf2dms.py,sha256=bFfl3UKVwewGxAGAFlpPrJCKHq-aZdpYtDNYugIWq7g,14977
|
|
71
|
+
cognite/neat/graph/models.py,sha256=Z9aj825ZS_BCU6rwekyxKq7LL0QMh6i0DXGp7QQf_D4,182
|
|
71
72
|
cognite/neat/graph/queries/__init__.py,sha256=BgDd-037kvtWwAoGAy8eORVNMiZ5-E9sIV0txIpeaN4,50
|
|
72
|
-
cognite/neat/graph/queries/_base.py,sha256=
|
|
73
|
+
cognite/neat/graph/queries/_base.py,sha256=SCBPd4w5BkXU6vq1DWDqRtY4JDPxXm3zDIMRZzpV2-s,8404
|
|
73
74
|
cognite/neat/graph/queries/_construct.py,sha256=lDquCxjiaUzL3G48ZQffrGJMcqPkWVtCdkfatgPAUKI,7208
|
|
74
75
|
cognite/neat/graph/queries/_shared.py,sha256=Kk53TqJmwD2G-rxhLq_jJXYy8jvLsUAAWGJS5r9pOaY,5327
|
|
75
76
|
cognite/neat/graph/transformers/__init__.py,sha256=FMvlDEDJHrZL4Jb_H0AiJZO5uHXBCuLhB5HVDuinnBI,665
|
|
@@ -77,7 +78,7 @@ cognite/neat/graph/transformers/_base.py,sha256=b37Ek-9njuM5pTR_3XhnxCMrg_ip_2BM
|
|
|
77
78
|
cognite/neat/graph/transformers/_classic_cdf.py,sha256=6xX-OBSJT5DAQrTJ-nuhCfGNaSk5Iktxn-WIMfzEIqo,13189
|
|
78
79
|
cognite/neat/graph/transformers/_rdfpath.py,sha256=VLtGJvTPT5SWhV98fuGGt0pptTXfzOOQSNehypsPHug,1861
|
|
79
80
|
cognite/neat/issues/__init__.py,sha256=KkBEO-0Lg3vdvjrQtxKR6Wy2iV2mooc9utSO8-_9UuI,405
|
|
80
|
-
cognite/neat/issues/_base.py,sha256=
|
|
81
|
+
cognite/neat/issues/_base.py,sha256=g-_C2zIitewZLHQkV84aBRQJU2UnT_-pl98PFcfmNy0,15183
|
|
81
82
|
cognite/neat/issues/errors/__init__.py,sha256=t23ZnbWOZEhd77Ae_gpAxMPAIWOTbt7-wi6yeCmlGZE,2077
|
|
82
83
|
cognite/neat/issues/errors/_external.py,sha256=TUdihRyr5amdGSzSU49hWz7N7BSPCTVo7glKFNDrc5w,1583
|
|
83
84
|
cognite/neat/issues/errors/_general.py,sha256=Dtt4kEfNyj-CxpowsVVrq2eAwWEzx68JpPnS48QoY2U,787
|
|
@@ -85,11 +86,11 @@ cognite/neat/issues/errors/_properties.py,sha256=7To9RvOyBzspZrs4jG3kAYJ3bzmMjDl
|
|
|
85
86
|
cognite/neat/issues/errors/_resources.py,sha256=SqzHY4Mtm-JEYSKZO8x4Mh7vOVWMV3nOEu1JrUVdjIc,3863
|
|
86
87
|
cognite/neat/issues/errors/_workflow.py,sha256=nC3sxqlJSyi-kmo2ZAfxEH23ZuNRMC-oBcwQcl_2hkU,950
|
|
87
88
|
cognite/neat/issues/formatters.py,sha256=QCk41VLlpq-R9uaHpINYceZkIUoI9m4pwSq_yWPOmr8,3331
|
|
88
|
-
cognite/neat/issues/warnings/__init__.py,sha256
|
|
89
|
+
cognite/neat/issues/warnings/__init__.py,sha256=-PVXhGHmzMa35heEbBaheJyOUxYX520anfJJRTyi_nA,2330
|
|
89
90
|
cognite/neat/issues/warnings/_external.py,sha256=pauqW4VjKnfflUiz7J8EXtTdpXxCuCcE-EuzvXlPJuI,953
|
|
90
91
|
cognite/neat/issues/warnings/_general.py,sha256=yLfooeTwq57LQPbvvVgMZDBZpyrnalXHlA6bu0lSqFg,601
|
|
91
92
|
cognite/neat/issues/warnings/_models.py,sha256=HIhn5_hICqE0sFiosI7HiJnn3gyJPkQxOk1kXpAdG-E,3026
|
|
92
|
-
cognite/neat/issues/warnings/_properties.py,sha256=
|
|
93
|
+
cognite/neat/issues/warnings/_properties.py,sha256=zIXT1sezgyPPZgvytavP8bRRR9_DgvVM_awiDD-pdjM,1940
|
|
93
94
|
cognite/neat/issues/warnings/_resources.py,sha256=RpmZ-KLEyTTckfAG9IvQVslq8yjN9NPS9Q_Oa6Y3ps8,1788
|
|
94
95
|
cognite/neat/issues/warnings/user_modeling.py,sha256=RwslCYWLZzmoX7zX8O2Ha5pgghbhIOLQCZyev5CppO8,3602
|
|
95
96
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -110,7 +111,7 @@ cognite/neat/rules/exporters/_rules2yaml.py,sha256=2yAkU3b4P4UYdsCyAZn5K2OwphnRX
|
|
|
110
111
|
cognite/neat/rules/exporters/_validation.py,sha256=A0kyrIEu51ZXl47CXmO4ZOT0whO5iKNwMY-BwMc2scA,680
|
|
111
112
|
cognite/neat/rules/importers/__init__.py,sha256=z682_ktGKDjr52DIL6cPvOercZS6-TYD_ZDo-MGqtck,1207
|
|
112
113
|
cognite/neat/rules/importers/_base.py,sha256=G9apdRztiAdnzX3LyZ-SNaavXagvtta2BQXFqEOQw_g,2851
|
|
113
|
-
cognite/neat/rules/importers/_dms2rules.py,sha256=
|
|
114
|
+
cognite/neat/rules/importers/_dms2rules.py,sha256=us8I9drw_lBCn-n5-9ZZ-RTvbn-bCPWMno08UO2klDg,22895
|
|
114
115
|
cognite/neat/rules/importers/_dtdl2rules/__init__.py,sha256=CNR-sUihs2mnR1bPMKs3j3L4ds3vFTsrl6YycExZTfU,68
|
|
115
116
|
cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py,sha256=wW4saKva61Q_i17guY0dc4OseJDQfqHy_QZBtm0OD6g,12134
|
|
116
117
|
cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py,sha256=WklOdKq1p-w-j3bloDGX-eJIltyD_1mwo4aZbKY9UG4,11904
|
|
@@ -122,7 +123,7 @@ cognite/neat/rules/importers/_rdf/_imf2rules/_imf2classes.py,sha256=bXlzybKhiCmh
|
|
|
122
123
|
cognite/neat/rules/importers/_rdf/_imf2rules/_imf2metadata.py,sha256=AHRyyt25Av_MS4iWFw49MCabz49Ng1mDGyLKXufisFM,957
|
|
123
124
|
cognite/neat/rules/importers/_rdf/_imf2rules/_imf2properties.py,sha256=aF7Jy29Jo2hm8rybRDyBxoLGycOx3UsM6Gq-ztBF41Y,6170
|
|
124
125
|
cognite/neat/rules/importers/_rdf/_imf2rules/_imf2rules.py,sha256=YFLXYjzsKCGL4rxE8gllpJ1LKeVEkNwXscE3aCyxlYs,6289
|
|
125
|
-
cognite/neat/rules/importers/_rdf/_inference2rules.py,sha256=
|
|
126
|
+
cognite/neat/rules/importers/_rdf/_inference2rules.py,sha256=ArD7zwiSbU1YXxycJ03F3Zju26XNUbsHtsR9PtlH5N8,12663
|
|
126
127
|
cognite/neat/rules/importers/_rdf/_owl2rules/__init__.py,sha256=tdGcrgtozdQyST-pTlxIa4cLBNTLvtk1nNYR4vOdFSw,63
|
|
127
128
|
cognite/neat/rules/importers/_rdf/_owl2rules/_owl2classes.py,sha256=VLlr2UHAia0xWaeg3tKJ3N0sq_nYur3UqcOXgjMYxzg,1934
|
|
128
129
|
cognite/neat/rules/importers/_rdf/_owl2rules/_owl2metadata.py,sha256=3eTXm0irYJcjMV4H57xblP_iaNO_T0JErQuAYZfNaFA,2659
|
|
@@ -143,7 +144,7 @@ cognite/neat/rules/models/asset/_serializer.py,sha256=ixqRf9qEzvChgysRaDX4g_vHVD
|
|
|
143
144
|
cognite/neat/rules/models/asset/_validation.py,sha256=3goorodISq_mlyXroaivcMOZ-QV8sd27IK9-iGKnQ28,2014
|
|
144
145
|
cognite/neat/rules/models/data_types.py,sha256=jTYsWqQPuvwHytInRU0Y2TGF4aVBF83v0vp_SH9KgLA,9722
|
|
145
146
|
cognite/neat/rules/models/dms/__init__.py,sha256=CUqUlVjz4yZX_-61F-2ofSoV7N9MlSYx2N7vM-omp7E,640
|
|
146
|
-
cognite/neat/rules/models/dms/_exporter.py,sha256=
|
|
147
|
+
cognite/neat/rules/models/dms/_exporter.py,sha256=4XiFCeXZOZuj5Ke1E-_rQJvPIcyRl7lIb2dHCfkYS4M,28126
|
|
147
148
|
cognite/neat/rules/models/dms/_rules.py,sha256=iwCQx0MVQVe1R0bFIIdDD5unyuzQ7tIZDQM7NmdbJp8,14871
|
|
148
149
|
cognite/neat/rules/models/dms/_rules_input.py,sha256=v5-zlb4VJi5Q610rnPLU1aHKzXmGwoUTrDzAkJFfEQY,10911
|
|
149
150
|
cognite/neat/rules/models/dms/_schema.py,sha256=lc6Q0EUchOAUSTRiJnWc6UPBz7LjCW5NEvIGwNakcSI,50724
|
|
@@ -164,12 +165,12 @@ cognite/neat/rules/models/information/_serializer.py,sha256=yti9I_xJruxrib66YIBI
|
|
|
164
165
|
cognite/neat/rules/models/information/_validation.py,sha256=Fa5S-rQozSCkIDpS4dPQn7U0lM71DOecAMCqL8K8Uag,9230
|
|
165
166
|
cognite/neat/rules/transformers/__init__.py,sha256=Iun5-3uDmzUzcO4IFneJ453PWAx6F_c-5LhkvrIrSc0,666
|
|
166
167
|
cognite/neat/rules/transformers/_base.py,sha256=FABG_8Xg_LUZPwVLQmKvxlcIDtI5phGLpEGpxNcJWNM,3269
|
|
167
|
-
cognite/neat/rules/transformers/_converters.py,sha256=
|
|
168
|
+
cognite/neat/rules/transformers/_converters.py,sha256=8qvgAbW4U7gcYEYkgFkrvOKE1P-PwNjg-nOIvOgbhnE,22763
|
|
168
169
|
cognite/neat/rules/transformers/_map_onto.py,sha256=eXPhontrcJdRm2ILopwkFoPcwfM8L-BNv-CapL30klg,4824
|
|
169
170
|
cognite/neat/rules/transformers/_pipelines.py,sha256=of3NJ4gsLeKr3NiTfBMQVl1J5b2IwI5JWm8FP7oQ3B4,2438
|
|
170
171
|
cognite/neat/rules/transformers/_verification.py,sha256=rPSeDKkpe-hCJ0iiBx6yycvSANwnCS78PUFTDYgmNcA,4448
|
|
171
172
|
cognite/neat/store/__init__.py,sha256=G-VG_YwfRt1kuPao07PDJyZ3w_0-eguzLUM13n-Z_RA,64
|
|
172
|
-
cognite/neat/store/_base.py,sha256=
|
|
173
|
+
cognite/neat/store/_base.py,sha256=WcwVxRo7UpSNUJ221yq26_XtaeX6xW647qkf9xG8aK0,12471
|
|
173
174
|
cognite/neat/store/_provenance.py,sha256=sniVJhLmvj0ulKhoUZzFLwjAsp7cQyRPxunZtLmMW4A,3902
|
|
174
175
|
cognite/neat/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
175
176
|
cognite/neat/utils/auth.py,sha256=k0sEfTpK_bamMjAkj7jN6n9yta8TaqHTFkZUjUgpwik,12770
|
|
@@ -203,8 +204,8 @@ cognite/neat/workflows/steps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
|
203
204
|
cognite/neat/workflows/steps/data_contracts.py,sha256=RobxctwAOxdOYdPf6jEkMj9KSTJjj4Cf__oOr5Ge2rs,2467
|
|
204
205
|
cognite/neat/workflows/steps/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
205
206
|
cognite/neat/workflows/steps/lib/current/__init__.py,sha256=c22IznGdCSNCpXCi_yonlbbywJE1uj6bfVCv0X2LYeE,225
|
|
206
|
-
cognite/neat/workflows/steps/lib/current/graph_extractor.py,sha256=
|
|
207
|
-
cognite/neat/workflows/steps/lib/current/graph_loader.py,sha256=
|
|
207
|
+
cognite/neat/workflows/steps/lib/current/graph_extractor.py,sha256=3nP-BoXbDA8oobVak7KLvMg8-0-5sQrXrPQNIXNGI1U,4585
|
|
208
|
+
cognite/neat/workflows/steps/lib/current/graph_loader.py,sha256=TUgLPExa9OuaDboGFBTRReigkhwFturMoJTMwkDT4s4,1689
|
|
208
209
|
cognite/neat/workflows/steps/lib/current/graph_store.py,sha256=UydcYMoF2d2m8gOKAtlul8yCfKS3jFJJCTF2psM2flg,1582
|
|
209
210
|
cognite/neat/workflows/steps/lib/current/rules_exporter.py,sha256=qLMlB3MqTZhD5q9A8YypksUQ7kOhwi6qGnNXdky_G9w,27752
|
|
210
211
|
cognite/neat/workflows/steps/lib/current/rules_importer.py,sha256=ytyIDg9_2AZWxMvH1rE044QI8jab5kdHNR-FKyKBaXE,17978
|
|
@@ -216,8 +217,8 @@ cognite/neat/workflows/steps_registry.py,sha256=FjMsFBlFFy82ABUzDnWoFidYODV3pp3c
|
|
|
216
217
|
cognite/neat/workflows/tasks.py,sha256=dqlJwKAb0jlkl7abbY8RRz3m7MT4SK8-7cntMWkOYjw,788
|
|
217
218
|
cognite/neat/workflows/triggers.py,sha256=_BLNplzoz0iic367u1mhHMHiUrCwP-SLK6_CZzfODX0,7071
|
|
218
219
|
cognite/neat/workflows/utils.py,sha256=gKdy3RLG7ctRhbCRwaDIWpL9Mi98zm56-d4jfHDqP1E,453
|
|
219
|
-
cognite_neat-0.
|
|
220
|
-
cognite_neat-0.
|
|
221
|
-
cognite_neat-0.
|
|
222
|
-
cognite_neat-0.
|
|
223
|
-
cognite_neat-0.
|
|
220
|
+
cognite_neat-0.90.1.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
|
|
221
|
+
cognite_neat-0.90.1.dist-info/METADATA,sha256=fesf1bMUebWMM4l-lPzQ92ZLM67NPT-Xdyb0y1AKNVU,9441
|
|
222
|
+
cognite_neat-0.90.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
223
|
+
cognite_neat-0.90.1.dist-info/entry_points.txt,sha256=61FPqiWb25vbqB0KI7znG8nsg_ibLHBvTjYnkPvNFso,50
|
|
224
|
+
cognite_neat-0.90.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|