cognite-toolkit 0.7.39__py3-none-any.whl → 0.7.41__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.
- cognite_toolkit/_cdf_tk/client/_toolkit_client.py +7 -1
- cognite_toolkit/_cdf_tk/client/api/assets.py +118 -0
- cognite_toolkit/_cdf_tk/client/api/events.py +97 -0
- cognite_toolkit/_cdf_tk/client/api/infield.py +3 -3
- cognite_toolkit/_cdf_tk/client/api/legacy/extended_functions.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/project.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/streams.py +2 -2
- cognite_toolkit/_cdf_tk/client/api/three_d.py +5 -4
- cognite_toolkit/_cdf_tk/client/api/timeseries.py +105 -0
- cognite_toolkit/_cdf_tk/client/cdf_client/__init__.py +9 -0
- cognite_toolkit/_cdf_tk/client/cdf_client/api.py +220 -0
- cognite_toolkit/_cdf_tk/client/{data_classes/api_classes.py → cdf_client/responses.py} +10 -13
- cognite_toolkit/_cdf_tk/client/data_classes/agent.py +127 -0
- cognite_toolkit/_cdf_tk/client/data_classes/asset.py +54 -0
- cognite_toolkit/_cdf_tk/client/data_classes/base.py +117 -22
- cognite_toolkit/_cdf_tk/client/data_classes/event.py +43 -0
- cognite_toolkit/_cdf_tk/client/data_classes/filemetadata.py +56 -0
- cognite_toolkit/_cdf_tk/client/data_classes/identifiers.py +44 -0
- cognite_toolkit/_cdf_tk/client/data_classes/instance_api.py +34 -0
- cognite_toolkit/_cdf_tk/client/data_classes/raw.py +43 -0
- cognite_toolkit/_cdf_tk/client/data_classes/streams.py +3 -2
- cognite_toolkit/_cdf_tk/client/data_classes/three_d.py +29 -34
- cognite_toolkit/_cdf_tk/client/data_classes/timeseries.py +55 -0
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/__init__.py +4 -4
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/_client.py +10 -10
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/_data_classes.py +2 -2
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/_data_classes2.py +10 -33
- cognite_toolkit/_cdf_tk/client/testing.py +6 -0
- cognite_toolkit/_cdf_tk/commands/_migrate/command.py +1 -1
- cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +6 -7
- cognite_toolkit/_cdf_tk/commands/_migrate/data_classes.py +6 -5
- cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +6 -4
- cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +10 -10
- cognite_toolkit/_cdf_tk/commands/_purge.py +7 -7
- cognite_toolkit/_cdf_tk/commands/_upload.py +1 -1
- cognite_toolkit/_cdf_tk/commands/pull.py +97 -2
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +43 -47
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +11 -4
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +2 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/location.py +3 -2
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +2 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +1 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +2 -1
- cognite_toolkit/_cdf_tk/storageio/_applications.py +1 -1
- cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +32 -29
- cognite_toolkit/_cdf_tk/storageio/_base.py +1 -1
- cognite_toolkit/_cdf_tk/storageio/_datapoints.py +7 -7
- cognite_toolkit/_cdf_tk/storageio/_file_content.py +7 -7
- cognite_toolkit/_cdf_tk/storageio/_raw.py +1 -1
- cognite_toolkit/_cdf_tk/utils/useful_types.py +4 -7
- cognite_toolkit/_cdf_tk/utils/useful_types2.py +12 -0
- cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
- cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
- cognite_toolkit/_resources/cdf.toml +1 -1
- cognite_toolkit/_version.py +1 -1
- {cognite_toolkit-0.7.39.dist-info → cognite_toolkit-0.7.41.dist-info}/METADATA +1 -1
- {cognite_toolkit-0.7.39.dist-info → cognite_toolkit-0.7.41.dist-info}/RECORD +61 -48
- {cognite_toolkit-0.7.39.dist-info → cognite_toolkit-0.7.41.dist-info}/WHEEL +1 -1
- /cognite_toolkit/_cdf_tk/{utils → client}/http_client/_exception.py +0 -0
- /cognite_toolkit/_cdf_tk/{utils → client}/http_client/_tracker.py +0 -0
- {cognite_toolkit-0.7.39.dist-info → cognite_toolkit-0.7.41.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import itertools
|
|
3
|
+
import json
|
|
3
4
|
import re
|
|
4
5
|
import sys
|
|
5
6
|
import tempfile
|
|
@@ -28,6 +29,7 @@ from cognite_toolkit._cdf_tk.cruds import (
|
|
|
28
29
|
HostedExtractorSourceCRUD,
|
|
29
30
|
ResourceCRUD,
|
|
30
31
|
StreamlitCRUD,
|
|
32
|
+
ViewCRUD,
|
|
31
33
|
)
|
|
32
34
|
from cognite_toolkit._cdf_tk.data_classes import (
|
|
33
35
|
BuildEnvironment,
|
|
@@ -643,6 +645,44 @@ class PullCommand(ToolkitCommand):
|
|
|
643
645
|
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
644
646
|
source_file: Path,
|
|
645
647
|
) -> tuple[str, dict[Path, str]]:
|
|
648
|
+
"""Convert resource data from CDF into YAML file content ready to be written to disk.
|
|
649
|
+
|
|
650
|
+
This method takes the raw CDF resource data and transforms it back into a properly
|
|
651
|
+
formatted YAML file that preserves:
|
|
652
|
+
- Template variables (e.g., {{ variable_name }}) instead of their resolved values
|
|
653
|
+
- YAML comments from the original source file
|
|
654
|
+
- The original key ordering in dictionaries
|
|
655
|
+
|
|
656
|
+
The transformation process:
|
|
657
|
+
1. Replace all template variables with unique placeholders
|
|
658
|
+
2. Load source YAML content while preserving comments
|
|
659
|
+
3. Update the resource data with placeholder values where variables were used
|
|
660
|
+
4. Dump the updated data back to YAML format
|
|
661
|
+
5. Replace placeholders with the original template variable syntax
|
|
662
|
+
6. Restore the YAML comments
|
|
663
|
+
|
|
664
|
+
Args:
|
|
665
|
+
source: The original YAML file content as a string.
|
|
666
|
+
to_write: A mapping from resource identifiers to their updated data dictionaries
|
|
667
|
+
pulled from CDF.
|
|
668
|
+
resources: The list of built resources containing build variables and metadata.
|
|
669
|
+
environment_variables: A mapping of environment variable names to their values,
|
|
670
|
+
used to resolve variables like ${VAR_NAME} in template values.
|
|
671
|
+
loader: The ResourceCRUD loader instance for this resource type.
|
|
672
|
+
source_file: The path to the source file being processed.
|
|
673
|
+
|
|
674
|
+
Returns:
|
|
675
|
+
A tuple containing:
|
|
676
|
+
- The final YAML content string ready to be written to disk.
|
|
677
|
+
- A dictionary mapping extra file paths to their content (for resources
|
|
678
|
+
that have additional files, like SQL queries for transformations).
|
|
679
|
+
|
|
680
|
+
Raises:
|
|
681
|
+
ValueError: If the loaded YAML structure doesn't match between the original
|
|
682
|
+
and placeholder versions.
|
|
683
|
+
ToolkitMissingResourceError: If a resource identifier is not found in the
|
|
684
|
+
to_write or resources mappings.
|
|
685
|
+
"""
|
|
646
686
|
# 1. Replace all variables with placeholders
|
|
647
687
|
# 2. Load source and keep the comments
|
|
648
688
|
# 3. Update the to_write dict with the placeholders
|
|
@@ -762,9 +802,22 @@ class PullCommand(ToolkitCommand):
|
|
|
762
802
|
|
|
763
803
|
|
|
764
804
|
class ResourceReplacer:
|
|
765
|
-
"""Replaces values in a local resource
|
|
805
|
+
"""Replaces values in a local resource dictionary with the updated values from CDF.
|
|
766
806
|
|
|
767
807
|
The local resource dict order is maintained. In addition, placeholders are used for variables.
|
|
808
|
+
|
|
809
|
+
This class is responsible for merging CDF resource values back into local configuration files
|
|
810
|
+
while preserving:
|
|
811
|
+
- The original key ordering in dictionaries
|
|
812
|
+
- Template variable placeholders (e.g., {{ variable_name }})
|
|
813
|
+
- Comments and formatting where possible
|
|
814
|
+
|
|
815
|
+
Args:
|
|
816
|
+
value_by_placeholder: A mapping from placeholder strings to their corresponding
|
|
817
|
+
BuildVariable objects. Placeholders are temporary substitutes for template
|
|
818
|
+
variables during processing.
|
|
819
|
+
loader: The ResourceCRUD loader instance used to determine how to diff lists
|
|
820
|
+
and handle resource-specific logic.
|
|
768
821
|
"""
|
|
769
822
|
|
|
770
823
|
def __init__(self, value_by_placeholder: dict[str, BuildVariable], loader: ResourceCRUD) -> None:
|
|
@@ -777,7 +830,49 @@ class ResourceReplacer:
|
|
|
777
830
|
placeholder: dict[str, Any],
|
|
778
831
|
to_write: dict[str, Any],
|
|
779
832
|
) -> dict[str, Any]:
|
|
780
|
-
|
|
833
|
+
"""Replace values in a local resource dict with updated values from CDF.
|
|
834
|
+
|
|
835
|
+
Merges the CDF resource values into the local configuration while maintaining
|
|
836
|
+
the original dictionary key ordering and preserving template variable placeholders.
|
|
837
|
+
|
|
838
|
+
Args:
|
|
839
|
+
current: The current local resource dictionary with resolved variable values.
|
|
840
|
+
This represents the source file content after template variables have
|
|
841
|
+
been substituted with their actual values.
|
|
842
|
+
placeholder: The local resource dictionary with placeholder strings instead
|
|
843
|
+
of resolved values. Used to identify which values contain template
|
|
844
|
+
variables that should be preserved.
|
|
845
|
+
to_write: The resource dictionary from CDF containing the updated values
|
|
846
|
+
to merge into the local configuration.
|
|
847
|
+
|
|
848
|
+
Returns:
|
|
849
|
+
A new dictionary with CDF values merged in, maintaining the original key
|
|
850
|
+
order from `current`. Template variables are preserved as placeholders
|
|
851
|
+
(to be converted back to {{ variable }} syntax by the caller). New keys
|
|
852
|
+
from CDF are appended at the end, and removed keys are omitted.
|
|
853
|
+
|
|
854
|
+
Raises:
|
|
855
|
+
ToolkitValueError: If a list variable has changed and cannot be updated,
|
|
856
|
+
or if there's a type mismatch between local and CDF values.
|
|
857
|
+
"""
|
|
858
|
+
has_stringified_view_filter = False
|
|
859
|
+
if isinstance(self._loader, ViewCRUD):
|
|
860
|
+
# view.filter are recursive nested dicts that are complex. To avoid issues with comparing
|
|
861
|
+
# lists inside the filters, we stringify them before processing such that they are compared
|
|
862
|
+
# as strings.
|
|
863
|
+
processed = []
|
|
864
|
+
for d in (current, placeholder, to_write):
|
|
865
|
+
if isinstance(d.get("filter"), dict):
|
|
866
|
+
d = d.copy()
|
|
867
|
+
d["filter"] = json.dumps(d["filter"])
|
|
868
|
+
has_stringified_view_filter = True
|
|
869
|
+
processed.append(d)
|
|
870
|
+
current, placeholder, to_write = processed
|
|
871
|
+
output = self._replace_dict(current, placeholder, to_write, tuple())
|
|
872
|
+
if has_stringified_view_filter and "filter" in output:
|
|
873
|
+
# Special case for ViewCRUD where the filter is stringified in CDF
|
|
874
|
+
output["filter"] = json.loads(output["filter"])
|
|
875
|
+
return output
|
|
781
876
|
|
|
782
877
|
def _replace_dict(
|
|
783
878
|
self,
|
|
@@ -6,10 +6,6 @@ from typing import Any, final
|
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
8
8
|
from cognite.client.data_classes import (
|
|
9
|
-
AggregateResultItem,
|
|
10
|
-
Asset,
|
|
11
|
-
AssetList,
|
|
12
|
-
AssetWrite,
|
|
13
9
|
Event,
|
|
14
10
|
EventList,
|
|
15
11
|
EventWrite,
|
|
@@ -24,6 +20,12 @@ from cognite.client.utils.useful_types import SequenceNotStr
|
|
|
24
20
|
from rich.console import Console
|
|
25
21
|
|
|
26
22
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
23
|
+
from cognite_toolkit._cdf_tk.client.data_classes.asset import (
|
|
24
|
+
AssetAggregateItem,
|
|
25
|
+
AssetRequest,
|
|
26
|
+
AssetResponse,
|
|
27
|
+
)
|
|
28
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId, InternalOrExternalId
|
|
27
29
|
from cognite_toolkit._cdf_tk.client.data_classes.legacy.sequences import (
|
|
28
30
|
ToolkitSequenceRows,
|
|
29
31
|
ToolkitSequenceRowsList,
|
|
@@ -44,10 +46,10 @@ _DEPRECATION_WARNING_ISSUED = False
|
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
@final
|
|
47
|
-
class AssetCRUD(ResourceCRUD[
|
|
49
|
+
class AssetCRUD(ResourceCRUD[ExternalId, AssetRequest, AssetResponse]):
|
|
48
50
|
folder_name = "classic"
|
|
49
|
-
resource_cls =
|
|
50
|
-
resource_write_cls =
|
|
51
|
+
resource_cls = AssetResponse
|
|
52
|
+
resource_write_cls = AssetRequest
|
|
51
53
|
yaml_cls = AssetYAML
|
|
52
54
|
kind = "Asset"
|
|
53
55
|
dependencies = frozenset({DataSetsCRUD, LabelCRUD})
|
|
@@ -78,15 +80,15 @@ class AssetCRUD(ResourceCRUD[str, AssetWrite, Asset]):
|
|
|
78
80
|
return "assets"
|
|
79
81
|
|
|
80
82
|
@classmethod
|
|
81
|
-
def get_id(cls, item:
|
|
83
|
+
def get_id(cls, item: AssetRequest | AssetResponse | dict) -> ExternalId:
|
|
82
84
|
if isinstance(item, dict):
|
|
83
|
-
return item["externalId"]
|
|
85
|
+
return ExternalId(external_id=item["externalId"])
|
|
84
86
|
if not item.external_id:
|
|
85
87
|
raise KeyError("Asset must have external_id")
|
|
86
|
-
return item.external_id
|
|
88
|
+
return ExternalId(external_id=item.external_id)
|
|
87
89
|
|
|
88
90
|
@classmethod
|
|
89
|
-
def get_internal_id(cls, item:
|
|
91
|
+
def get_internal_id(cls, item: AssetResponse | dict) -> int:
|
|
90
92
|
if isinstance(item, dict):
|
|
91
93
|
return item["id"]
|
|
92
94
|
if not item.id:
|
|
@@ -94,12 +96,12 @@ class AssetCRUD(ResourceCRUD[str, AssetWrite, Asset]):
|
|
|
94
96
|
return item.id
|
|
95
97
|
|
|
96
98
|
@classmethod
|
|
97
|
-
def dump_id(cls, id:
|
|
98
|
-
return
|
|
99
|
+
def dump_id(cls, id: ExternalId) -> dict[str, Any]:
|
|
100
|
+
return id.dump()
|
|
99
101
|
|
|
100
102
|
@classmethod
|
|
101
103
|
def get_required_capability(
|
|
102
|
-
cls, items: collections.abc.Sequence[
|
|
104
|
+
cls, items: collections.abc.Sequence[AssetRequest] | None, read_only: bool
|
|
103
105
|
) -> Capability | list[Capability]:
|
|
104
106
|
if not items and items is not None:
|
|
105
107
|
return []
|
|
@@ -119,45 +121,39 @@ class AssetCRUD(ResourceCRUD[str, AssetWrite, Asset]):
|
|
|
119
121
|
|
|
120
122
|
return capabilities.AssetsAcl(actions, scope)
|
|
121
123
|
|
|
122
|
-
def create(self, items: Sequence[
|
|
123
|
-
return self.client.assets.create(items)
|
|
124
|
+
def create(self, items: collections.abc.Sequence[AssetRequest]) -> list[AssetResponse]:
|
|
125
|
+
return self.client.tool.assets.create(items)
|
|
124
126
|
|
|
125
|
-
def retrieve(self, ids: SequenceNotStr[
|
|
126
|
-
return self.client.assets.
|
|
127
|
+
def retrieve(self, ids: SequenceNotStr[ExternalId]) -> list[AssetResponse]:
|
|
128
|
+
return self.client.tool.assets.retrieve(list(ids), ignore_unknown_ids=True)
|
|
127
129
|
|
|
128
|
-
def update(self, items: Sequence[
|
|
129
|
-
return self.client.assets.update(items, mode="replace")
|
|
130
|
+
def update(self, items: collections.abc.Sequence[AssetRequest]) -> list[AssetResponse]:
|
|
131
|
+
return self.client.tool.assets.update(items, mode="replace")
|
|
130
132
|
|
|
131
|
-
def delete(self, ids: SequenceNotStr[
|
|
133
|
+
def delete(self, ids: SequenceNotStr[InternalOrExternalId]) -> int:
|
|
132
134
|
if not ids:
|
|
133
135
|
return 0
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
self.client.assets.delete(id=internal_ids, external_id=external_ids)
|
|
137
|
-
except CogniteNotFoundError as e:
|
|
138
|
-
# Do a CogniteNotFoundError instead of passing 'ignore_unknown_ids=True' to the delete method
|
|
139
|
-
# to obtain an accurate list of deleted assets.
|
|
140
|
-
non_existing = set(e.failed or [])
|
|
141
|
-
if existing := [id_ for id_ in ids if id_ not in non_existing]:
|
|
142
|
-
internal_ids, external_ids = self._split_ids(existing)
|
|
143
|
-
self.client.assets.delete(id=internal_ids, external_id=external_ids)
|
|
144
|
-
return len(existing)
|
|
145
|
-
else:
|
|
146
|
-
return len(ids)
|
|
136
|
+
self.client.tool.assets.delete(list(ids), ignore_unknown_ids=True)
|
|
137
|
+
return len(ids)
|
|
147
138
|
|
|
148
139
|
def _iterate(
|
|
149
140
|
self,
|
|
150
141
|
data_set_external_id: str | None = None,
|
|
151
142
|
space: str | None = None,
|
|
152
143
|
parent_ids: list[Hashable] | None = None,
|
|
153
|
-
) -> Iterable[
|
|
154
|
-
|
|
155
|
-
|
|
144
|
+
) -> Iterable[AssetResponse]:
|
|
145
|
+
cursor: str | None = None
|
|
146
|
+
while True:
|
|
147
|
+
page = self.client.tool.assets.iterate(
|
|
148
|
+
limit=1000,
|
|
149
|
+
cursor=cursor,
|
|
156
150
|
data_set_external_ids=[data_set_external_id] if data_set_external_id else None,
|
|
157
|
-
|
|
158
|
-
aggregated_properties=["depth", "child_count", "path"],
|
|
151
|
+
aggregated_properties=True,
|
|
159
152
|
)
|
|
160
|
-
|
|
153
|
+
yield from page.items
|
|
154
|
+
if not page.next_cursor or not page.items:
|
|
155
|
+
break
|
|
156
|
+
cursor = page.next_cursor
|
|
161
157
|
|
|
162
158
|
@classmethod
|
|
163
159
|
def get_dependent_items(cls, item: dict) -> Iterable[tuple[type[ResourceCRUD], Hashable]]:
|
|
@@ -202,7 +198,7 @@ class AssetCRUD(ResourceCRUD[str, AssetWrite, Asset]):
|
|
|
202
198
|
|
|
203
199
|
return resources
|
|
204
200
|
|
|
205
|
-
def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) ->
|
|
201
|
+
def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> AssetRequest:
|
|
206
202
|
# Unpack metadata keys from table formats (e.g. csv, parquet)
|
|
207
203
|
metadata: dict = resource.get("metadata", {})
|
|
208
204
|
for key, value in list(resource.items()):
|
|
@@ -219,10 +215,10 @@ class AssetCRUD(ResourceCRUD[str, AssetWrite, Asset]):
|
|
|
219
215
|
|
|
220
216
|
if ds_external_id := resource.pop("dataSetExternalId", None):
|
|
221
217
|
resource["dataSetId"] = self.client.lookup.data_sets.id(ds_external_id, is_dry_run)
|
|
222
|
-
return
|
|
218
|
+
return AssetRequest.model_validate(resource)
|
|
223
219
|
|
|
224
|
-
def dump_resource(self, resource:
|
|
225
|
-
dumped = resource.
|
|
220
|
+
def dump_resource(self, resource: AssetResponse, local: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
221
|
+
dumped = resource.as_request_resource().dump()
|
|
226
222
|
local = local or {}
|
|
227
223
|
if data_set_id := dumped.pop("dataSetId", None):
|
|
228
224
|
dumped["dataSetExternalId"] = self.client.lookup.data_sets.external_id(data_set_id)
|
|
@@ -234,7 +230,7 @@ class AssetCRUD(ResourceCRUD[str, AssetWrite, Asset]):
|
|
|
234
230
|
# This is only included when the asset is downloaded/migrated with aggregated properties
|
|
235
231
|
aggregates = (
|
|
236
232
|
resource.aggregates.dump()
|
|
237
|
-
if isinstance(resource.aggregates,
|
|
233
|
+
if isinstance(resource.aggregates, AssetAggregateItem)
|
|
238
234
|
else resource.aggregates
|
|
239
235
|
)
|
|
240
236
|
if "path" in aggregates:
|
|
@@ -372,7 +368,7 @@ class SequenceCRUD(ResourceCRUD[str, SequenceWrite, CDFSequence]):
|
|
|
372
368
|
if "dataSetExternalId" in item:
|
|
373
369
|
yield DataSetsCRUD, item["dataSetExternalId"]
|
|
374
370
|
if "assetExternalId" in item:
|
|
375
|
-
yield AssetCRUD, item["assetExternalId"]
|
|
371
|
+
yield AssetCRUD, ExternalId(external_id=item["assetExternalId"])
|
|
376
372
|
|
|
377
373
|
|
|
378
374
|
@final
|
|
@@ -596,7 +592,7 @@ class EventCRUD(ResourceCRUD[str, EventWrite, Event]):
|
|
|
596
592
|
yield DataSetsCRUD, item["dataSetExternalId"]
|
|
597
593
|
for asset_id in item.get("assetExternalIds", []):
|
|
598
594
|
if isinstance(asset_id, str):
|
|
599
|
-
yield AssetCRUD, asset_id
|
|
595
|
+
yield AssetCRUD, ExternalId(external_id=asset_id)
|
|
600
596
|
|
|
601
597
|
def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> EventWrite:
|
|
602
598
|
if ds_external_id := resource.get("dataSetExternalId", None):
|
|
@@ -8,6 +8,7 @@ from cognite.client.data_classes.data_modeling import NodeApplyResultList, NodeI
|
|
|
8
8
|
from cognite.client.exceptions import CogniteAPIError
|
|
9
9
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
10
10
|
|
|
11
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
|
|
11
12
|
from cognite_toolkit._cdf_tk.client.data_classes.infield import (
|
|
12
13
|
InFieldCDMLocationConfig,
|
|
13
14
|
InfieldLocationConfig,
|
|
@@ -139,7 +140,7 @@ class InfieldV1CRUD(ResourceCRUD[str, APMConfigWrite, APMConfig]):
|
|
|
139
140
|
yield SpaceCRUD, customer_data_space_id
|
|
140
141
|
for config in cls._get_root_location_configurations(item) or []:
|
|
141
142
|
if isinstance(asset_external_id := config.get("assetExternalId"), str):
|
|
142
|
-
yield AssetCRUD, asset_external_id
|
|
143
|
+
yield AssetCRUD, ExternalId(external_id=asset_external_id)
|
|
143
144
|
if isinstance(data_set_external_id := config.get("dataSetExternalId"), str):
|
|
144
145
|
yield DataSetsCRUD, data_set_external_id
|
|
145
146
|
if isinstance(app_data_instance_space := config.get("appDataInstanceSpace"), str):
|
|
@@ -162,7 +163,7 @@ class InfieldV1CRUD(ResourceCRUD[str, APMConfigWrite, APMConfig]):
|
|
|
162
163
|
yield DataSetsCRUD, data_set_external_id
|
|
163
164
|
for asset_external_id in filter_.get("assetSubtreeExternalIds", []):
|
|
164
165
|
if isinstance(asset_external_id, str):
|
|
165
|
-
yield AssetCRUD, asset_external_id
|
|
166
|
+
yield AssetCRUD, ExternalId(external_id=asset_external_id)
|
|
166
167
|
if app_data_instance_space := filter_.get("appDataInstanceSpace"):
|
|
167
168
|
if isinstance(app_data_instance_space, str):
|
|
168
169
|
yield SpaceCRUD, app_data_instance_space
|
|
@@ -267,7 +268,10 @@ class InFieldLocationConfigCRUD(ResourceCRUD[TypedNodeIdentifier, InfieldLocatio
|
|
|
267
268
|
|
|
268
269
|
@classmethod
|
|
269
270
|
def dump_id(cls, id: TypedNodeIdentifier) -> dict[str, Any]:
|
|
270
|
-
return
|
|
271
|
+
return {
|
|
272
|
+
"space": id.space,
|
|
273
|
+
"externalId": id.external_id,
|
|
274
|
+
}
|
|
271
275
|
|
|
272
276
|
@classmethod
|
|
273
277
|
def get_required_capability(
|
|
@@ -368,7 +372,10 @@ class InFieldCDMLocationConfigCRUD(
|
|
|
368
372
|
|
|
369
373
|
@classmethod
|
|
370
374
|
def dump_id(cls, id: TypedNodeIdentifier) -> dict[str, Any]:
|
|
371
|
-
return
|
|
375
|
+
return {
|
|
376
|
+
"space": id.space,
|
|
377
|
+
"externalId": id.external_id,
|
|
378
|
+
}
|
|
372
379
|
|
|
373
380
|
@classmethod
|
|
374
381
|
def get_required_capability(
|
|
@@ -33,6 +33,7 @@ from cognite.client.utils._time import convert_data_modelling_timestamp
|
|
|
33
33
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
34
34
|
from rich import print
|
|
35
35
|
|
|
36
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
|
|
36
37
|
from cognite_toolkit._cdf_tk.client.data_classes.legacy.extendable_cognite_file import (
|
|
37
38
|
ExtendableCogniteFile,
|
|
38
39
|
ExtendableCogniteFileApply,
|
|
@@ -118,7 +119,7 @@ class FileMetadataCRUD(ResourceContainerCRUD[str, FileMetadataWrite, FileMetadat
|
|
|
118
119
|
elif isinstance(label, str):
|
|
119
120
|
yield LabelCRUD, label
|
|
120
121
|
for asset_external_id in item.get("assetExternalIds", []):
|
|
121
|
-
yield AssetCRUD, asset_external_id
|
|
122
|
+
yield AssetCRUD, ExternalId(external_id=asset_external_id)
|
|
122
123
|
|
|
123
124
|
def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> FileMetadataWrite:
|
|
124
125
|
if resource.get("dataSetExternalId") is not None:
|
|
@@ -7,6 +7,7 @@ from cognite.client.data_classes.capabilities import Capability, LocationFilters
|
|
|
7
7
|
from cognite.client.data_classes.data_modeling import DataModelId, ViewId
|
|
8
8
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
9
9
|
|
|
10
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
|
|
10
11
|
from cognite_toolkit._cdf_tk.client.data_classes.legacy.location_filters import (
|
|
11
12
|
LocationFilter,
|
|
12
13
|
LocationFilterList,
|
|
@@ -239,14 +240,14 @@ class LocationFilterCRUD(ResourceCRUD[str, LocationFilterWrite, LocationFilter])
|
|
|
239
240
|
yield DataSetsCRUD, data_set_external_id
|
|
240
241
|
for asset in asset_centric.get("assetSubtreeIds", []):
|
|
241
242
|
if "externalId" in asset:
|
|
242
|
-
yield AssetCRUD, asset["externalId"]
|
|
243
|
+
yield AssetCRUD, ExternalId(external_id=asset["externalId"])
|
|
243
244
|
for subfilter_name in cls.subfilter_names:
|
|
244
245
|
subfilter = asset_centric.get(subfilter_name, {})
|
|
245
246
|
for data_set_external_id in subfilter.get("dataSetExternalIds", []):
|
|
246
247
|
yield DataSetsCRUD, data_set_external_id
|
|
247
248
|
for asset in subfilter.get("assetSubtreeIds", []):
|
|
248
249
|
if "externalId" in asset:
|
|
249
|
-
yield AssetCRUD, asset["externalId"]
|
|
250
|
+
yield AssetCRUD, ExternalId(external_id=asset["externalId"])
|
|
250
251
|
for view in item.get("views", []):
|
|
251
252
|
if in_dict(["space", "externalId", "version"], view):
|
|
252
253
|
yield ViewCRUD, ViewId(view["space"], view["externalId"], view["version"])
|
|
@@ -11,6 +11,7 @@ from cognite.client.data_classes.capabilities import Capability
|
|
|
11
11
|
from cognite.client.exceptions import CogniteAPIError, CogniteNotFoundError
|
|
12
12
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
13
13
|
|
|
14
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
|
|
14
15
|
from cognite_toolkit._cdf_tk.cruds._base_cruds import ResourceCRUD
|
|
15
16
|
from cognite_toolkit._cdf_tk.resource_classes import RelationshipYAML
|
|
16
17
|
|
|
@@ -123,7 +124,7 @@ class RelationshipCRUD(ResourceCRUD[str, RelationshipWrite, Relationship]):
|
|
|
123
124
|
if isinstance(id_value, str) and isinstance(type_value, str):
|
|
124
125
|
type_value = type_value.strip().casefold()
|
|
125
126
|
if type_value == "asset":
|
|
126
|
-
yield AssetCRUD, id_value
|
|
127
|
+
yield AssetCRUD, ExternalId(external_id=id_value)
|
|
127
128
|
elif type_value == "sequence":
|
|
128
129
|
yield SequenceCRUD, id_value
|
|
129
130
|
elif type_value == "timeseries":
|
|
@@ -9,9 +9,9 @@ from cognite_toolkit._cdf_tk.client.data_classes.streams import (
|
|
|
9
9
|
StreamResponse,
|
|
10
10
|
StreamResponseList,
|
|
11
11
|
)
|
|
12
|
+
from cognite_toolkit._cdf_tk.client.http_client import ToolkitAPIError
|
|
12
13
|
from cognite_toolkit._cdf_tk.cruds._base_cruds import ResourceCRUD
|
|
13
14
|
from cognite_toolkit._cdf_tk.resource_classes import StreamYAML
|
|
14
|
-
from cognite_toolkit._cdf_tk.utils.http_client import ToolkitAPIError
|
|
15
15
|
|
|
16
16
|
from .datamodel import ContainerCRUD
|
|
17
17
|
|
|
@@ -23,6 +23,7 @@ from cognite.client.data_classes.datapoints_subscriptions import TimeSeriesIDLis
|
|
|
23
23
|
from cognite.client.exceptions import CogniteAPIError, CogniteNotFoundError
|
|
24
24
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
25
25
|
|
|
26
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
|
|
26
27
|
from cognite_toolkit._cdf_tk.constants import MAX_TIMESTAMP_MS, MIN_TIMESTAMP_MS
|
|
27
28
|
from cognite_toolkit._cdf_tk.cruds._base_cruds import ResourceContainerCRUD, ResourceCRUD
|
|
28
29
|
from cognite_toolkit._cdf_tk.exceptions import (
|
|
@@ -97,7 +98,7 @@ class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
|
|
|
97
98
|
for security_category in item["securityCategoryNames"]:
|
|
98
99
|
yield SecurityCategoryCRUD, security_category
|
|
99
100
|
if "assetExternalId" in item:
|
|
100
|
-
yield AssetCRUD, item["assetExternalId"]
|
|
101
|
+
yield AssetCRUD, ExternalId(external_id=item["assetExternalId"])
|
|
101
102
|
|
|
102
103
|
def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> TimeSeriesWrite:
|
|
103
104
|
if ds_external_id := resource.pop("dataSetExternalId", None):
|
|
@@ -7,10 +7,10 @@ from cognite_toolkit._cdf_tk.client.data_classes.legacy.canvas import (
|
|
|
7
7
|
IndustrialCanvasApply,
|
|
8
8
|
)
|
|
9
9
|
from cognite_toolkit._cdf_tk.client.data_classes.legacy.charts import Chart, ChartList, ChartWrite
|
|
10
|
+
from cognite_toolkit._cdf_tk.client.http_client import HTTPClient, HTTPMessage, SimpleBodyRequest
|
|
10
11
|
from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError
|
|
11
12
|
from cognite_toolkit._cdf_tk.tk_warnings import HighSeverityWarning, MediumSeverityWarning
|
|
12
13
|
from cognite_toolkit._cdf_tk.utils.collection import chunker_sequence
|
|
13
|
-
from cognite_toolkit._cdf_tk.utils.http_client import HTTPClient, HTTPMessage, SimpleBodyRequest
|
|
14
14
|
from cognite_toolkit._cdf_tk.utils.useful_types import JsonVal
|
|
15
15
|
|
|
16
16
|
from ._base import Page, UploadableStorageIO, UploadItem
|
|
@@ -4,10 +4,6 @@ from collections.abc import Iterable, Sequence
|
|
|
4
4
|
from typing import Any, ClassVar, Generic
|
|
5
5
|
|
|
6
6
|
from cognite.client.data_classes import (
|
|
7
|
-
AggregateResultItem,
|
|
8
|
-
Asset,
|
|
9
|
-
AssetList,
|
|
10
|
-
AssetWrite,
|
|
11
7
|
Event,
|
|
12
8
|
EventList,
|
|
13
9
|
EventWrite,
|
|
@@ -21,6 +17,8 @@ from cognite.client.data_classes import (
|
|
|
21
17
|
)
|
|
22
18
|
|
|
23
19
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
20
|
+
from cognite_toolkit._cdf_tk.client.data_classes.asset import AssetAggregateItem, AssetRequest, AssetResponse
|
|
21
|
+
from cognite_toolkit._cdf_tk.client.data_classes.identifiers import InternalId
|
|
24
22
|
from cognite_toolkit._cdf_tk.cruds import (
|
|
25
23
|
AssetCRUD,
|
|
26
24
|
DataSetsCRUD,
|
|
@@ -42,10 +40,10 @@ from cognite_toolkit._cdf_tk.utils.cdf import metadata_key_counts
|
|
|
42
40
|
from cognite_toolkit._cdf_tk.utils.fileio import FileReader, SchemaColumn
|
|
43
41
|
from cognite_toolkit._cdf_tk.utils.fileio._readers import TableReader
|
|
44
42
|
from cognite_toolkit._cdf_tk.utils.useful_types import (
|
|
45
|
-
AssetCentricResource,
|
|
46
43
|
AssetCentricType,
|
|
47
44
|
JsonVal,
|
|
48
45
|
)
|
|
46
|
+
from cognite_toolkit._cdf_tk.utils.useful_types2 import AssetCentricResource
|
|
49
47
|
|
|
50
48
|
from ._base import (
|
|
51
49
|
ConfigurableStorageIO,
|
|
@@ -112,12 +110,14 @@ class AssetCentricIO(
|
|
|
112
110
|
return asset_subtree_external_ids, data_set_external_ids
|
|
113
111
|
|
|
114
112
|
def _collect_dependencies(
|
|
115
|
-
self,
|
|
113
|
+
self,
|
|
114
|
+
resources: Sequence[AssetResponse] | FileMetadataList | TimeSeriesList | EventList,
|
|
115
|
+
selector: AssetCentricSelector,
|
|
116
116
|
) -> None:
|
|
117
117
|
for resource in resources:
|
|
118
118
|
if resource.data_set_id:
|
|
119
119
|
self._downloaded_data_sets_by_selector[selector].add(resource.data_set_id)
|
|
120
|
-
if isinstance(resource,
|
|
120
|
+
if isinstance(resource, AssetResponse | FileMetadata):
|
|
121
121
|
for label in resource.labels or []:
|
|
122
122
|
if isinstance(label, str):
|
|
123
123
|
self._downloaded_labels_by_selector[selector].add(label)
|
|
@@ -149,7 +149,7 @@ class AssetCentricIO(
|
|
|
149
149
|
def create_internal_identifier(cls, internal_id: int, project: str) -> str:
|
|
150
150
|
return f"INTERNAL_ID_project_{project}_{internal_id!s}"
|
|
151
151
|
|
|
152
|
-
def _populate_data_set_id_cache(self, chunk: Sequence[
|
|
152
|
+
def _populate_data_set_id_cache(self, chunk: Sequence[AssetResponse | FileMetadata | TimeSeries | Event]) -> None:
|
|
153
153
|
data_set_ids = {item.data_set_id for item in chunk if item.data_set_id is not None}
|
|
154
154
|
self.client.lookup.data_sets.external_id(list(data_set_ids))
|
|
155
155
|
|
|
@@ -249,7 +249,7 @@ class UploadableAssetCentricIO(
|
|
|
249
249
|
)
|
|
250
250
|
|
|
251
251
|
|
|
252
|
-
class AssetIO(UploadableAssetCentricIO[
|
|
252
|
+
class AssetIO(UploadableAssetCentricIO[AssetResponse, AssetRequest]):
|
|
253
253
|
KIND = "Assets"
|
|
254
254
|
RESOURCE_TYPE = "asset"
|
|
255
255
|
SUPPORTED_DOWNLOAD_FORMATS = frozenset({".parquet", ".csv", ".ndjson"})
|
|
@@ -261,7 +261,7 @@ class AssetIO(UploadableAssetCentricIO[Asset, AssetWrite]):
|
|
|
261
261
|
super().__init__(client)
|
|
262
262
|
self._crud = AssetCRUD.create_loader(self.client)
|
|
263
263
|
|
|
264
|
-
def as_id(self, item:
|
|
264
|
+
def as_id(self, item: AssetResponse) -> str:
|
|
265
265
|
return item.external_id if item.external_id is not None else self._create_identifier(item.id)
|
|
266
266
|
|
|
267
267
|
def _get_aggregator(self) -> AssetCentricAggregator:
|
|
@@ -311,21 +311,25 @@ class AssetIO(UploadableAssetCentricIO[Asset, AssetWrite]):
|
|
|
311
311
|
|
|
312
312
|
def stream_data(self, selector: AssetCentricSelector, limit: int | None = None) -> Iterable[Page]:
|
|
313
313
|
asset_subtree_external_ids, data_set_external_ids = self._get_hierarchy_dataset_pair(selector)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
self._collect_dependencies(
|
|
325
|
-
yield Page(worker_id="main", items=
|
|
314
|
+
cursor: str | None = None
|
|
315
|
+
total_count = 0
|
|
316
|
+
while True:
|
|
317
|
+
page = self.client.tool.assets.iterate(
|
|
318
|
+
aggregated_properties=True,
|
|
319
|
+
data_set_external_ids=data_set_external_ids,
|
|
320
|
+
asset_subtree_external_ids=asset_subtree_external_ids,
|
|
321
|
+
limit=self.CHUNK_SIZE,
|
|
322
|
+
cursor=cursor,
|
|
323
|
+
)
|
|
324
|
+
self._collect_dependencies(page.items, selector)
|
|
325
|
+
yield Page(worker_id="main", items=page.items)
|
|
326
|
+
total_count += len(page.items)
|
|
327
|
+
if page.next_cursor is None or (limit is not None and total_count >= limit):
|
|
328
|
+
break
|
|
329
|
+
cursor = page.next_cursor
|
|
326
330
|
|
|
327
331
|
def data_to_json_chunk(
|
|
328
|
-
self, data_chunk: Sequence[
|
|
332
|
+
self, data_chunk: Sequence[AssetResponse], selector: AssetCentricSelector | None = None
|
|
329
333
|
) -> list[dict[str, JsonVal]]:
|
|
330
334
|
# Ensure data sets are looked up to populate cache.
|
|
331
335
|
# This is to avoid looking up each data set id individually in the .dump_resource call.
|
|
@@ -333,19 +337,18 @@ class AssetIO(UploadableAssetCentricIO[Asset, AssetWrite]):
|
|
|
333
337
|
asset_ids = {
|
|
334
338
|
segment["id"]
|
|
335
339
|
for item in data_chunk
|
|
336
|
-
if isinstance(item.aggregates,
|
|
337
|
-
for segment in item.aggregates.path
|
|
338
|
-
if "id" in segment
|
|
340
|
+
if isinstance(item.aggregates, AssetAggregateItem)
|
|
341
|
+
for segment in item.aggregates.path
|
|
339
342
|
}
|
|
340
343
|
self.client.lookup.assets.external_id(list(asset_ids))
|
|
341
344
|
|
|
342
345
|
return [self._crud.dump_resource(item) for item in data_chunk]
|
|
343
346
|
|
|
344
|
-
def json_to_resource(self, item_json: dict[str, JsonVal]) ->
|
|
347
|
+
def json_to_resource(self, item_json: dict[str, JsonVal]) -> AssetRequest:
|
|
345
348
|
return self._crud.load_resource(item_json)
|
|
346
349
|
|
|
347
|
-
def retrieve(self, ids: Sequence[int]) ->
|
|
348
|
-
return self.client.assets.
|
|
350
|
+
def retrieve(self, ids: Sequence[int]) -> list[AssetResponse]:
|
|
351
|
+
return self.client.tool.assets.retrieve(InternalId.from_ids(ids))
|
|
349
352
|
|
|
350
353
|
@classmethod
|
|
351
354
|
def read_chunks(
|
|
@@ -4,11 +4,11 @@ from dataclasses import dataclass
|
|
|
4
4
|
from typing import ClassVar, Generic, Literal, TypeVar
|
|
5
5
|
|
|
6
6
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
7
|
+
from cognite_toolkit._cdf_tk.client.http_client import HTTPClient, HTTPMessage, ItemsRequest
|
|
7
8
|
from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError
|
|
8
9
|
from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
|
|
9
10
|
from cognite_toolkit._cdf_tk.utils.collection import chunker
|
|
10
11
|
from cognite_toolkit._cdf_tk.utils.fileio import MultiFileReader, SchemaColumn
|
|
11
|
-
from cognite_toolkit._cdf_tk.utils.http_client import HTTPClient, HTTPMessage, ItemsRequest
|
|
12
12
|
from cognite_toolkit._cdf_tk.utils.useful_types import JsonVal
|
|
13
13
|
|
|
14
14
|
from .selectors import DataSelector
|
|
@@ -15,6 +15,13 @@ from cognite.client.data_classes.filters import Exists
|
|
|
15
15
|
from cognite.client.data_classes.time_series import TimeSeriesProperty
|
|
16
16
|
|
|
17
17
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
18
|
+
from cognite_toolkit._cdf_tk.client.http_client import (
|
|
19
|
+
DataBodyRequest,
|
|
20
|
+
HTTPClient,
|
|
21
|
+
HTTPMessage,
|
|
22
|
+
SimpleBodyRequest,
|
|
23
|
+
SuccessResponse,
|
|
24
|
+
)
|
|
18
25
|
from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError
|
|
19
26
|
from cognite_toolkit._cdf_tk.tk_warnings import HighSeverityWarning
|
|
20
27
|
from cognite_toolkit._cdf_tk.utils import humanize_collection
|
|
@@ -26,13 +33,6 @@ from cognite_toolkit._cdf_tk.utils.dtype_conversion import (
|
|
|
26
33
|
)
|
|
27
34
|
from cognite_toolkit._cdf_tk.utils.fileio import SchemaColumn
|
|
28
35
|
from cognite_toolkit._cdf_tk.utils.fileio._readers import MultiFileReader
|
|
29
|
-
from cognite_toolkit._cdf_tk.utils.http_client import (
|
|
30
|
-
DataBodyRequest,
|
|
31
|
-
HTTPClient,
|
|
32
|
-
HTTPMessage,
|
|
33
|
-
SimpleBodyRequest,
|
|
34
|
-
SuccessResponse,
|
|
35
|
-
)
|
|
36
36
|
from cognite_toolkit._cdf_tk.utils.useful_types import JsonVal
|
|
37
37
|
|
|
38
38
|
from ._base import Page, TableStorageIO, TableUploadableStorageIO, UploadItem
|