cognite-neat 0.122.1__py3-none-any.whl → 0.122.2__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/importers/_dms2data_model.py +2 -2
- cognite/neat/core/_data_model/transformers/_converters.py +1 -1
- cognite/neat/core/_data_model/transformers/_mapping.py +1 -1
- cognite/neat/core/_data_model/transformers/_verification.py +1 -1
- cognite/neat/core/_instances/loaders/__init__.py +2 -1
- cognite/neat/core/_instances/loaders/_base.py +4 -10
- cognite/neat/core/_instances/loaders/_rdf2dms.py +18 -131
- cognite/neat/core/_instances/loaders/_rdf_to_instance_space.py +249 -0
- cognite/neat/core/_instances/queries/_select.py +12 -0
- cognite/neat/session/_base.py +2 -2
- cognite/neat/session/_drop.py +1 -1
- cognite/neat/session/_fix.py +1 -1
- cognite/neat/session/_mapping.py +1 -1
- cognite/neat/session/_prepare.py +3 -3
- cognite/neat/session/_read.py +10 -10
- cognite/neat/session/_set.py +1 -1
- cognite/neat/session/_state.py +2 -2
- cognite/neat/session/_subset.py +2 -2
- cognite/neat/session/_template.py +3 -3
- cognite/neat/session/_to.py +21 -14
- {cognite_neat-0.122.1.dist-info → cognite_neat-0.122.2.dist-info}/METADATA +1 -1
- {cognite_neat-0.122.1.dist-info → cognite_neat-0.122.2.dist-info}/RECORD +25 -24
- {cognite_neat-0.122.1.dist-info → cognite_neat-0.122.2.dist-info}/WHEEL +0 -0
- {cognite_neat-0.122.1.dist-info → cognite_neat-0.122.2.dist-info}/licenses/LICENSE +0 -0
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.122.
|
|
1
|
+
__version__ = "0.122.2"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -269,14 +269,14 @@ class DMSImporter(BaseImporter[UnverifiedPhysicalDataModel]):
|
|
|
269
269
|
|
|
270
270
|
model = self.schema.data_model
|
|
271
271
|
|
|
272
|
-
user_data_model = self.
|
|
272
|
+
user_data_model = self._create_data_model_components(model, self.schema, self.metadata)
|
|
273
273
|
|
|
274
274
|
self.issue_list.trigger_warnings()
|
|
275
275
|
if self.issue_list.has_errors:
|
|
276
276
|
raise MultiValueError(self.issue_list.errors)
|
|
277
277
|
return ImportedDataModel(user_data_model, {})
|
|
278
278
|
|
|
279
|
-
def
|
|
279
|
+
def _create_data_model_components(
|
|
280
280
|
self,
|
|
281
281
|
data_model: dm.DataModelApply,
|
|
282
282
|
schema: DMSSchema,
|
|
@@ -2346,7 +2346,7 @@ class AddCogniteProperties(
|
|
|
2346
2346
|
) -> ImportedDataModel[UnverifiedConceptualDataModel]:
|
|
2347
2347
|
input_ = data_model.unverified_data_model
|
|
2348
2348
|
if input_ is None:
|
|
2349
|
-
raise NeatValueError("
|
|
2349
|
+
raise NeatValueError("Data model read failed. Cannot add cognite properties to None data_model.")
|
|
2350
2350
|
|
|
2351
2351
|
default_space = input_.metadata.space
|
|
2352
2352
|
default_version = input_.metadata.version
|
|
@@ -29,7 +29,7 @@ from ._base import VerifiedDataModelTransformer
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class MapOntoTransformers(VerifiedDataModelTransformer[PhysicalDataModel, PhysicalDataModel], ABC):
|
|
32
|
-
"""Base class for transformers that map one
|
|
32
|
+
"""Base class for transformers that map one data model onto another."""
|
|
33
33
|
|
|
34
34
|
...
|
|
35
35
|
|
|
@@ -54,7 +54,7 @@ class VerificationTransformer(DataModelTransformer[T_ImportedUnverifiedDataModel
|
|
|
54
54
|
elif issubclass(validation_cls, ConceptualValidation):
|
|
55
55
|
validation_issues = ConceptualValidation(verified_data_model, data_model.context).validate() # type: ignore[arg-type]
|
|
56
56
|
else:
|
|
57
|
-
raise NeatValueError("Unsupported
|
|
57
|
+
raise NeatValueError("Unsupported data model type")
|
|
58
58
|
issues.extend(validation_issues)
|
|
59
59
|
|
|
60
60
|
# Raise issues which is expected to be handled outside of this method
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from ._base import BaseLoader, CDFLoader
|
|
2
2
|
from ._rdf2dms import DMSLoader
|
|
3
|
+
from ._rdf_to_instance_space import InstanceSpaceLoader
|
|
3
4
|
|
|
4
|
-
__all__ = ["BaseLoader", "CDFLoader", "DMSLoader"]
|
|
5
|
+
__all__ = ["BaseLoader", "CDFLoader", "DMSLoader", "InstanceSpaceLoader"]
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def _repr_html_() -> str:
|
|
@@ -3,12 +3,11 @@ from collections.abc import Hashable, Iterable
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import ClassVar, Generic, TypeVar
|
|
5
5
|
|
|
6
|
-
from cognite.client import CogniteClient
|
|
7
6
|
from cognite.client.data_classes.capabilities import Capability
|
|
8
7
|
|
|
8
|
+
from cognite.neat.core._client import NeatClient
|
|
9
9
|
from cognite.neat.core._issues import IssueList, NeatIssue
|
|
10
10
|
from cognite.neat.core._issues.errors import AuthorizationError
|
|
11
|
-
from cognite.neat.core._store import NeatInstanceStore
|
|
12
11
|
from cognite.neat.core._utils.auxiliary import class_html_doc
|
|
13
12
|
from cognite.neat.core._utils.upload import UploadResult, UploadResultList
|
|
14
13
|
|
|
@@ -29,9 +28,6 @@ class BaseLoader(ABC, Generic[T_Output]):
|
|
|
29
28
|
_new_line = "\n"
|
|
30
29
|
_encoding = "utf-8"
|
|
31
30
|
|
|
32
|
-
def __init__(self, instance_store: NeatInstanceStore):
|
|
33
|
-
self.instance_store = instance_store
|
|
34
|
-
|
|
35
31
|
@abstractmethod
|
|
36
32
|
def write_to_file(self, filepath: Path) -> None:
|
|
37
33
|
raise NotImplementedError
|
|
@@ -59,9 +55,7 @@ class BaseLoader(ABC, Generic[T_Output]):
|
|
|
59
55
|
class CDFLoader(BaseLoader[T_Output]):
|
|
60
56
|
_UPLOAD_BATCH_SIZE: ClassVar[int] = 1000
|
|
61
57
|
|
|
62
|
-
def load_into_cdf(
|
|
63
|
-
self, client: CogniteClient, dry_run: bool = False, check_client: bool = True
|
|
64
|
-
) -> UploadResultList:
|
|
58
|
+
def load_into_cdf(self, client: NeatClient, dry_run: bool = False, check_client: bool = True) -> UploadResultList:
|
|
65
59
|
upload_result_by_name: dict[str, UploadResult] = {}
|
|
66
60
|
for upload_result in self.load_into_cdf_iterable(client, dry_run, check_client):
|
|
67
61
|
if last_result := upload_result_by_name.get(upload_result.name):
|
|
@@ -72,7 +66,7 @@ class CDFLoader(BaseLoader[T_Output]):
|
|
|
72
66
|
return UploadResultList(upload_result_by_name.values())
|
|
73
67
|
|
|
74
68
|
def load_into_cdf_iterable(
|
|
75
|
-
self, client:
|
|
69
|
+
self, client: NeatClient, dry_run: bool = False, check_client: bool = True
|
|
76
70
|
) -> Iterable[UploadResult]:
|
|
77
71
|
if check_client:
|
|
78
72
|
missing_capabilities = client.iam.verify_capabilities(self._get_required_capabilities())
|
|
@@ -113,7 +107,7 @@ class CDFLoader(BaseLoader[T_Output]):
|
|
|
113
107
|
@abstractmethod
|
|
114
108
|
def _upload_to_cdf(
|
|
115
109
|
self,
|
|
116
|
-
client:
|
|
110
|
+
client: NeatClient,
|
|
117
111
|
items: list[T_Output],
|
|
118
112
|
dry_run: bool,
|
|
119
113
|
read_issues: IssueList,
|
|
@@ -6,7 +6,7 @@ from collections import defaultdict
|
|
|
6
6
|
from collections.abc import Iterable, Sequence
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Any, Literal, cast, get_args
|
|
9
|
+
from typing import Any, Literal, cast, get_args
|
|
10
10
|
|
|
11
11
|
import yaml
|
|
12
12
|
from cognite.client import CogniteClient
|
|
@@ -39,13 +39,11 @@ from cognite.neat.core._data_model.models.data_types import (
|
|
|
39
39
|
)
|
|
40
40
|
from cognite.neat.core._issues import IssueList, NeatError, NeatIssue, catch_issues
|
|
41
41
|
from cognite.neat.core._issues.errors import (
|
|
42
|
-
AuthorizationError,
|
|
43
42
|
ResourceCreationError,
|
|
44
43
|
ResourceDuplicatedError,
|
|
45
44
|
ResourceNotFoundError,
|
|
46
45
|
)
|
|
47
46
|
from cognite.neat.core._issues.warnings import (
|
|
48
|
-
NeatValueWarning,
|
|
49
47
|
PropertyDirectRelationLimitWarning,
|
|
50
48
|
PropertyMultipleValueWarning,
|
|
51
49
|
PropertyTypeNotSupportedWarning,
|
|
@@ -58,11 +56,8 @@ from cognite.neat.core._utils.collection_ import (
|
|
|
58
56
|
iterate_progress_bar_if_above_config_threshold,
|
|
59
57
|
)
|
|
60
58
|
from cognite.neat.core._utils.rdf_ import (
|
|
61
|
-
namespace_as_space,
|
|
62
59
|
remove_namespace_from_uri,
|
|
63
|
-
split_uri,
|
|
64
60
|
)
|
|
65
|
-
from cognite.neat.core._utils.text import NamingStandardization
|
|
66
61
|
from cognite.neat.core._utils.upload import UploadResult
|
|
67
62
|
|
|
68
63
|
from ._base import _END_OF_CLASS, _START_OF_CLASS, CDFLoader
|
|
@@ -104,14 +99,10 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
104
99
|
conceptual_data_model (ConceptualDataModel): Conceptual data model,
|
|
105
100
|
used to look+up the instances in the store.
|
|
106
101
|
instance_store (NeatInstanceStore): The instance store to load the instances from.
|
|
107
|
-
instance_space (str): The instance space to load the data into.
|
|
108
102
|
create_issues (Sequence[NeatIssue] | None): A list of issues that occurred during reading. Defaults to None.
|
|
109
103
|
client (NeatClient | None): This is used to lookup containers such that the loader
|
|
110
104
|
creates instances in accordance with required constraints. Defaults to None.
|
|
111
105
|
unquote_external_ids (bool): If True, the loader will unquote external ids before creating the instances.
|
|
112
|
-
neat_prefix_by_predicate_uri (dict[URIRef, str] | None): A dictionary that maps a predicate URIRef to a
|
|
113
|
-
prefix that Neat added to the object upon extraction. This is used to remove the prefix from the
|
|
114
|
-
object before creating the instance.
|
|
115
106
|
"""
|
|
116
107
|
|
|
117
108
|
def __init__(
|
|
@@ -119,24 +110,17 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
119
110
|
physical_data_model: PhysicalDataModel,
|
|
120
111
|
conceptual_data_model: ConceptualDataModel,
|
|
121
112
|
instance_store: NeatInstanceStore,
|
|
122
|
-
|
|
123
|
-
space_property: str | None = None,
|
|
124
|
-
use_source_space: bool = False,
|
|
113
|
+
space_by_instance_uri: dict[URIRef, str],
|
|
125
114
|
client: NeatClient | None = None,
|
|
126
115
|
create_issues: Sequence[NeatIssue] | None = None,
|
|
127
116
|
unquote_external_ids: bool = False,
|
|
128
|
-
neat_prefix_by_predicate_uri: dict[URIRef, str] | None = None,
|
|
129
117
|
neat_prefix_by_type_uri: dict[URIRef, str] | None = None,
|
|
130
118
|
):
|
|
131
|
-
|
|
119
|
+
self.instance_store = instance_store
|
|
132
120
|
self.physical_data_model = physical_data_model
|
|
133
121
|
self.conceptual_data_model = conceptual_data_model
|
|
134
|
-
self.neat_prefix_by_predicate_uri = neat_prefix_by_predicate_uri or {}
|
|
135
122
|
self.neat_prefix_by_type_uri = neat_prefix_by_type_uri or {}
|
|
136
|
-
self.
|
|
137
|
-
self._space_property = space_property
|
|
138
|
-
self._use_source_space = use_source_space
|
|
139
|
-
self._space_by_instance_uri: dict[URIRef, str] = defaultdict(lambda: instance_space)
|
|
123
|
+
self._space_by_instance_uri = space_by_instance_uri
|
|
140
124
|
self._external_id_by_uri: dict[URIRef, str] = {}
|
|
141
125
|
self._issues = IssueList(create_issues or [])
|
|
142
126
|
self._client = client
|
|
@@ -172,16 +156,6 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
172
156
|
return
|
|
173
157
|
view_iterations, issues = self._create_view_iterations()
|
|
174
158
|
yield from issues
|
|
175
|
-
if self._space_property:
|
|
176
|
-
yield from self._lookup_space_by_uri(view_iterations, stop_on_exception)
|
|
177
|
-
|
|
178
|
-
if self._client:
|
|
179
|
-
space_creation = self._create_instance_space_if_not_exists()
|
|
180
|
-
yield from space_creation.warnings
|
|
181
|
-
if space_creation.has_errors and stop_on_exception:
|
|
182
|
-
raise space_creation.as_exception()
|
|
183
|
-
yield from space_creation.errors
|
|
184
|
-
|
|
185
159
|
if self.neat_prefix_by_type_uri:
|
|
186
160
|
self._lookup_identifier_by_uri()
|
|
187
161
|
|
|
@@ -280,46 +254,6 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
280
254
|
view_iterations[view_id] = _ViewIterator(view_id, count, query)
|
|
281
255
|
return view_iterations
|
|
282
256
|
|
|
283
|
-
def _lookup_space_by_uri(self, view_iterations: list[_ViewIterator], stop_on_exception: bool = False) -> IssueList:
|
|
284
|
-
issues = IssueList()
|
|
285
|
-
if self._space_property is None:
|
|
286
|
-
return issues
|
|
287
|
-
total = sum(it.instance_count for it in view_iterations)
|
|
288
|
-
properties_by_uriref = self.instance_store.queries.select.properties()
|
|
289
|
-
space_property_uri = next((k for k, v in properties_by_uriref.items() if v == self._space_property), None)
|
|
290
|
-
if space_property_uri is None:
|
|
291
|
-
error: ResourceNotFoundError[str, str] = ResourceNotFoundError(
|
|
292
|
-
self._space_property,
|
|
293
|
-
"property",
|
|
294
|
-
more=f"Could not find the {self._space_property} in the graph.",
|
|
295
|
-
)
|
|
296
|
-
if stop_on_exception:
|
|
297
|
-
raise error
|
|
298
|
-
issues.append(error)
|
|
299
|
-
return issues
|
|
300
|
-
|
|
301
|
-
instance_iterable = self.instance_store.queries.select.list_instances_ids_by_space(space_property_uri)
|
|
302
|
-
instance_iterable = iterate_progress_bar_if_above_config_threshold(
|
|
303
|
-
instance_iterable, total, f"Looking up spaces for {total} instances..."
|
|
304
|
-
)
|
|
305
|
-
neat_prefix = self.neat_prefix_by_predicate_uri.get(space_property_uri)
|
|
306
|
-
warned_spaces: set[str] = set()
|
|
307
|
-
for instance, space in instance_iterable:
|
|
308
|
-
if neat_prefix:
|
|
309
|
-
space = space.removeprefix(neat_prefix)
|
|
310
|
-
|
|
311
|
-
clean_space = NamingStandardization.standardize_space_str(space)
|
|
312
|
-
if clean_space != space and space not in warned_spaces:
|
|
313
|
-
issues.append(
|
|
314
|
-
NeatValueWarning(
|
|
315
|
-
f"Invalid space in property {self._space_property}: {space}. Fixed to {clean_space}"
|
|
316
|
-
)
|
|
317
|
-
)
|
|
318
|
-
warned_spaces.add(space)
|
|
319
|
-
|
|
320
|
-
self._space_by_instance_uri[instance] = clean_space
|
|
321
|
-
return issues
|
|
322
|
-
|
|
323
257
|
def _lookup_identifier_by_uri(self) -> None:
|
|
324
258
|
if not self.neat_prefix_by_type_uri:
|
|
325
259
|
return
|
|
@@ -343,20 +277,6 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
343
277
|
if len(uris) == 1:
|
|
344
278
|
self._external_id_by_uri[uris[0]] = identifier
|
|
345
279
|
|
|
346
|
-
def _create_instance_space_if_not_exists(self) -> IssueList:
|
|
347
|
-
issues = IssueList()
|
|
348
|
-
if not self._client:
|
|
349
|
-
return issues
|
|
350
|
-
|
|
351
|
-
instance_spaces = set(self._space_by_instance_uri.values()) - {self._instance_space}
|
|
352
|
-
existing_spaces = {space.space for space in self._client.data_modeling.spaces.retrieve(list(instance_spaces))}
|
|
353
|
-
if missing_spaces := (instance_spaces - existing_spaces):
|
|
354
|
-
try:
|
|
355
|
-
self._client.data_modeling.spaces.apply([dm.SpaceApply(space=space) for space in missing_spaces])
|
|
356
|
-
except CogniteAPIError as e:
|
|
357
|
-
issues.append(AuthorizationError(f"Creating {len(missing_spaces)} instance spaces.", str(e)))
|
|
358
|
-
return issues
|
|
359
|
-
|
|
360
280
|
def _create_projection(self, view: dm.View) -> tuple[_Projection, IssueList]:
|
|
361
281
|
issues = IssueList()
|
|
362
282
|
field_definitions: dict[str, tuple[type, Any]] = {}
|
|
@@ -473,12 +393,10 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
473
393
|
)
|
|
474
394
|
value = value[:limit]
|
|
475
395
|
|
|
476
|
-
ids = (self._create_instance_id(v
|
|
396
|
+
ids = (self._create_instance_id(v) for v in value)
|
|
477
397
|
return [id_.dump(camel_case=True, include_instance_type=False) for id_ in ids]
|
|
478
398
|
elif value:
|
|
479
|
-
return self._create_instance_id(value[0],
|
|
480
|
-
camel_case=True, include_instance_type=False
|
|
481
|
-
)
|
|
399
|
+
return self._create_instance_id(value[0]).dump(camel_case=True, include_instance_type=False)
|
|
482
400
|
return {}
|
|
483
401
|
|
|
484
402
|
validators["parse_direct_relation"] = field_validator(*direct_relation_by_property.keys(), mode="before")( # type: ignore[assignment]
|
|
@@ -518,7 +436,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
518
436
|
projection: _Projection,
|
|
519
437
|
stop_on_exception: Literal[True, False] = False,
|
|
520
438
|
) -> Iterable[dm.InstanceApply | NeatIssue]:
|
|
521
|
-
instance_id = self._create_instance_id(instance_uri
|
|
439
|
+
instance_id = self._create_instance_id(instance_uri)
|
|
522
440
|
if not isinstance(instance_id, InstanceId):
|
|
523
441
|
yield instance_id
|
|
524
442
|
return
|
|
@@ -567,8 +485,8 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
567
485
|
return
|
|
568
486
|
|
|
569
487
|
if start_node and end_node:
|
|
570
|
-
start = self._create_instance_id(start_node
|
|
571
|
-
end = self._create_instance_id(end_node
|
|
488
|
+
start = self._create_instance_id(start_node)
|
|
489
|
+
end = self._create_instance_id(end_node)
|
|
572
490
|
if isinstance(start, NeatError):
|
|
573
491
|
yield start
|
|
574
492
|
if isinstance(end, NeatError):
|
|
@@ -594,7 +512,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
594
512
|
),
|
|
595
513
|
sources=sources,
|
|
596
514
|
)
|
|
597
|
-
yield from self._create_edges_without_properties(space, external_id, properties, projection
|
|
515
|
+
yield from self._create_edges_without_properties(space, external_id, properties, projection)
|
|
598
516
|
|
|
599
517
|
def _create_edges_without_properties(
|
|
600
518
|
self,
|
|
@@ -602,7 +520,6 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
602
520
|
identifier: str,
|
|
603
521
|
properties: dict[str | InstanceType, list[str] | list[URIRef]],
|
|
604
522
|
projection: _Projection,
|
|
605
|
-
stop_on_exception: Literal[True, False],
|
|
606
523
|
) -> Iterable[dm.EdgeApply | NeatIssue]:
|
|
607
524
|
for predicate, values in properties.items():
|
|
608
525
|
if predicate in projection.edge_by_type:
|
|
@@ -620,10 +537,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
620
537
|
yield error
|
|
621
538
|
continue
|
|
622
539
|
for target in values:
|
|
623
|
-
target_id = self._create_instance_id(
|
|
624
|
-
if not isinstance(target_id, InstanceId):
|
|
625
|
-
yield target_id
|
|
626
|
-
continue
|
|
540
|
+
target_id = self._create_instance_id(cast(URIRef, target))
|
|
627
541
|
if isinstance(target, URIRef):
|
|
628
542
|
target = remove_namespace_from_uri(target)
|
|
629
543
|
external_id = f"{identifier}.{prop_id}.{target}"
|
|
@@ -656,43 +570,16 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
656
570
|
return start_node, end_node # type: ignore[return-value]
|
|
657
571
|
return None, None
|
|
658
572
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
@overload
|
|
665
|
-
def _create_instance_id(
|
|
666
|
-
self, uri: URIRef, instance_type: str, stop_on_exception: Literal[True] = True
|
|
667
|
-
) -> InstanceId: ...
|
|
668
|
-
|
|
669
|
-
def _create_instance_id(
|
|
670
|
-
self, uri: URIRef, instance_type: str, stop_on_exception: bool = False
|
|
671
|
-
) -> InstanceId | NeatError:
|
|
672
|
-
space: str | None = None
|
|
673
|
-
external_id: str | None = None
|
|
674
|
-
error: NeatError | None = None
|
|
675
|
-
if self._use_source_space:
|
|
676
|
-
namespace, external_id = split_uri(uri)
|
|
677
|
-
space = namespace_as_space(namespace)
|
|
678
|
-
if space is None:
|
|
679
|
-
error = ResourceCreationError(uri, instance_type, f"Could not find space for {uri!s}.")
|
|
573
|
+
def _create_instance_id(self, uri: URIRef) -> InstanceId:
|
|
574
|
+
space = self._space_by_instance_uri[uri]
|
|
575
|
+
if uri in self._external_id_by_uri:
|
|
576
|
+
external_id = self._external_id_by_uri[uri]
|
|
680
577
|
else:
|
|
681
|
-
|
|
682
|
-
if uri in self._external_id_by_uri:
|
|
683
|
-
external_id = self._external_id_by_uri[uri]
|
|
684
|
-
else:
|
|
685
|
-
external_id = remove_namespace_from_uri(uri)
|
|
578
|
+
external_id = remove_namespace_from_uri(uri)
|
|
686
579
|
|
|
687
580
|
if external_id and self._unquote_external_ids:
|
|
688
581
|
external_id = urllib.parse.unquote(external_id)
|
|
689
|
-
|
|
690
|
-
return InstanceId(space, external_id)
|
|
691
|
-
if error is None:
|
|
692
|
-
raise ValueError(f"Bug in neat. Failed to create instance ID and determine error for {uri!r}")
|
|
693
|
-
if stop_on_exception:
|
|
694
|
-
raise error
|
|
695
|
-
return error
|
|
582
|
+
return InstanceId(space, external_id)
|
|
696
583
|
|
|
697
584
|
def _get_required_capabilities(self) -> list[Capability]:
|
|
698
585
|
return [
|
|
@@ -702,7 +589,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
|
|
|
702
589
|
DataModelInstancesAcl.Action.Write_Properties,
|
|
703
590
|
DataModelInstancesAcl.Action.Read,
|
|
704
591
|
],
|
|
705
|
-
scope=DataModelInstancesAcl.Scope.SpaceID(
|
|
592
|
+
scope=DataModelInstancesAcl.Scope.SpaceID(sorted(set(self._space_by_instance_uri.values()))),
|
|
706
593
|
)
|
|
707
594
|
]
|
|
708
595
|
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
import json
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import cast
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
from cognite.client import data_modeling as dm
|
|
10
|
+
from cognite.client.data_classes.capabilities import Capability, DataModelsAcl
|
|
11
|
+
from rdflib import URIRef
|
|
12
|
+
|
|
13
|
+
from cognite.neat.core._client import NeatClient
|
|
14
|
+
from cognite.neat.core._client._api.data_modeling_loaders import MultiCogniteAPIError
|
|
15
|
+
from cognite.neat.core._constants import COGNITE_SPACES
|
|
16
|
+
from cognite.neat.core._issues import IssueList, NeatIssue
|
|
17
|
+
from cognite.neat.core._issues.errors import ResourceCreationError, ResourceNotFoundError
|
|
18
|
+
from cognite.neat.core._issues.warnings import NeatValueWarning
|
|
19
|
+
from cognite.neat.core._store import NeatInstanceStore
|
|
20
|
+
from cognite.neat.core._utils.collection_ import iterate_progress_bar_if_above_config_threshold
|
|
21
|
+
from cognite.neat.core._utils.rdf_ import namespace_as_space, split_uri
|
|
22
|
+
from cognite.neat.core._utils.text import NamingStandardization
|
|
23
|
+
from cognite.neat.core._utils.upload import UploadResult
|
|
24
|
+
|
|
25
|
+
from ._base import _END_OF_CLASS, _START_OF_CLASS, CDFLoader
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class InstanceSpaceLoader(CDFLoader[dm.SpaceApply]):
|
|
29
|
+
"""Loads Instance Space into Cognite Data Fusion (CDF).
|
|
30
|
+
|
|
31
|
+
There are three ways to determine the space for each instance:
|
|
32
|
+
1. If `instance_space` is provided, all instances will be assigned to that space, i.e., the space
|
|
33
|
+
is constant for all instances.
|
|
34
|
+
(If not it is set based on the triples (subject, predicate, object) in the graph store.)
|
|
35
|
+
2. If `space_property` is provided, this is the predicate and the space is set to the object. The `instance_space`
|
|
36
|
+
is used as a fallback if the object is not a valid space.
|
|
37
|
+
3. If `use_source_space` is set to True, the instances are assumed to be extracted from CDF and the space is part
|
|
38
|
+
of the subject.
|
|
39
|
+
|
|
40
|
+
This class exposes the `space_by_instance_uri` property used by the DMSLoader to lookup space for each instance URI.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
graph_store (NeatInstanceStore): The graph store to load the data from.
|
|
44
|
+
instance_space (str): The instance space to load the data into.
|
|
45
|
+
space_property (str): The property to use to determine the space for each instance.
|
|
46
|
+
use_source_space (bool): If True, use the source space of the instances when extracted from CDF.
|
|
47
|
+
neat_prefix_by_predicate_uri (dict[URIRef, str] | None): A dictionary that maps a predicate URIRef to a
|
|
48
|
+
prefix that Neat added to the object upon extraction. This is used to remove the prefix from the
|
|
49
|
+
object before creating the instance.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
graph_store: NeatInstanceStore | None = None,
|
|
55
|
+
instance_space: str | None = None,
|
|
56
|
+
space_property: str | None = None,
|
|
57
|
+
use_source_space: bool = False,
|
|
58
|
+
neat_prefix_by_predicate_uri: dict[URIRef, str] | None = None,
|
|
59
|
+
) -> None:
|
|
60
|
+
self.graph_store = graph_store
|
|
61
|
+
self.instance_space = instance_space
|
|
62
|
+
self.space_property = space_property
|
|
63
|
+
self.use_source_space = use_source_space
|
|
64
|
+
self.neat_prefix_by_predicate_uri = neat_prefix_by_predicate_uri or {}
|
|
65
|
+
|
|
66
|
+
self._lookup_issues = IssueList()
|
|
67
|
+
|
|
68
|
+
self._has_looked_up = False
|
|
69
|
+
# This is a dictionary mapping instance URIs to their respective spaces
|
|
70
|
+
# This is exposed through the property space_by_instance_uri. If the instance_space or space_property is
|
|
71
|
+
# set (1. and 2.) this is changed to a defaultdict with the instance_space as the default value.
|
|
72
|
+
self._space_by_instance_uri: dict[URIRef, str] = {}
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def space_by_instance_uri(self) -> dict[URIRef, str]:
|
|
76
|
+
"""Returns a dictionary mapping instance URIs to their respective spaces."""
|
|
77
|
+
if not self._has_looked_up:
|
|
78
|
+
self._lookup_spaces()
|
|
79
|
+
self._has_looked_up = True
|
|
80
|
+
return self._space_by_instance_uri
|
|
81
|
+
|
|
82
|
+
def _get_required_capabilities(self) -> list[Capability]:
|
|
83
|
+
return [
|
|
84
|
+
DataModelsAcl(
|
|
85
|
+
actions=[
|
|
86
|
+
DataModelsAcl.Action.Write,
|
|
87
|
+
DataModelsAcl.Action.Read,
|
|
88
|
+
],
|
|
89
|
+
scope=DataModelsAcl.Scope.All(),
|
|
90
|
+
)
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
def _upload_to_cdf(
|
|
94
|
+
self,
|
|
95
|
+
client: NeatClient,
|
|
96
|
+
spaces: list[dm.SpaceApply],
|
|
97
|
+
dry_run: bool,
|
|
98
|
+
read_issues: IssueList,
|
|
99
|
+
class_name: str | None = None,
|
|
100
|
+
) -> Iterable[UploadResult]:
|
|
101
|
+
cdf_spaces = client.data_modeling.spaces.retrieve([space.space for space in spaces])
|
|
102
|
+
cdf_space_by_id = {item.space: item for item in cdf_spaces}
|
|
103
|
+
|
|
104
|
+
to_create = dm.SpaceApplyList([])
|
|
105
|
+
to_update = dm.SpaceApplyList([])
|
|
106
|
+
unchanged = dm.SpaceApplyList([])
|
|
107
|
+
|
|
108
|
+
for local_space in spaces:
|
|
109
|
+
cdf_space = cdf_space_by_id.get(local_space.space)
|
|
110
|
+
if cdf_space is None:
|
|
111
|
+
to_create.append(local_space)
|
|
112
|
+
elif cdf_space != local_space.as_write():
|
|
113
|
+
to_update.append(local_space)
|
|
114
|
+
else:
|
|
115
|
+
unchanged.append(local_space)
|
|
116
|
+
loader = client.loaders.spaces
|
|
117
|
+
results: UploadResult[str] = UploadResult("instance spaces")
|
|
118
|
+
results.unchanged.update(unchanged.as_ids())
|
|
119
|
+
if dry_run:
|
|
120
|
+
results.created.update(to_create.as_ids())
|
|
121
|
+
results.changed.update(to_update.as_ids())
|
|
122
|
+
yield results
|
|
123
|
+
if to_create:
|
|
124
|
+
try:
|
|
125
|
+
client.loaders.spaces.create(to_create)
|
|
126
|
+
except MultiCogniteAPIError as e:
|
|
127
|
+
results.failed_created.update(to_create.as_ids())
|
|
128
|
+
for error in e.errors:
|
|
129
|
+
results.error_messages.append(f"Failed to create {loader.resource_name}: {error!s}")
|
|
130
|
+
else:
|
|
131
|
+
results.created.update(to_create.as_ids())
|
|
132
|
+
|
|
133
|
+
if to_update:
|
|
134
|
+
try:
|
|
135
|
+
client.loaders.spaces.update(to_update)
|
|
136
|
+
except MultiCogniteAPIError as e:
|
|
137
|
+
results.failed_changed.update(to_update.as_ids())
|
|
138
|
+
for error in e.errors:
|
|
139
|
+
results.error_messages.append(f"Failed to update {loader.resource_name}: {error!s}")
|
|
140
|
+
else:
|
|
141
|
+
results.changed.update(to_update.as_ids())
|
|
142
|
+
|
|
143
|
+
yield results
|
|
144
|
+
|
|
145
|
+
def write_to_file(self, filepath: Path) -> None:
|
|
146
|
+
"""Dumps the instance spaces to file."""
|
|
147
|
+
if filepath.suffix not in [".json", ".yaml", ".yml"]:
|
|
148
|
+
raise ValueError(f"File format {filepath.suffix} is not supported")
|
|
149
|
+
dumped: dict[str, list] = {"spaces": [], "issues": []}
|
|
150
|
+
for item in self.load(stop_on_exception=False):
|
|
151
|
+
key = {
|
|
152
|
+
dm.SpaceApply: "spaces",
|
|
153
|
+
NeatIssue: "issues",
|
|
154
|
+
}.get(type(item))
|
|
155
|
+
if key is None:
|
|
156
|
+
# This should never happen, and is a bug in neat
|
|
157
|
+
raise ValueError(f"Item {item} is not supported. This is a bug in neat please report it.")
|
|
158
|
+
dumped[key].append(item.dump())
|
|
159
|
+
with filepath.open("w", encoding=self._encoding, newline=self._new_line) as f:
|
|
160
|
+
if filepath.suffix == ".json":
|
|
161
|
+
json.dump(dumped, f, indent=2)
|
|
162
|
+
else:
|
|
163
|
+
yaml.safe_dump(dumped, f, sort_keys=False)
|
|
164
|
+
|
|
165
|
+
def _load(
|
|
166
|
+
self, stop_on_exception: bool = False
|
|
167
|
+
) -> Iterable[dm.SpaceApply | NeatIssue | type[_END_OF_CLASS] | _START_OF_CLASS]:
|
|
168
|
+
self._lookup_spaces()
|
|
169
|
+
if self._lookup_issues.has_errors and stop_on_exception:
|
|
170
|
+
raise self._lookup_issues.as_errors()
|
|
171
|
+
yield from self._lookup_issues
|
|
172
|
+
seen: set[str] = set()
|
|
173
|
+
for space_str in set(self.space_by_instance_uri.values()):
|
|
174
|
+
if space_str in seen or space_str in COGNITE_SPACES:
|
|
175
|
+
continue
|
|
176
|
+
yield dm.SpaceApply(space=space_str)
|
|
177
|
+
seen.add(space_str)
|
|
178
|
+
|
|
179
|
+
def _lookup_spaces(self) -> None:
|
|
180
|
+
# Case 1: Same instance space for all instances:
|
|
181
|
+
if isinstance(self.instance_space, str) and self.space_property is None and self.use_source_space is False:
|
|
182
|
+
self._space_by_instance_uri = defaultdict(lambda: cast(str, self.instance_space))
|
|
183
|
+
# Adding a dummy entry to ensure that the instance space is included
|
|
184
|
+
self._space_by_instance_uri[URIRef(self.instance_space)] = self.instance_space
|
|
185
|
+
return
|
|
186
|
+
if self.graph_store is None:
|
|
187
|
+
raise ValueError("Graph store must be provided to lookup spaces")
|
|
188
|
+
# Case 3: Use the source space, i.e., the space of the instances when extracted from CDF
|
|
189
|
+
if self.use_source_space and self.instance_space is None and self.space_property is None:
|
|
190
|
+
self._lookup_space_via_instance_uris(self.graph_store)
|
|
191
|
+
# Case 2: Use a property on each instance to determine the space.
|
|
192
|
+
elif self.space_property is not None and self.use_source_space is False:
|
|
193
|
+
if self.instance_space is None:
|
|
194
|
+
raise ValueError(
|
|
195
|
+
"Missing fallback instance space. This is required when "
|
|
196
|
+
f"using space_property='{self.space_property}'"
|
|
197
|
+
)
|
|
198
|
+
self._space_by_instance_uri = defaultdict(lambda: cast(str, self.instance_space))
|
|
199
|
+
self._lookup_space_via_property(self.graph_store, self.space_property)
|
|
200
|
+
else:
|
|
201
|
+
raise ValueError("Either 'instance_space', 'space_property', or 'use_source_space' must be provided.")
|
|
202
|
+
|
|
203
|
+
def _lookup_space_via_instance_uris(self, graph_store: NeatInstanceStore) -> None:
|
|
204
|
+
instance_iterable = itertools.chain(
|
|
205
|
+
(res[0] for res in graph_store.queries.select.list_instances_ids()),
|
|
206
|
+
graph_store.queries.select.list_instance_object_ids(),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
for instance_uri in instance_iterable:
|
|
210
|
+
namespace, external_id = split_uri(instance_uri)
|
|
211
|
+
space = namespace_as_space(namespace)
|
|
212
|
+
if space is None:
|
|
213
|
+
error = ResourceCreationError(instance_uri, "instance", "This instance was not extracted from CDF.")
|
|
214
|
+
self._lookup_issues.append(error)
|
|
215
|
+
else:
|
|
216
|
+
self._space_by_instance_uri[instance_uri] = space
|
|
217
|
+
|
|
218
|
+
def _lookup_space_via_property(self, graph_store: NeatInstanceStore, space_property: str) -> None:
|
|
219
|
+
properties_by_uriref = graph_store.queries.select.properties()
|
|
220
|
+
space_property_uri = next((k for k, v in properties_by_uriref.items() if v == space_property), None)
|
|
221
|
+
if space_property_uri is None:
|
|
222
|
+
error: ResourceNotFoundError[str, str] = ResourceNotFoundError(
|
|
223
|
+
self.space_property,
|
|
224
|
+
"property",
|
|
225
|
+
more=f"Could not find the {space_property} in the graph.",
|
|
226
|
+
)
|
|
227
|
+
self._lookup_issues.append(error)
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
class_with_total_pair = graph_store.queries.select.summarize_instances()
|
|
231
|
+
total = sum([count for _, count in class_with_total_pair])
|
|
232
|
+
instance_iterable = graph_store.queries.select.list_instances_ids_by_space(space_property_uri)
|
|
233
|
+
instance_iterable = iterate_progress_bar_if_above_config_threshold(
|
|
234
|
+
instance_iterable, total, f"Looking up spaces for {total} instances..."
|
|
235
|
+
)
|
|
236
|
+
neat_prefix = self.neat_prefix_by_predicate_uri.get(space_property_uri)
|
|
237
|
+
warned_spaces: set[str] = set()
|
|
238
|
+
for instance, space in instance_iterable:
|
|
239
|
+
if neat_prefix:
|
|
240
|
+
space = space.removeprefix(neat_prefix)
|
|
241
|
+
|
|
242
|
+
clean_space = NamingStandardization.standardize_space_str(space)
|
|
243
|
+
if clean_space != space and space not in warned_spaces:
|
|
244
|
+
self._lookup_issues.append(
|
|
245
|
+
NeatValueWarning(f"Invalid space in property {space_property}: {space}. Fixed to {clean_space}")
|
|
246
|
+
)
|
|
247
|
+
warned_spaces.add(space)
|
|
248
|
+
|
|
249
|
+
self._space_by_instance_uri[instance] = clean_space
|
|
@@ -120,6 +120,18 @@ class SelectQueries(BaseQuery):
|
|
|
120
120
|
# MyPy is not very happy with RDFLib, so just ignore the type hinting here
|
|
121
121
|
return (tuple(res) if class_uri is None else res[0] for res in self.graph(named_graph).query(query)) # type: ignore[index, return-value, arg-type]
|
|
122
122
|
|
|
123
|
+
def list_instance_object_ids(self, limit: int = -1, named_graph: URIRef | None = None) -> Iterable[URIRef]:
|
|
124
|
+
query = (
|
|
125
|
+
"SELECT DISTINCT ?object WHERE { "
|
|
126
|
+
"?subject ?predicate ?object . FILTER(?predicate != rdf:type && isURI(?object))"
|
|
127
|
+
"}"
|
|
128
|
+
)
|
|
129
|
+
if limit != -1:
|
|
130
|
+
query += f" LIMIT {limit}"
|
|
131
|
+
|
|
132
|
+
# MyPy is not very happy with RDFLib, so just ignore the type hinting here
|
|
133
|
+
return cast(Iterable[URIRef], (res[0] for res in self.graph(named_graph).query(query))) # type: ignore[index]
|
|
134
|
+
|
|
123
135
|
def type_with_property(self, type_: URIRef, property_uri: URIRef, named_graph: URIRef | None = None) -> bool:
|
|
124
136
|
"""Check if a property exists in the graph store
|
|
125
137
|
|
cognite/neat/session/_base.py
CHANGED
|
@@ -174,7 +174,7 @@ class NeatSession:
|
|
|
174
174
|
)
|
|
175
175
|
converter = ConceptualToPhysical(reserved_properties=reserved_properties, client=self._state.client)
|
|
176
176
|
|
|
177
|
-
issues = self._state.
|
|
177
|
+
issues = self._state.data_model_transform(converter)
|
|
178
178
|
|
|
179
179
|
if self._verbose and not issues.has_errors:
|
|
180
180
|
print("Conceptual data model converted to physical data model.")
|
|
@@ -222,7 +222,7 @@ class NeatSession:
|
|
|
222
222
|
max_number_of_instance=max_number_of_instance,
|
|
223
223
|
data_model_id=model_id,
|
|
224
224
|
)
|
|
225
|
-
return self._state.
|
|
225
|
+
return self._state.data_model_import(importer)
|
|
226
226
|
|
|
227
227
|
def _infer_subclasses(
|
|
228
228
|
self,
|
cognite/neat/session/_drop.py
CHANGED
|
@@ -97,7 +97,7 @@ class DropDataModelAPI:
|
|
|
97
97
|
f"{len(missing_views)} view(s) not found in the data model.\nDid you mean {', '.join(suggestions)}?"
|
|
98
98
|
)
|
|
99
99
|
before = len(last_dms.views)
|
|
100
|
-
issues = self._state.
|
|
100
|
+
issues = self._state.data_model_transform(DropModelViews(view_external_id, group))
|
|
101
101
|
after = len(self._state.data_model_store.last_verified_physical_data_model.views)
|
|
102
102
|
print(f"Dropped {before - after} views.")
|
|
103
103
|
return issues
|
cognite/neat/session/_fix.py
CHANGED
|
@@ -25,4 +25,4 @@ class DataModelFixAPI:
|
|
|
25
25
|
|
|
26
26
|
def cdf_compliant_external_ids(self) -> IssueList:
|
|
27
27
|
"""Convert (information/logical) data model component external ids to CDF compliant entities."""
|
|
28
|
-
return self._state.
|
|
28
|
+
return self._state.data_model_transform(ToCompliantEntities())
|
cognite/neat/session/_mapping.py
CHANGED
cognite/neat/session/_prepare.py
CHANGED
|
@@ -264,7 +264,7 @@ class DataModelPrepareAPI:
|
|
|
264
264
|
|
|
265
265
|
"""
|
|
266
266
|
|
|
267
|
-
return self._state.
|
|
267
|
+
return self._state.data_model_transform(PrefixEntities(prefix)) # type: ignore[arg-type]
|
|
268
268
|
|
|
269
269
|
def standardize_naming(self) -> IssueList:
|
|
270
270
|
"""Standardize the naming of all views/classes/properties in the data model.
|
|
@@ -274,7 +274,7 @@ class DataModelPrepareAPI:
|
|
|
274
274
|
"""
|
|
275
275
|
warnings.filterwarnings("default")
|
|
276
276
|
ExperimentalFlags.standardize_naming.warn()
|
|
277
|
-
return self._state.
|
|
277
|
+
return self._state.data_model_transform(StandardizeNaming())
|
|
278
278
|
|
|
279
279
|
def standardize_space_and_version(self) -> IssueList:
|
|
280
280
|
"""Standardize space and version in the data model.
|
|
@@ -283,4 +283,4 @@ class DataModelPrepareAPI:
|
|
|
283
283
|
"""
|
|
284
284
|
warnings.filterwarnings("default")
|
|
285
285
|
ExperimentalFlags.standardize_space_and_version.warn()
|
|
286
|
-
return self._state.
|
|
286
|
+
return self._state.data_model_transform(StandardizeSpaceAndVersion())
|
cognite/neat/session/_read.py
CHANGED
|
@@ -118,7 +118,7 @@ class CDFReadAPI(BaseReadAPI):
|
|
|
118
118
|
)
|
|
119
119
|
|
|
120
120
|
importer = importers.DMSImporter.from_data_model_id(cast(NeatClient, self._state.client), data_model_id)
|
|
121
|
-
return self._state.
|
|
121
|
+
return self._state.data_model_import(importer)
|
|
122
122
|
|
|
123
123
|
def core_data_model(self, concepts: str | list[str]) -> IssueList:
|
|
124
124
|
"""Subset the data model to the desired concepts.
|
|
@@ -159,7 +159,7 @@ class CDFReadAPI(BaseReadAPI):
|
|
|
159
159
|
importer: importers.DMSImporter = importers.DMSImporter.from_data_model_id(
|
|
160
160
|
cast(NeatClient, self._state.client), cdm_v1
|
|
161
161
|
)
|
|
162
|
-
issues = self._state.
|
|
162
|
+
issues = self._state.data_model_import(importer)
|
|
163
163
|
|
|
164
164
|
if issues.has_errors:
|
|
165
165
|
return issues
|
|
@@ -167,7 +167,7 @@ class CDFReadAPI(BaseReadAPI):
|
|
|
167
167
|
cdm_data_model = self._state.data_model_store.last_verified_data_model
|
|
168
168
|
|
|
169
169
|
issues.extend(
|
|
170
|
-
self._state.
|
|
170
|
+
self._state.data_model_transform(
|
|
171
171
|
ToEnterpriseModel(
|
|
172
172
|
new_model_id=("my_space", "MyCDMSubset", "v1"),
|
|
173
173
|
org_name="CopyOf",
|
|
@@ -181,7 +181,7 @@ class CDFReadAPI(BaseReadAPI):
|
|
|
181
181
|
return issues
|
|
182
182
|
|
|
183
183
|
issues.extend(
|
|
184
|
-
self._state.
|
|
184
|
+
self._state.data_model_transform(
|
|
185
185
|
_SubsetEditableCDMPhysicalDataModel(
|
|
186
186
|
views={
|
|
187
187
|
ViewEntity(
|
|
@@ -568,7 +568,7 @@ class ExcelReadAPI(BaseReadAPI):
|
|
|
568
568
|
empty_data_model_store_required=True,
|
|
569
569
|
)
|
|
570
570
|
|
|
571
|
-
return self._state.
|
|
571
|
+
return self._state.data_model_import(importers.ExcelImporter(path), enable_manual_edit)
|
|
572
572
|
|
|
573
573
|
|
|
574
574
|
@session_class_wrapper
|
|
@@ -607,7 +607,7 @@ class YamlReadAPI(BaseReadAPI):
|
|
|
607
607
|
importer = dms_importer
|
|
608
608
|
else:
|
|
609
609
|
raise NeatValueError(f"Unsupported YAML format: {format}")
|
|
610
|
-
return self._state.
|
|
610
|
+
return self._state.data_model_import(importer)
|
|
611
611
|
|
|
612
612
|
|
|
613
613
|
@session_class_wrapper
|
|
@@ -824,7 +824,7 @@ class RDFReadAPI(BaseReadAPI):
|
|
|
824
824
|
|
|
825
825
|
reader = NeatReader.create(io)
|
|
826
826
|
importer = importers.OWLImporter.from_file(reader.materialize_path(), source_name=f"file {reader!s}")
|
|
827
|
-
return self._state.
|
|
827
|
+
return self._state.data_model_import(importer)
|
|
828
828
|
|
|
829
829
|
def imf(self, io: Any) -> IssueList:
|
|
830
830
|
"""Reads IMF Types provided as SHACL shapes into NeatSession.
|
|
@@ -847,7 +847,7 @@ class RDFReadAPI(BaseReadAPI):
|
|
|
847
847
|
|
|
848
848
|
reader = NeatReader.create(io)
|
|
849
849
|
importer = importers.IMFImporter.from_file(reader.materialize_path(), source_name=f"file {reader!s}")
|
|
850
|
-
return self._state.
|
|
850
|
+
return self._state.data_model_import(importer)
|
|
851
851
|
|
|
852
852
|
def instances(self, io: Any) -> IssueList:
|
|
853
853
|
self._state._raise_exception_if_condition_not_met(
|
|
@@ -915,7 +915,7 @@ class Examples:
|
|
|
915
915
|
)
|
|
916
916
|
|
|
917
917
|
importer: importers.ExcelImporter = importers.ExcelImporter(catalog.hello_world_pump)
|
|
918
|
-
return self._state.
|
|
918
|
+
return self._state.data_model_import(importer)
|
|
919
919
|
|
|
920
920
|
def core_data_model(self) -> IssueList:
|
|
921
921
|
"""Reads the core data model example into the NeatSession."""
|
|
@@ -930,4 +930,4 @@ class Examples:
|
|
|
930
930
|
importer: importers.DMSImporter = importers.DMSImporter.from_data_model_id(
|
|
931
931
|
cast(NeatClient, self._state.client), cdm_v1
|
|
932
932
|
)
|
|
933
|
-
return self._state.
|
|
933
|
+
return self._state.data_model_import(importer)
|
cognite/neat/session/_set.py
CHANGED
|
@@ -48,7 +48,7 @@ class SetAPI:
|
|
|
48
48
|
"Cannot change the data model ID of a Cognite Data Model in NeatSession"
|
|
49
49
|
" due to temporarily issue with the reverse direct relation interpretation"
|
|
50
50
|
)
|
|
51
|
-
return self._state.
|
|
51
|
+
return self._state.data_model_transform(SetIDDMSModel(new_model_id, name))
|
|
52
52
|
|
|
53
53
|
def client(self, client: CogniteClient) -> None:
|
|
54
54
|
"""Sets the client to be used in the session."""
|
cognite/neat/session/_state.py
CHANGED
|
@@ -30,7 +30,7 @@ class SessionState:
|
|
|
30
30
|
self.client = client
|
|
31
31
|
self.quoted_source_identifiers = False
|
|
32
32
|
|
|
33
|
-
def
|
|
33
|
+
def data_model_transform(self, *transformer: VerifiedDataModelTransformer) -> IssueList:
|
|
34
34
|
if not transformer:
|
|
35
35
|
raise NeatSessionError("No transformers provided.")
|
|
36
36
|
start = self.data_model_store.provenance[-1].target_entity.display_name
|
|
@@ -40,7 +40,7 @@ class SessionState:
|
|
|
40
40
|
issues.hint = "Use the .inspect.issues() for more details."
|
|
41
41
|
return issues
|
|
42
42
|
|
|
43
|
-
def
|
|
43
|
+
def data_model_import(self, importer: BaseImporter, enable_manual_edit: bool = False) -> IssueList:
|
|
44
44
|
issues = self.data_model_store.import_data_model(
|
|
45
45
|
importer,
|
|
46
46
|
client=self.client,
|
cognite/neat/session/_subset.py
CHANGED
|
@@ -68,14 +68,14 @@ class SubsetAPI:
|
|
|
68
68
|
for concept in concepts
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
issues = self._state.
|
|
71
|
+
issues = self._state.data_model_transform(SubsetPhysicalDataModel(views=views))
|
|
72
72
|
if not issues:
|
|
73
73
|
after = len(self._state.data_model_store.last_verified_physical_data_model.views)
|
|
74
74
|
|
|
75
75
|
elif information:
|
|
76
76
|
classes = {ConceptEntity(prefix=information.metadata.space, suffix=concept) for concept in concepts}
|
|
77
77
|
|
|
78
|
-
issues = self._state.
|
|
78
|
+
issues = self._state.data_model_transform(SubsetConceptualDataModel(concepts=classes))
|
|
79
79
|
if not issues:
|
|
80
80
|
after = len(self._state.data_model_store.last_verified_conceptual_data_model.concepts)
|
|
81
81
|
|
|
@@ -70,7 +70,7 @@ class TemplateAPI:
|
|
|
70
70
|
|
|
71
71
|
"""
|
|
72
72
|
last_dm = self._state.data_model_store.last_verified_data_model
|
|
73
|
-
issues = self._state.
|
|
73
|
+
issues = self._state.data_model_transform(
|
|
74
74
|
ToEnterpriseModel(
|
|
75
75
|
new_model_id=data_model_id,
|
|
76
76
|
org_name=org_name,
|
|
@@ -122,7 +122,7 @@ class TemplateAPI:
|
|
|
122
122
|
|
|
123
123
|
transformers.append(ToDataProductModel(new_model_id=data_model_id, include=include))
|
|
124
124
|
|
|
125
|
-
issues = self._state.
|
|
125
|
+
issues = self._state.data_model_transform(*transformers)
|
|
126
126
|
if last_dm and not issues.has_errors:
|
|
127
127
|
self._state.last_reference = last_dm
|
|
128
128
|
return issues
|
|
@@ -202,7 +202,7 @@ class TemplateAPI:
|
|
|
202
202
|
ExcelExporter(styling="maximal").export_to_file(info, output_path)
|
|
203
203
|
issues.action = "Created extension template"
|
|
204
204
|
|
|
205
|
-
# Adding issues to the state in the
|
|
205
|
+
# Adding issues to the state in the data model store
|
|
206
206
|
if issues:
|
|
207
207
|
self._state.data_model_store._last_issues = issues
|
|
208
208
|
return issues
|
cognite/neat/session/_to.py
CHANGED
|
@@ -311,34 +311,37 @@ class CDFToAPI:
|
|
|
311
311
|
|
|
312
312
|
client = cast(NeatClient, self._state.client)
|
|
313
313
|
physical_data_model = self._state.data_model_store.last_verified_physical_data_model
|
|
314
|
-
instance_space = instance_space or f"{physical_data_model.metadata.space}_instances"
|
|
315
314
|
|
|
316
315
|
if instance_space and instance_space == physical_data_model.metadata.space:
|
|
317
316
|
raise NeatSessionError("Space for instances must be different from the data model space.")
|
|
318
317
|
elif not PATTERNS.space_compliance.match(str(instance_space)):
|
|
319
318
|
raise NeatSessionError("Please provide a valid space name. {PATTERNS.space_compliance.pattern}")
|
|
320
319
|
|
|
321
|
-
|
|
322
|
-
|
|
320
|
+
instance_space_loader = loaders.InstanceSpaceLoader(
|
|
321
|
+
self._state.instances.store,
|
|
322
|
+
instance_space=instance_space,
|
|
323
|
+
space_property=space_from_property,
|
|
324
|
+
use_source_space=use_source_space,
|
|
325
|
+
neat_prefix_by_predicate_uri=self._state.instances.neat_prefix_by_predicate_uri,
|
|
326
|
+
)
|
|
327
|
+
result = instance_space_loader.load_into_cdf(client)
|
|
323
328
|
|
|
324
329
|
loader = loaders.DMSLoader(
|
|
325
330
|
self._state.data_model_store.last_verified_physical_data_model,
|
|
326
331
|
self._state.data_model_store.last_verified_conceptual_data_model,
|
|
327
332
|
self._state.instances.store,
|
|
328
|
-
|
|
333
|
+
space_by_instance_uri=instance_space_loader.space_by_instance_uri,
|
|
329
334
|
client=client,
|
|
330
|
-
space_property=space_from_property,
|
|
331
|
-
use_source_space=use_source_space,
|
|
332
335
|
# In case urllib.parse.quote() was run on the extraction, we need to run
|
|
333
336
|
# urllib.parse.unquote() on the load.
|
|
334
337
|
unquote_external_ids=True,
|
|
335
|
-
neat_prefix_by_predicate_uri=self._state.instances.neat_prefix_by_predicate_uri,
|
|
336
338
|
neat_prefix_by_type_uri=self._state.instances.neat_prefix_by_type_uri,
|
|
337
339
|
)
|
|
338
340
|
|
|
339
|
-
|
|
340
|
-
self._state.instances.outcome.append(result)
|
|
341
|
+
instance_result = loader.load_into_cdf(client)
|
|
341
342
|
print("You can inspect the details with the .inspect.outcome.instances(...) method.")
|
|
343
|
+
result.extend(instance_result)
|
|
344
|
+
self._state.instances.outcome.append(result)
|
|
342
345
|
return result
|
|
343
346
|
|
|
344
347
|
def data_model(
|
|
@@ -419,22 +422,26 @@ class ToPythonAPI:
|
|
|
419
422
|
```
|
|
420
423
|
"""
|
|
421
424
|
physical_data_model = self._state.data_model_store.last_verified_physical_data_model
|
|
422
|
-
instance_space = instance_space or f"{physical_data_model.metadata.space}_instances"
|
|
423
425
|
|
|
424
426
|
if instance_space and instance_space == physical_data_model.metadata.space:
|
|
425
427
|
raise NeatSessionError("Space for instances must be different from the data model space.")
|
|
426
428
|
elif not PATTERNS.space_compliance.match(str(instance_space)):
|
|
427
429
|
raise NeatSessionError(f"Please provide a valid space name. {PATTERNS.space_compliance.pattern}")
|
|
428
430
|
|
|
429
|
-
|
|
430
|
-
self._state.data_model_store.last_verified_physical_data_model,
|
|
431
|
-
self._state.data_model_store.last_verified_conceptual_data_model,
|
|
431
|
+
instance_loader = loaders.InstanceSpaceLoader(
|
|
432
432
|
self._state.instances.store,
|
|
433
433
|
instance_space=instance_space,
|
|
434
434
|
space_property=space_from_property,
|
|
435
435
|
use_source_space=use_source_space,
|
|
436
|
-
unquote_external_ids=True,
|
|
437
436
|
neat_prefix_by_predicate_uri=self._state.instances.neat_prefix_by_predicate_uri,
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
loader = loaders.DMSLoader(
|
|
440
|
+
self._state.data_model_store.last_verified_physical_data_model,
|
|
441
|
+
self._state.data_model_store.last_verified_conceptual_data_model,
|
|
442
|
+
self._state.instances.store,
|
|
443
|
+
space_by_instance_uri=instance_loader.space_by_instance_uri,
|
|
444
|
+
unquote_external_ids=True,
|
|
438
445
|
neat_prefix_by_type_uri=self._state.instances.neat_prefix_by_type_uri,
|
|
439
446
|
)
|
|
440
447
|
issue_list = IssueList()
|
|
@@ -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=_JrRkMfRe7BY5PWfWWx60wpSBwtlRhSaJ8zbSR9WYtc,46
|
|
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
|
|
@@ -38,7 +38,7 @@ cognite/neat/core/_data_model/importers/__init__.py,sha256=ipImLDSse0vAHX4AWvtPI
|
|
|
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
40
|
cognite/neat/core/_data_model/importers/_dict2data_model.py,sha256=-1zmo8JkxJ9qiWuC7sUH7oSlpnPPKTMxZtm4WrRPO5A,4709
|
|
41
|
-
cognite/neat/core/_data_model/importers/_dms2data_model.py,sha256=
|
|
41
|
+
cognite/neat/core/_data_model/importers/_dms2data_model.py,sha256=fbPf1IA5wAZtosSYe8sd4Tnur3w41TTJz2qRbTHX-d0,28306
|
|
42
42
|
cognite/neat/core/_data_model/importers/_spreadsheet2data_model.py,sha256=2QqrxQ9AI3LT9toH_gryIR52UecMsR-v44ljXedDCp4,11972
|
|
43
43
|
cognite/neat/core/_data_model/importers/_dtdl2data_model/__init__.py,sha256=CNR-sUihs2mnR1bPMKs3j3L4ds3vFTsrl6YycExZTfU,68
|
|
44
44
|
cognite/neat/core/_data_model/importers/_dtdl2data_model/_unit_lookup.py,sha256=wW4saKva61Q_i17guY0dc4OseJDQfqHy_QZBtm0OD6g,12134
|
|
@@ -77,9 +77,9 @@ cognite/neat/core/_data_model/models/physical/_validation.py,sha256=i0YHDE2c09Oe
|
|
|
77
77
|
cognite/neat/core/_data_model/models/physical/_verified.py,sha256=UsfzuIyYRsdUPK9wJM9Wxs4VkD4GiGUQAjRjgDCmIHw,24237
|
|
78
78
|
cognite/neat/core/_data_model/transformers/__init__.py,sha256=_FPmPh0kA68SXR4arKKNmtWQ8B2-wSwWQeGAWnjoJAQ,1788
|
|
79
79
|
cognite/neat/core/_data_model/transformers/_base.py,sha256=7adUBJgDkXgRq_h7l1q2VsLQo3lE7-xmzmHdcF4QHq8,3133
|
|
80
|
-
cognite/neat/core/_data_model/transformers/_converters.py,sha256=
|
|
81
|
-
cognite/neat/core/_data_model/transformers/_mapping.py,sha256=
|
|
82
|
-
cognite/neat/core/_data_model/transformers/_verification.py,sha256=
|
|
80
|
+
cognite/neat/core/_data_model/transformers/_converters.py,sha256=OazYC7DgAXXEvxdiaPfJSe2ZNkYn2mRqWhtvtvWK59g,111575
|
|
81
|
+
cognite/neat/core/_data_model/transformers/_mapping.py,sha256=GwmTRnhiUPIG37CgUSIbjT7ZpWOwdWuBZ_HAIIBiKYY,19024
|
|
82
|
+
cognite/neat/core/_data_model/transformers/_verification.py,sha256=yyPK6irhMGjVtwKxRIElSsPLUvLLVfk1lBAGny6jN5w,5193
|
|
83
83
|
cognite/neat/core/_instances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
84
84
|
cognite/neat/core/_instances/_shared.py,sha256=6avH6mtjxjHI7JDLkXwICxGvZwooGBr6APs1_w1To-A,940
|
|
85
85
|
cognite/neat/core/_instances/_tracking/__init__.py,sha256=WOwsYieZtCW-iW15YkxUFrfKVVdLWdXHOGGStTwvE8A,91
|
|
@@ -108,13 +108,14 @@ cognite/neat/core/_instances/extractors/_classic_cdf/_labels.py,sha256=7guTZdGFT
|
|
|
108
108
|
cognite/neat/core/_instances/extractors/_classic_cdf/_relationships.py,sha256=kNzrqHQuIZMBecZ8957Qs3-Pp2m2-k2CCfiUZlVwaD0,5395
|
|
109
109
|
cognite/neat/core/_instances/extractors/_classic_cdf/_sequences.py,sha256=zwHM52afnq-JHvLOTi4rH6DyfkTftxH6cmODwoZi8uw,11399
|
|
110
110
|
cognite/neat/core/_instances/extractors/_classic_cdf/_timeseries.py,sha256=Py8MDcn82MJcsDPbeqDHMx4g2rQHmEOSHNe6gOi5gew,2044
|
|
111
|
-
cognite/neat/core/_instances/loaders/__init__.py,sha256=
|
|
112
|
-
cognite/neat/core/_instances/loaders/_base.py,sha256=
|
|
113
|
-
cognite/neat/core/_instances/loaders/_rdf2dms.py,sha256=
|
|
111
|
+
cognite/neat/core/_instances/loaders/__init__.py,sha256=qyOrKy0cJgYmgEuWVM-O1mpUemQE8EkfQYtJyEc8UVs,778
|
|
112
|
+
cognite/neat/core/_instances/loaders/_base.py,sha256=jfik8xsdocMHVlodvgHpnDJfYdEjYuKdd0t7MGhzAHI,4337
|
|
113
|
+
cognite/neat/core/_instances/loaders/_rdf2dms.py,sha256=PoNj77pxVoUpP7qxmMWf2nNul2PtlAlIFcVzUV2gyuE,29076
|
|
114
|
+
cognite/neat/core/_instances/loaders/_rdf_to_instance_space.py,sha256=qVxRzEUyhv8AGvAO8whJWPCZ-8BppEy0mk1Ux_8gOzY,11937
|
|
114
115
|
cognite/neat/core/_instances/queries/__init__.py,sha256=W477LMyB4l6HIRbQhJoFgA_MUBwVCh2GBvtFeZu0AUA,53
|
|
115
116
|
cognite/neat/core/_instances/queries/_base.py,sha256=APevHeeWQDEoOQ0MlBtVlPf9hbZukVkI5fOvt5oPJCE,543
|
|
116
117
|
cognite/neat/core/_instances/queries/_queries.py,sha256=4BidSQXhdZYZ6_kyG7jMJ2iG0UtSrbQxfmwPM7V167A,466
|
|
117
|
-
cognite/neat/core/_instances/queries/_select.py,sha256
|
|
118
|
+
cognite/neat/core/_instances/queries/_select.py,sha256=-iJnEddNCIr26D2QBBq_82G4l6YoYpTs2jd_CELvxB8,19096
|
|
118
119
|
cognite/neat/core/_instances/queries/_update.py,sha256=j2hU62rEIYWvZ_ZAkm9Khc2lNddnww0W-1jR7MJJbFY,1290
|
|
119
120
|
cognite/neat/core/_instances/transformers/__init__.py,sha256=YzC1Z8BuT77NwagWX4Z-F9R9BARLSS7zM4bCdxBbqKg,1761
|
|
120
121
|
cognite/neat/core/_instances/transformers/_base.py,sha256=RYa9es5fEsjLpaok8liuy73ACPDWwHVfTm2Lq4HVCig,4695
|
|
@@ -160,22 +161,22 @@ cognite/neat/core/_utils/xml_.py,sha256=FQkq84u35MUsnKcL6nTMJ9ajtG9D5i1u4VBnhGqP
|
|
|
160
161
|
cognite/neat/core/_utils/reader/__init__.py,sha256=fPkrNB_9hLB7CyHTCFV_xEbIfOMqUQzNly5JN33-QfM,146
|
|
161
162
|
cognite/neat/core/_utils/reader/_base.py,sha256=fRXxUWW8a3UFedeCLxDTDgFntWGlHaEGxmKLcITtiWE,5417
|
|
162
163
|
cognite/neat/session/__init__.py,sha256=fxQ5URVlUnmEGYyB8Baw7IDq-uYacqkigbc4b-Pr9Fw,58
|
|
163
|
-
cognite/neat/session/_base.py,sha256=
|
|
164
|
+
cognite/neat/session/_base.py,sha256=DqujVyC19Jg8hGxnw9TfCeF3BYOFuauk4yTTuAsjJz4,12807
|
|
164
165
|
cognite/neat/session/_collector.py,sha256=-icWXOT9YBjAOVZfpPtBx-D39kpRP2RaQKdPtcr7Xm8,4233
|
|
165
|
-
cognite/neat/session/_drop.py,sha256=
|
|
166
|
+
cognite/neat/session/_drop.py,sha256=ipD8RS_ZebPNpeIkhC7yqSSeo7e57TXMRxrh5_6IRik,4239
|
|
166
167
|
cognite/neat/session/_experimental.py,sha256=U_Wq3NWgnGaOJh5Fq8iO6HcYUhlG9RQIutT8e4LZL8o,1224
|
|
167
168
|
cognite/neat/session/_explore.py,sha256=PLxpHDqBk5B0Q4a5tJKnF6KzL4heQ77b2qUETbf6iVQ,1599
|
|
168
|
-
cognite/neat/session/_fix.py,sha256=
|
|
169
|
+
cognite/neat/session/_fix.py,sha256=oJRXuRI4f_HgLYHkjbtPAwHK0vSDUYd19hIZeFaE7rQ,919
|
|
169
170
|
cognite/neat/session/_inspect.py,sha256=AESQd2SOidR_pDTFk5B_JdPnKZ5PNNskdAQBepH2Mv0,10175
|
|
170
|
-
cognite/neat/session/_mapping.py,sha256=
|
|
171
|
-
cognite/neat/session/_prepare.py,sha256=
|
|
172
|
-
cognite/neat/session/_read.py,sha256=
|
|
173
|
-
cognite/neat/session/_set.py,sha256=
|
|
171
|
+
cognite/neat/session/_mapping.py,sha256=ItEXhXo_8V3069hktHMxdpBsLNeTck3gZBvhlm12Oxw,2895
|
|
172
|
+
cognite/neat/session/_prepare.py,sha256=pskEVNgcnVJVRvYKk5xI55V89vKDO_kgjszj5flY8Zs,12778
|
|
173
|
+
cognite/neat/session/_read.py,sha256=sKtSw7Ub--vR6wfEexNzzaEHb0MZCHj3kzCEnF5wjf0,35349
|
|
174
|
+
cognite/neat/session/_set.py,sha256=PU4lKI-LGtKFVyvdtfZkk-zLw9e_rnFHzuV9IyrOrTM,4593
|
|
174
175
|
cognite/neat/session/_show.py,sha256=YLt6K4ukG1s_I_FhuVrIVPtw_btvvOL50Rwrx-vo7VQ,10743
|
|
175
|
-
cognite/neat/session/_state.py,sha256=
|
|
176
|
-
cognite/neat/session/_subset.py,sha256=
|
|
177
|
-
cognite/neat/session/_template.py,sha256=
|
|
178
|
-
cognite/neat/session/_to.py,sha256=
|
|
176
|
+
cognite/neat/session/_state.py,sha256=DLEm9wn3GtOuTGhy5-M1IK2v9qvLnTYEruWPidzAP_Q,6580
|
|
177
|
+
cognite/neat/session/_subset.py,sha256=p7n6WmL0gZlUbqpVBgyPncQ6uWn_pi7FDSixDFrm7DM,2848
|
|
178
|
+
cognite/neat/session/_template.py,sha256=NCgrrwLT98DpLYoo3Wybr_OUXrEXpsJZjrJ83KqfyWc,9908
|
|
179
|
+
cognite/neat/session/_to.py,sha256=_R-UB3iEIQoa12kTD7tuSrRDdbySQXQg_mzbn5t-7bg,19399
|
|
179
180
|
cognite/neat/session/_wizard.py,sha256=hARNNzD5Zfkk_V147rIjOLVvrFaqzXGXWhZuH1NJG3M,1486
|
|
180
181
|
cognite/neat/session/exceptions.py,sha256=KJ7UUjmuGb_1O6FIamkwe4z0bCroAwn-AwX---hEudY,3341
|
|
181
182
|
cognite/neat/session/_state/README.md,sha256=o6N7EL98lgyWffw8IoEUf2KG5uSKveD5__TW45YzVjA,902
|
|
@@ -183,7 +184,7 @@ cognite/neat/session/engine/__init__.py,sha256=D3MxUorEs6-NtgoICqtZ8PISQrjrr4dvc
|
|
|
183
184
|
cognite/neat/session/engine/_import.py,sha256=1QxA2_EK613lXYAHKQbZyw2yjo5P9XuiX4Z6_6-WMNQ,169
|
|
184
185
|
cognite/neat/session/engine/_interface.py,sha256=3W-cYr493c_mW3P5O6MKN1xEQg3cA7NHR_ev3zdF9Vk,533
|
|
185
186
|
cognite/neat/session/engine/_load.py,sha256=g52uYakQM03VqHt_RDHtpHso1-mFFifH5M4T2ScuH8A,5198
|
|
186
|
-
cognite_neat-0.122.
|
|
187
|
-
cognite_neat-0.122.
|
|
188
|
-
cognite_neat-0.122.
|
|
189
|
-
cognite_neat-0.122.
|
|
187
|
+
cognite_neat-0.122.2.dist-info/METADATA,sha256=_QX6C2C4GLJTwqISRsJcrNIFpPZbxTXi6OLbwc_hDhg,9171
|
|
188
|
+
cognite_neat-0.122.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
189
|
+
cognite_neat-0.122.2.dist-info/licenses/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
|
|
190
|
+
cognite_neat-0.122.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|