cognite-toolkit 0.6.97__py3-none-any.whl → 0.7.39__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.py +21 -23
- cognite_toolkit/_cdf_tk/apps/__init__.py +4 -0
- cognite_toolkit/_cdf_tk/apps/_core_app.py +19 -5
- cognite_toolkit/_cdf_tk/apps/_data_app.py +1 -1
- cognite_toolkit/_cdf_tk/apps/_dev_app.py +86 -0
- cognite_toolkit/_cdf_tk/apps/_download_app.py +693 -25
- cognite_toolkit/_cdf_tk/apps/_dump_app.py +44 -102
- cognite_toolkit/_cdf_tk/apps/_import_app.py +41 -0
- cognite_toolkit/_cdf_tk/apps/_landing_app.py +18 -4
- cognite_toolkit/_cdf_tk/apps/_migrate_app.py +424 -9
- cognite_toolkit/_cdf_tk/apps/_modules_app.py +0 -3
- cognite_toolkit/_cdf_tk/apps/_purge.py +15 -43
- cognite_toolkit/_cdf_tk/apps/_run.py +11 -0
- cognite_toolkit/_cdf_tk/apps/_upload_app.py +45 -6
- cognite_toolkit/_cdf_tk/builders/__init__.py +2 -2
- cognite_toolkit/_cdf_tk/builders/_base.py +28 -42
- cognite_toolkit/_cdf_tk/builders/_raw.py +1 -1
- cognite_toolkit/_cdf_tk/cdf_toml.py +20 -1
- cognite_toolkit/_cdf_tk/client/_toolkit_client.py +32 -12
- cognite_toolkit/_cdf_tk/client/api/infield.py +114 -17
- cognite_toolkit/_cdf_tk/client/api/{canvas.py → legacy/canvas.py} +15 -7
- cognite_toolkit/_cdf_tk/client/api/{charts.py → legacy/charts.py} +1 -1
- cognite_toolkit/_cdf_tk/client/api/{extended_data_modeling.py → legacy/extended_data_modeling.py} +1 -1
- cognite_toolkit/_cdf_tk/client/api/{extended_files.py → legacy/extended_files.py} +2 -2
- cognite_toolkit/_cdf_tk/client/api/{extended_functions.py → legacy/extended_functions.py} +15 -18
- cognite_toolkit/_cdf_tk/client/api/{extended_raw.py → legacy/extended_raw.py} +1 -1
- cognite_toolkit/_cdf_tk/client/api/{extended_timeseries.py → legacy/extended_timeseries.py} +5 -2
- cognite_toolkit/_cdf_tk/client/api/{location_filters.py → legacy/location_filters.py} +1 -1
- cognite_toolkit/_cdf_tk/client/api/legacy/robotics/__init__.py +8 -0
- cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/capabilities.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/data_postprocessing.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/frames.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/locations.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/maps.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/robots.py +2 -2
- cognite_toolkit/_cdf_tk/client/api/{search_config.py → legacy/search_config.py} +5 -1
- cognite_toolkit/_cdf_tk/client/api/migration.py +177 -4
- cognite_toolkit/_cdf_tk/client/api/project.py +9 -8
- cognite_toolkit/_cdf_tk/client/api/search.py +2 -2
- cognite_toolkit/_cdf_tk/client/api/streams.py +88 -0
- cognite_toolkit/_cdf_tk/client/api/three_d.py +384 -0
- cognite_toolkit/_cdf_tk/client/data_classes/api_classes.py +13 -0
- cognite_toolkit/_cdf_tk/client/data_classes/base.py +37 -33
- cognite_toolkit/_cdf_tk/client/data_classes/charts_data.py +95 -213
- cognite_toolkit/_cdf_tk/client/data_classes/infield.py +32 -18
- cognite_toolkit/_cdf_tk/client/data_classes/instance_api.py +18 -13
- cognite_toolkit/_cdf_tk/client/data_classes/legacy/__init__.py +0 -0
- cognite_toolkit/_cdf_tk/client/data_classes/{canvas.py → legacy/canvas.py} +47 -4
- cognite_toolkit/_cdf_tk/client/data_classes/{charts.py → legacy/charts.py} +3 -3
- cognite_toolkit/_cdf_tk/client/data_classes/{migration.py → legacy/migration.py} +10 -2
- cognite_toolkit/_cdf_tk/client/data_classes/streams.py +90 -0
- cognite_toolkit/_cdf_tk/client/data_classes/three_d.py +112 -0
- cognite_toolkit/_cdf_tk/client/testing.py +42 -18
- cognite_toolkit/_cdf_tk/commands/__init__.py +7 -6
- cognite_toolkit/_cdf_tk/commands/_changes.py +3 -42
- cognite_toolkit/_cdf_tk/commands/_download.py +21 -11
- cognite_toolkit/_cdf_tk/commands/_migrate/__init__.py +0 -2
- cognite_toolkit/_cdf_tk/commands/_migrate/command.py +22 -20
- cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +140 -92
- cognite_toolkit/_cdf_tk/commands/_migrate/creators.py +1 -1
- cognite_toolkit/_cdf_tk/commands/_migrate/data_classes.py +108 -26
- cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +448 -45
- cognite_toolkit/_cdf_tk/commands/_migrate/data_model.py +1 -0
- cognite_toolkit/_cdf_tk/commands/_migrate/default_mappings.py +6 -6
- cognite_toolkit/_cdf_tk/commands/_migrate/issues.py +52 -1
- cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +377 -11
- cognite_toolkit/_cdf_tk/commands/_migrate/selectors.py +9 -4
- cognite_toolkit/_cdf_tk/commands/_profile.py +1 -1
- cognite_toolkit/_cdf_tk/commands/_purge.py +36 -39
- cognite_toolkit/_cdf_tk/commands/_questionary_style.py +16 -0
- cognite_toolkit/_cdf_tk/commands/_upload.py +109 -86
- cognite_toolkit/_cdf_tk/commands/about.py +221 -0
- cognite_toolkit/_cdf_tk/commands/auth.py +19 -12
- cognite_toolkit/_cdf_tk/commands/build_cmd.py +16 -62
- cognite_toolkit/_cdf_tk/commands/build_v2/__init__.py +0 -0
- cognite_toolkit/_cdf_tk/commands/build_v2/build_cmd.py +241 -0
- cognite_toolkit/_cdf_tk/commands/build_v2/build_input.py +85 -0
- cognite_toolkit/_cdf_tk/commands/build_v2/build_issues.py +27 -0
- cognite_toolkit/_cdf_tk/commands/clean.py +63 -16
- cognite_toolkit/_cdf_tk/commands/deploy.py +20 -17
- cognite_toolkit/_cdf_tk/commands/dump_resource.py +10 -8
- cognite_toolkit/_cdf_tk/commands/init.py +225 -3
- cognite_toolkit/_cdf_tk/commands/modules.py +20 -44
- cognite_toolkit/_cdf_tk/commands/pull.py +6 -19
- cognite_toolkit/_cdf_tk/commands/resources.py +179 -0
- cognite_toolkit/_cdf_tk/commands/run.py +1 -1
- cognite_toolkit/_cdf_tk/constants.py +20 -1
- cognite_toolkit/_cdf_tk/cruds/__init__.py +19 -5
- cognite_toolkit/_cdf_tk/cruds/_base_cruds.py +14 -70
- cognite_toolkit/_cdf_tk/cruds/_data_cruds.py +10 -19
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/__init__.py +4 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/agent.py +11 -9
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/auth.py +5 -15
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +45 -44
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/configuration.py +5 -12
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/data_organization.py +4 -13
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/datamodel.py +206 -67
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/extraction_pipeline.py +6 -18
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +126 -35
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +7 -28
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/function.py +23 -30
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/hosted_extractors.py +12 -30
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/industrial_tool.py +4 -8
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/location.py +4 -16
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/migration.py +5 -13
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/raw.py +5 -11
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +3 -8
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/robotics.py +16 -45
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +94 -0
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/three_d_model.py +3 -7
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +5 -15
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/transformation.py +75 -32
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/workflow.py +20 -40
- cognite_toolkit/_cdf_tk/cruds/_worker.py +24 -36
- cognite_toolkit/_cdf_tk/data_classes/_module_toml.py +1 -0
- cognite_toolkit/_cdf_tk/feature_flags.py +16 -36
- cognite_toolkit/_cdf_tk/plugins.py +2 -1
- cognite_toolkit/_cdf_tk/resource_classes/__init__.py +4 -0
- cognite_toolkit/_cdf_tk/resource_classes/capabilities.py +12 -0
- cognite_toolkit/_cdf_tk/resource_classes/functions.py +3 -1
- cognite_toolkit/_cdf_tk/resource_classes/infield_cdm_location_config.py +109 -0
- cognite_toolkit/_cdf_tk/resource_classes/migration.py +8 -17
- cognite_toolkit/_cdf_tk/resource_classes/search_config.py +1 -1
- cognite_toolkit/_cdf_tk/resource_classes/streams.py +29 -0
- cognite_toolkit/_cdf_tk/resource_classes/workflow_version.py +164 -5
- cognite_toolkit/_cdf_tk/storageio/__init__.py +9 -21
- cognite_toolkit/_cdf_tk/storageio/_annotations.py +19 -16
- cognite_toolkit/_cdf_tk/storageio/_applications.py +340 -28
- cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +67 -104
- cognite_toolkit/_cdf_tk/storageio/_base.py +61 -29
- cognite_toolkit/_cdf_tk/storageio/_datapoints.py +276 -20
- cognite_toolkit/_cdf_tk/storageio/_file_content.py +435 -0
- cognite_toolkit/_cdf_tk/storageio/_instances.py +35 -3
- cognite_toolkit/_cdf_tk/storageio/_raw.py +26 -0
- cognite_toolkit/_cdf_tk/storageio/selectors/__init__.py +71 -4
- cognite_toolkit/_cdf_tk/storageio/selectors/_base.py +14 -2
- cognite_toolkit/_cdf_tk/storageio/selectors/_canvas.py +14 -0
- cognite_toolkit/_cdf_tk/storageio/selectors/_charts.py +14 -0
- cognite_toolkit/_cdf_tk/storageio/selectors/_datapoints.py +23 -3
- cognite_toolkit/_cdf_tk/storageio/selectors/_file_content.py +164 -0
- cognite_toolkit/_cdf_tk/storageio/selectors/_three_d.py +34 -0
- cognite_toolkit/_cdf_tk/tk_warnings/other.py +4 -0
- cognite_toolkit/_cdf_tk/tracker.py +2 -2
- cognite_toolkit/_cdf_tk/utils/cdf.py +1 -1
- cognite_toolkit/_cdf_tk/utils/dtype_conversion.py +9 -3
- cognite_toolkit/_cdf_tk/utils/fileio/__init__.py +2 -0
- cognite_toolkit/_cdf_tk/utils/fileio/_base.py +5 -1
- cognite_toolkit/_cdf_tk/utils/fileio/_readers.py +112 -20
- cognite_toolkit/_cdf_tk/utils/fileio/_writers.py +15 -15
- cognite_toolkit/_cdf_tk/utils/http_client/__init__.py +28 -0
- cognite_toolkit/_cdf_tk/utils/http_client/_client.py +285 -18
- cognite_toolkit/_cdf_tk/utils/http_client/_data_classes.py +56 -4
- cognite_toolkit/_cdf_tk/utils/http_client/_data_classes2.py +247 -0
- cognite_toolkit/_cdf_tk/utils/http_client/_tracker.py +5 -2
- cognite_toolkit/_cdf_tk/utils/interactive_select.py +60 -18
- cognite_toolkit/_cdf_tk/utils/sql_parser.py +2 -3
- cognite_toolkit/_cdf_tk/utils/useful_types.py +6 -2
- cognite_toolkit/_cdf_tk/validation.py +83 -1
- 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 +5 -4
- cognite_toolkit/_version.py +1 -1
- cognite_toolkit/config.dev.yaml +13 -0
- {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.39.dist-info}/METADATA +24 -24
- cognite_toolkit-0.7.39.dist-info/RECORD +322 -0
- cognite_toolkit-0.7.39.dist-info/WHEEL +4 -0
- {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.39.dist-info}/entry_points.txt +1 -0
- cognite_toolkit/_cdf_tk/client/api/robotics/__init__.py +0 -3
- cognite_toolkit/_cdf_tk/commands/_migrate/canvas.py +0 -201
- cognite_toolkit/_cdf_tk/commands/dump_data.py +0 -489
- cognite_toolkit/_cdf_tk/commands/featureflag.py +0 -27
- cognite_toolkit/_cdf_tk/prototypes/import_app.py +0 -41
- cognite_toolkit/_cdf_tk/utils/table_writers.py +0 -434
- cognite_toolkit-0.6.97.dist-info/RECORD +0 -306
- cognite_toolkit-0.6.97.dist-info/WHEEL +0 -4
- cognite_toolkit-0.6.97.dist-info/licenses/LICENSE +0 -18
- /cognite_toolkit/_cdf_tk/{prototypes/commands → client/api/legacy}/__init__.py +0 -0
- /cognite_toolkit/_cdf_tk/client/api/{dml.py → legacy/dml.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/api/{fixed_transformations.py → legacy/fixed_transformations.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/api.py +0 -0
- /cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/utlis.py +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{apm_config_v1.py → legacy/apm_config_v1.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{extendable_cognite_file.py → legacy/extendable_cognite_file.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{extended_filemetadata.py → legacy/extended_filemetadata.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{extended_filemetdata.py → legacy/extended_filemetdata.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{extended_timeseries.py → legacy/extended_timeseries.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{functions.py → legacy/functions.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{graphql_data_models.py → legacy/graphql_data_models.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{instances.py → legacy/instances.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{location_filters.py → legacy/location_filters.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{pending_instances_ids.py → legacy/pending_instances_ids.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{project.py → legacy/project.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{raw.py → legacy/raw.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{robotics.py → legacy/robotics.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{search_config.py → legacy/search_config.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{sequences.py → legacy/sequences.py} +0 -0
- /cognite_toolkit/_cdf_tk/client/data_classes/{streamlit_.py → legacy/streamlit_.py} +0 -0
- /cognite_toolkit/_cdf_tk/{prototypes/commands/import_.py → commands/_import_cmd.py} +0 -0
|
@@ -1,29 +1,59 @@
|
|
|
1
|
-
from collections.abc import Iterator, Mapping, Sequence
|
|
2
|
-
from typing import ClassVar, cast
|
|
1
|
+
from collections.abc import Iterable, Iterator, Mapping, Sequence
|
|
2
|
+
from typing import ClassVar, Literal, cast
|
|
3
3
|
|
|
4
|
-
from cognite.client.data_classes
|
|
4
|
+
from cognite.client.data_classes import Annotation
|
|
5
|
+
from cognite.client.data_classes.data_modeling import EdgeId, InstanceApply, NodeId
|
|
5
6
|
|
|
6
7
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
7
|
-
from cognite_toolkit._cdf_tk.client.data_classes.pending_instances_ids import PendingInstanceId
|
|
8
|
+
from cognite_toolkit._cdf_tk.client.data_classes.legacy.pending_instances_ids import PendingInstanceId
|
|
9
|
+
from cognite_toolkit._cdf_tk.client.data_classes.three_d import (
|
|
10
|
+
AssetMappingDMRequest,
|
|
11
|
+
AssetMappingResponse,
|
|
12
|
+
ThreeDModelResponse,
|
|
13
|
+
)
|
|
14
|
+
from cognite_toolkit._cdf_tk.commands._migrate.data_classes import ThreeDMigrationRequest
|
|
8
15
|
from cognite_toolkit._cdf_tk.constants import MISSING_EXTERNAL_ID, MISSING_INSTANCE_SPACE
|
|
9
|
-
from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError
|
|
16
|
+
from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError, ToolkitValueError
|
|
10
17
|
from cognite_toolkit._cdf_tk.storageio import (
|
|
18
|
+
AnnotationIO,
|
|
11
19
|
HierarchyIO,
|
|
12
20
|
InstanceIO,
|
|
21
|
+
T_Selector,
|
|
13
22
|
UploadableStorageIO,
|
|
14
23
|
)
|
|
15
24
|
from cognite_toolkit._cdf_tk.storageio._base import Page, UploadItem
|
|
25
|
+
from cognite_toolkit._cdf_tk.storageio.selectors import (
|
|
26
|
+
ThreeDModelFilteredSelector,
|
|
27
|
+
ThreeDModelIdSelector,
|
|
28
|
+
ThreeDSelector,
|
|
29
|
+
)
|
|
30
|
+
from cognite_toolkit._cdf_tk.tk_warnings import MediumSeverityWarning
|
|
16
31
|
from cognite_toolkit._cdf_tk.utils.collection import chunker_sequence
|
|
17
|
-
from cognite_toolkit._cdf_tk.utils.http_client import
|
|
32
|
+
from cognite_toolkit._cdf_tk.utils.http_client import (
|
|
33
|
+
FailedResponse,
|
|
34
|
+
HTTPClient,
|
|
35
|
+
HTTPMessage,
|
|
36
|
+
ItemsRequest,
|
|
37
|
+
SimpleBodyRequest,
|
|
38
|
+
SuccessResponseItems,
|
|
39
|
+
ToolkitAPIError,
|
|
40
|
+
)
|
|
18
41
|
from cognite_toolkit._cdf_tk.utils.useful_types import (
|
|
19
|
-
|
|
42
|
+
AssetCentricKindExtended,
|
|
20
43
|
AssetCentricType,
|
|
21
44
|
JsonVal,
|
|
22
45
|
T_AssetCentricResource,
|
|
23
46
|
)
|
|
24
47
|
|
|
25
|
-
from .data_classes import
|
|
48
|
+
from .data_classes import (
|
|
49
|
+
AnnotationMapping,
|
|
50
|
+
AssetCentricMapping,
|
|
51
|
+
AssetCentricMappingList,
|
|
52
|
+
MigrationMapping,
|
|
53
|
+
MigrationMappingList,
|
|
54
|
+
)
|
|
26
55
|
from .data_model import INSTANCE_SOURCE_VIEW_ID
|
|
56
|
+
from .default_mappings import ASSET_ANNOTATIONS_ID, FILE_ANNOTATIONS_ID
|
|
27
57
|
from .selectors import AssetCentricMigrationSelector, MigrateDataSetSelector, MigrationCSVFileSelector
|
|
28
58
|
|
|
29
59
|
|
|
@@ -37,7 +67,7 @@ class AssetCentricMigrationIO(
|
|
|
37
67
|
CHUNK_SIZE = 1000
|
|
38
68
|
UPLOAD_ENDPOINT = InstanceIO.UPLOAD_ENDPOINT
|
|
39
69
|
|
|
40
|
-
PENDING_INSTANCE_ID_ENDPOINT_BY_KIND: ClassVar[Mapping[
|
|
70
|
+
PENDING_INSTANCE_ID_ENDPOINT_BY_KIND: ClassVar[Mapping[AssetCentricKindExtended, str]] = {
|
|
41
71
|
"TimeSeries": "/timeseries/set-pending-instance-ids",
|
|
42
72
|
"FileMetadata": "/files/set-pending-instance-ids",
|
|
43
73
|
}
|
|
@@ -113,8 +143,8 @@ class AssetCentricMigrationIO(
|
|
|
113
143
|
yield mapping_list
|
|
114
144
|
|
|
115
145
|
@staticmethod
|
|
116
|
-
def _kind_to_resource_type(kind:
|
|
117
|
-
mapping: dict[
|
|
146
|
+
def _kind_to_resource_type(kind: AssetCentricKindExtended) -> AssetCentricType:
|
|
147
|
+
mapping: dict[AssetCentricKindExtended, AssetCentricType] = {
|
|
118
148
|
"Assets": "asset",
|
|
119
149
|
"Events": "event",
|
|
120
150
|
"TimeSeries": "timeseries",
|
|
@@ -199,3 +229,339 @@ class AssetCentricMigrationIO(
|
|
|
199
229
|
pending_instance_id=NodeId(item.space, item.external_id),
|
|
200
230
|
id=id_,
|
|
201
231
|
)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class AnnotationMigrationIO(
|
|
235
|
+
UploadableStorageIO[AssetCentricMigrationSelector, AssetCentricMapping[Annotation], InstanceApply]
|
|
236
|
+
):
|
|
237
|
+
"""IO class for migrating Annotations.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
client: The ToolkitClient to use for CDF interactions.
|
|
241
|
+
instance_space: The instance space to use for the migrated annotations.
|
|
242
|
+
default_asset_annotation_mapping: The default ingestion mapping to use for asset-linked annotations.
|
|
243
|
+
default_file_annotation_mapping: The default ingestion mappingto use for file-linked annotations.
|
|
244
|
+
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
KIND = "AnnotationMigration"
|
|
248
|
+
SUPPORTED_DOWNLOAD_FORMATS = frozenset({".parquet", ".csv", ".ndjson"})
|
|
249
|
+
SUPPORTED_COMPRESSIONS = frozenset({".gz"})
|
|
250
|
+
SUPPORTED_READ_FORMATS = frozenset({".parquet", ".csv", ".ndjson", ".yaml", ".yml"})
|
|
251
|
+
CHUNK_SIZE = 1000
|
|
252
|
+
UPLOAD_ENDPOINT = InstanceIO.UPLOAD_ENDPOINT
|
|
253
|
+
|
|
254
|
+
SUPPORTED_ANNOTATION_TYPES = frozenset({"diagrams.AssetLink", "diagrams.FileLink"})
|
|
255
|
+
|
|
256
|
+
def __init__(
|
|
257
|
+
self,
|
|
258
|
+
client: ToolkitClient,
|
|
259
|
+
instance_space: str | None = None,
|
|
260
|
+
default_asset_annotation_mapping: str | None = None,
|
|
261
|
+
default_file_annotation_mapping: str | None = None,
|
|
262
|
+
) -> None:
|
|
263
|
+
super().__init__(client)
|
|
264
|
+
self.annotation_io = AnnotationIO(client)
|
|
265
|
+
self.instance_space = instance_space
|
|
266
|
+
self.default_asset_annotation_mapping = default_asset_annotation_mapping or ASSET_ANNOTATIONS_ID
|
|
267
|
+
self.default_file_annotation_mapping = default_file_annotation_mapping or FILE_ANNOTATIONS_ID
|
|
268
|
+
|
|
269
|
+
def as_id(self, item: AssetCentricMapping[Annotation]) -> str:
|
|
270
|
+
return f"Annotation_{item.mapping.id}"
|
|
271
|
+
|
|
272
|
+
def count(self, selector: AssetCentricMigrationSelector) -> int | None:
|
|
273
|
+
if isinstance(selector, MigrationCSVFileSelector):
|
|
274
|
+
return len(selector.items)
|
|
275
|
+
else:
|
|
276
|
+
# There is no efficient way to count annotations in CDF.
|
|
277
|
+
return None
|
|
278
|
+
|
|
279
|
+
def stream_data(self, selector: AssetCentricMigrationSelector, limit: int | None = None) -> Iterable[Page]:
|
|
280
|
+
if isinstance(selector, MigrateDataSetSelector):
|
|
281
|
+
iterator = self._stream_from_dataset(selector, limit)
|
|
282
|
+
elif isinstance(selector, MigrationCSVFileSelector):
|
|
283
|
+
iterator = self._stream_from_csv(selector, limit)
|
|
284
|
+
else:
|
|
285
|
+
raise ToolkitNotImplementedError(f"Selector {type(selector)} is not supported for stream_data")
|
|
286
|
+
yield from (Page(worker_id="main", items=items) for items in iterator)
|
|
287
|
+
|
|
288
|
+
def _stream_from_dataset(
|
|
289
|
+
self, selector: MigrateDataSetSelector, limit: int | None = None
|
|
290
|
+
) -> Iterator[Sequence[AssetCentricMapping[Annotation]]]:
|
|
291
|
+
if self.instance_space is None:
|
|
292
|
+
raise ToolkitValueError("Instance space must be provided for dataset-based annotation migration.")
|
|
293
|
+
asset_centric_selector = selector.as_asset_centric_selector()
|
|
294
|
+
for data_chunk in self.annotation_io.stream_data(asset_centric_selector, limit):
|
|
295
|
+
mapping_list = AssetCentricMappingList[Annotation]([])
|
|
296
|
+
for resource in data_chunk.items:
|
|
297
|
+
if resource.annotation_type not in self.SUPPORTED_ANNOTATION_TYPES:
|
|
298
|
+
# This should not happen, as the annotation_io should already filter these out.
|
|
299
|
+
# This is just in case.
|
|
300
|
+
continue
|
|
301
|
+
mapping = AnnotationMapping(
|
|
302
|
+
instance_id=EdgeId(space=self.instance_space, external_id=f"annotation_{resource.id!r}"),
|
|
303
|
+
id=resource.id,
|
|
304
|
+
ingestion_view=self._get_mapping(selector.ingestion_mapping, resource),
|
|
305
|
+
preferred_consumer_view=selector.preferred_consumer_view,
|
|
306
|
+
# The PySDK is poorly typed.
|
|
307
|
+
annotation_type=resource.annotation_type, # type: ignore[arg-type]
|
|
308
|
+
)
|
|
309
|
+
mapping_list.append(AssetCentricMapping(mapping=mapping, resource=resource))
|
|
310
|
+
yield mapping_list
|
|
311
|
+
|
|
312
|
+
def _stream_from_csv(
|
|
313
|
+
self, selector: MigrationCSVFileSelector, limit: int | None = None
|
|
314
|
+
) -> Iterator[Sequence[AssetCentricMapping[Annotation]]]:
|
|
315
|
+
items = selector.items
|
|
316
|
+
if limit is not None:
|
|
317
|
+
items = MigrationMappingList(items[:limit])
|
|
318
|
+
chunk: list[AssetCentricMapping[Annotation]] = []
|
|
319
|
+
for current_batch in chunker_sequence(items, self.CHUNK_SIZE):
|
|
320
|
+
resources = self.client.annotations.retrieve_multiple(current_batch.get_ids())
|
|
321
|
+
resources_by_id = {resource.id: resource for resource in resources}
|
|
322
|
+
not_found = 0
|
|
323
|
+
incorrect_type_count = 0
|
|
324
|
+
for mapping in current_batch:
|
|
325
|
+
resource = resources_by_id.get(mapping.id)
|
|
326
|
+
if resource is None:
|
|
327
|
+
not_found += 1
|
|
328
|
+
continue
|
|
329
|
+
if resource.annotation_type not in self.SUPPORTED_ANNOTATION_TYPES:
|
|
330
|
+
incorrect_type_count += 1
|
|
331
|
+
continue
|
|
332
|
+
mapping.ingestion_view = self._get_mapping(mapping.ingestion_view, resource)
|
|
333
|
+
chunk.append(AssetCentricMapping(mapping=mapping, resource=resource))
|
|
334
|
+
if chunk:
|
|
335
|
+
yield chunk
|
|
336
|
+
chunk = []
|
|
337
|
+
if not_found:
|
|
338
|
+
MediumSeverityWarning(
|
|
339
|
+
f"Could not find {not_found} annotations referenced in the CSV file. They will be skipped during migration."
|
|
340
|
+
).print_warning(include_timestamp=True, console=self.client.console)
|
|
341
|
+
if incorrect_type_count:
|
|
342
|
+
MediumSeverityWarning(
|
|
343
|
+
f"Found {incorrect_type_count} annotations with unsupported types. Only 'diagrams.AssetLink' and "
|
|
344
|
+
"'diagrams.FileLink' are supported. These annotations will be skipped during migration."
|
|
345
|
+
).print_warning(include_timestamp=True, console=self.client.console)
|
|
346
|
+
|
|
347
|
+
def _get_mapping(self, current_mapping: str | None, resource: Annotation) -> str:
|
|
348
|
+
try:
|
|
349
|
+
return (
|
|
350
|
+
current_mapping
|
|
351
|
+
or {
|
|
352
|
+
"diagrams.AssetLink": self.default_asset_annotation_mapping,
|
|
353
|
+
"diagrams.FileLink": self.default_file_annotation_mapping,
|
|
354
|
+
}[resource.annotation_type]
|
|
355
|
+
)
|
|
356
|
+
except KeyError as e:
|
|
357
|
+
raise ToolkitValueError(
|
|
358
|
+
f"Could not determine default ingestion view for annotation type '{resource.annotation_type}'. "
|
|
359
|
+
"Please specify the ingestion view explicitly in the CSV file."
|
|
360
|
+
) from e
|
|
361
|
+
|
|
362
|
+
def json_to_resource(self, item_json: dict[str, JsonVal]) -> InstanceApply:
|
|
363
|
+
raise NotImplementedError("Deserializing Annotation Migrations from JSON is not supported.")
|
|
364
|
+
|
|
365
|
+
def data_to_json_chunk(
|
|
366
|
+
self,
|
|
367
|
+
data_chunk: Sequence[AssetCentricMapping[Annotation]],
|
|
368
|
+
selector: AssetCentricMigrationSelector | None = None,
|
|
369
|
+
) -> list[dict[str, JsonVal]]:
|
|
370
|
+
raise NotImplementedError("Serializing Annotation Migrations to JSON is not supported.")
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
class ThreeDMigrationIO(UploadableStorageIO[ThreeDSelector, ThreeDModelResponse, ThreeDMigrationRequest]):
|
|
374
|
+
"""IO class for downloading and migrating 3D models.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
client: The ToolkitClient to use for CDF interactions.
|
|
378
|
+
data_model_type: The type of 3D data model to download. Either "classic" or "DM".
|
|
379
|
+
|
|
380
|
+
"""
|
|
381
|
+
|
|
382
|
+
KIND = "3DMigration"
|
|
383
|
+
SUPPORTED_DOWNLOAD_FORMATS = frozenset({".ndjson"})
|
|
384
|
+
SUPPORTED_COMPRESSIONS = frozenset({".gz"})
|
|
385
|
+
SUPPORTED_READ_FORMATS = frozenset({".ndjson"})
|
|
386
|
+
DOWNLOAD_LIMIT = 1000
|
|
387
|
+
CHUNK_SIZE = 1
|
|
388
|
+
UPLOAD_ENDPOINT = "/3d/migrate/models"
|
|
389
|
+
REVISION_ENDPOINT = "/3d/migrate/revisions"
|
|
390
|
+
|
|
391
|
+
def __init__(self, client: ToolkitClient, data_model_type: Literal["classic", "data modeling"] = "classic") -> None:
|
|
392
|
+
super().__init__(client)
|
|
393
|
+
self.data_model_type = data_model_type
|
|
394
|
+
|
|
395
|
+
def as_id(self, item: ThreeDModelResponse) -> str:
|
|
396
|
+
return f"{item.name}_{item.id!s}"
|
|
397
|
+
|
|
398
|
+
def _is_selected(self, item: ThreeDModelResponse, included_models: set[int] | None) -> bool:
|
|
399
|
+
return self._is_correct_type(item) and (included_models is None or item.id in included_models)
|
|
400
|
+
|
|
401
|
+
def _is_correct_type(self, item: ThreeDModelResponse) -> bool:
|
|
402
|
+
if self.data_model_type == "classic":
|
|
403
|
+
return item.space is None
|
|
404
|
+
else:
|
|
405
|
+
return item.space is not None
|
|
406
|
+
|
|
407
|
+
def stream_data(self, selector: ThreeDSelector, limit: int | None = None) -> Iterable[Page[ThreeDModelResponse]]:
|
|
408
|
+
published: bool | None = None
|
|
409
|
+
if isinstance(selector, ThreeDModelFilteredSelector):
|
|
410
|
+
published = selector.published
|
|
411
|
+
included_models: set[int] | None = None
|
|
412
|
+
if isinstance(selector, ThreeDModelIdSelector):
|
|
413
|
+
included_models = set(selector.ids)
|
|
414
|
+
cursor: str | None = None
|
|
415
|
+
total = 0
|
|
416
|
+
while True:
|
|
417
|
+
request_limit = min(self.DOWNLOAD_LIMIT, limit - total) if limit is not None else self.DOWNLOAD_LIMIT
|
|
418
|
+
response = self.client.tool.three_d.models.iterate(
|
|
419
|
+
published=published, include_revision_info=True, limit=request_limit, cursor=cursor
|
|
420
|
+
)
|
|
421
|
+
items = [item for item in response.items if self._is_selected(item, included_models)]
|
|
422
|
+
total += len(items)
|
|
423
|
+
if items:
|
|
424
|
+
yield Page(worker_id="main", items=items, next_cursor=response.next_cursor)
|
|
425
|
+
if response.next_cursor is None:
|
|
426
|
+
break
|
|
427
|
+
cursor = response.next_cursor
|
|
428
|
+
|
|
429
|
+
def count(self, selector: ThreeDSelector) -> int | None:
|
|
430
|
+
# There is no efficient way to count 3D models in CDF.
|
|
431
|
+
return None
|
|
432
|
+
|
|
433
|
+
def data_to_json_chunk(
|
|
434
|
+
self, data_chunk: Sequence[ThreeDModelResponse], selector: ThreeDSelector | None = None
|
|
435
|
+
) -> list[dict[str, JsonVal]]:
|
|
436
|
+
raise NotImplementedError("Deserializing Annotation Migrations from JSON is not supported.")
|
|
437
|
+
|
|
438
|
+
def json_to_resource(self, item_json: dict[str, JsonVal]) -> ThreeDMigrationRequest:
|
|
439
|
+
raise NotImplementedError("Deserializing ThreeD Migrations from JSON is not supported.")
|
|
440
|
+
|
|
441
|
+
def upload_items(
|
|
442
|
+
self,
|
|
443
|
+
data_chunk: Sequence[UploadItem[ThreeDMigrationRequest]],
|
|
444
|
+
http_client: HTTPClient,
|
|
445
|
+
selector: ThreeDSelector | None = None,
|
|
446
|
+
) -> Sequence[HTTPMessage]:
|
|
447
|
+
"""Migrate 3D models by uploading them to the migrate/models endpoint."""
|
|
448
|
+
if len(data_chunk) > self.CHUNK_SIZE:
|
|
449
|
+
raise RuntimeError(f"Uploading more than {self.CHUNK_SIZE} 3D models at a time is not supported.")
|
|
450
|
+
|
|
451
|
+
results: list[HTTPMessage] = []
|
|
452
|
+
responses = http_client.request_with_retries(
|
|
453
|
+
message=ItemsRequest(
|
|
454
|
+
endpoint_url=self.client.config.create_api_url(self.UPLOAD_ENDPOINT),
|
|
455
|
+
method="POST",
|
|
456
|
+
items=list(data_chunk),
|
|
457
|
+
)
|
|
458
|
+
)
|
|
459
|
+
if (
|
|
460
|
+
failed_response := next((res for res in responses if isinstance(res, FailedResponse)), None)
|
|
461
|
+
) and failed_response.status_code == 400:
|
|
462
|
+
raise ToolkitAPIError("3D model migration failed. You need to enable the 3D migration alpha feature flag.")
|
|
463
|
+
|
|
464
|
+
results.extend(responses)
|
|
465
|
+
success_ids = {id for res in responses if isinstance(res, SuccessResponseItems) for id in res.ids}
|
|
466
|
+
for data in data_chunk:
|
|
467
|
+
if data.source_id not in success_ids:
|
|
468
|
+
continue
|
|
469
|
+
revision = http_client.request_with_retries(
|
|
470
|
+
message=SimpleBodyRequest(
|
|
471
|
+
endpoint_url=self.client.config.create_api_url(self.REVISION_ENDPOINT),
|
|
472
|
+
method="POST",
|
|
473
|
+
body_content={"items": [data.item.revision.dump(camel_case=True)]},
|
|
474
|
+
)
|
|
475
|
+
)
|
|
476
|
+
results.extend(revision.as_item_responses(data.source_id))
|
|
477
|
+
return results
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
class ThreeDAssetMappingMigrationIO(UploadableStorageIO[ThreeDSelector, AssetMappingResponse, AssetMappingDMRequest]):
|
|
481
|
+
KIND = "3DMigrationAssetMapping"
|
|
482
|
+
SUPPORTED_DOWNLOAD_FORMATS = frozenset({".ndjson"})
|
|
483
|
+
SUPPORTED_COMPRESSIONS = frozenset({".gz"})
|
|
484
|
+
SUPPORTED_READ_FORMATS = frozenset({".ndjson"})
|
|
485
|
+
DOWNLOAD_LIMIT = 1000
|
|
486
|
+
CHUNK_SIZE = 100
|
|
487
|
+
UPLOAD_ENDPOINT = "/3d/models/{modelId}/revisions/{revisionId}/mappings"
|
|
488
|
+
|
|
489
|
+
def __init__(self, client: ToolkitClient, object_3D_space: str, cad_node_space: str) -> None:
|
|
490
|
+
super().__init__(client)
|
|
491
|
+
self.object_3D_space = object_3D_space
|
|
492
|
+
self.cad_node_space = cad_node_space
|
|
493
|
+
# We can only migrate asset mappings for 3D models that are already migrated to data modeling.
|
|
494
|
+
self._3D_io = ThreeDMigrationIO(client, data_model_type="data modeling")
|
|
495
|
+
|
|
496
|
+
def as_id(self, item: AssetMappingResponse) -> str:
|
|
497
|
+
return f"AssetMapping_{item.model_id!s}_{item.revision_id!s}_{item.asset_id!s}"
|
|
498
|
+
|
|
499
|
+
def stream_data(self, selector: ThreeDSelector, limit: int | None = None) -> Iterable[Page[AssetMappingResponse]]:
|
|
500
|
+
total = 0
|
|
501
|
+
for three_d_page in self._3D_io.stream_data(selector, None):
|
|
502
|
+
for model in three_d_page.items:
|
|
503
|
+
if model.last_revision_info is None or model.last_revision_info.revision_id is None:
|
|
504
|
+
# No revisions, so no asset mappings to
|
|
505
|
+
continue
|
|
506
|
+
cursor: str | None = None
|
|
507
|
+
while True:
|
|
508
|
+
request_limit = (
|
|
509
|
+
min(self.DOWNLOAD_LIMIT, limit - total) if limit is not None else self.DOWNLOAD_LIMIT
|
|
510
|
+
)
|
|
511
|
+
if limit is not None and total >= limit:
|
|
512
|
+
return
|
|
513
|
+
response = self.client.tool.three_d.asset_mappings.iterate(
|
|
514
|
+
model_id=model.id,
|
|
515
|
+
revision_id=model.last_revision_info.revision_id,
|
|
516
|
+
cursor=cursor,
|
|
517
|
+
limit=request_limit,
|
|
518
|
+
)
|
|
519
|
+
items = response.items
|
|
520
|
+
total += len(items)
|
|
521
|
+
if items:
|
|
522
|
+
yield Page(worker_id="main", items=items, next_cursor=response.next_cursor)
|
|
523
|
+
if response.next_cursor is None:
|
|
524
|
+
break
|
|
525
|
+
cursor = response.next_cursor
|
|
526
|
+
|
|
527
|
+
def count(self, selector: ThreeDSelector) -> int | None:
|
|
528
|
+
# There is no efficient way to count 3D asset mappings in CDF.
|
|
529
|
+
return None
|
|
530
|
+
|
|
531
|
+
def upload_items(
|
|
532
|
+
self,
|
|
533
|
+
data_chunk: Sequence[UploadItem[AssetMappingDMRequest]],
|
|
534
|
+
http_client: HTTPClient,
|
|
535
|
+
selector: T_Selector | None = None,
|
|
536
|
+
) -> Sequence[HTTPMessage]:
|
|
537
|
+
"""Migrate 3D asset mappings by uploading them to the migrate/asset-mappings endpoint."""
|
|
538
|
+
if not data_chunk:
|
|
539
|
+
return []
|
|
540
|
+
# Assume all items in the chunk belong to the same model and revision, they should
|
|
541
|
+
# if the .stream_data method is used for downloading.
|
|
542
|
+
first = data_chunk[0]
|
|
543
|
+
model_id = first.item.model_id
|
|
544
|
+
revision_id = first.item.revision_id
|
|
545
|
+
endpoint = self.UPLOAD_ENDPOINT.format(modelId=model_id, revisionId=revision_id)
|
|
546
|
+
responses = http_client.request_with_retries(
|
|
547
|
+
ItemsRequest(
|
|
548
|
+
endpoint_url=self.client.config.create_api_url(endpoint),
|
|
549
|
+
method="POST",
|
|
550
|
+
items=list(data_chunk),
|
|
551
|
+
extra_body_fields={
|
|
552
|
+
"dmsContextualizationConfig": {
|
|
553
|
+
"object3DSpace": self.object_3D_space,
|
|
554
|
+
"cadNodeSpace": self.cad_node_space,
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
)
|
|
558
|
+
)
|
|
559
|
+
return responses
|
|
560
|
+
|
|
561
|
+
def json_to_resource(self, item_json: dict[str, JsonVal]) -> AssetMappingDMRequest:
|
|
562
|
+
raise NotImplementedError("Deserializing 3D Asset Mappings from JSON is not supported.")
|
|
563
|
+
|
|
564
|
+
def data_to_json_chunk(
|
|
565
|
+
self, data_chunk: Sequence[AssetMappingResponse], selector: ThreeDSelector | None = None
|
|
566
|
+
) -> list[dict[str, JsonVal]]:
|
|
567
|
+
raise NotImplementedError("Serializing 3D Asset Mappings to JSON is not supported.")
|
|
@@ -8,11 +8,11 @@ from cognite.client.data_classes.data_modeling import ViewId
|
|
|
8
8
|
from cognite_toolkit._cdf_tk.commands._migrate.data_classes import MigrationMappingList
|
|
9
9
|
from cognite_toolkit._cdf_tk.storageio import DataSelector
|
|
10
10
|
from cognite_toolkit._cdf_tk.storageio.selectors import DataSetSelector
|
|
11
|
-
from cognite_toolkit._cdf_tk.utils.useful_types import
|
|
11
|
+
from cognite_toolkit._cdf_tk.utils.useful_types import AssetCentricKindExtended
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class AssetCentricMigrationSelector(DataSelector, ABC):
|
|
15
|
-
kind:
|
|
15
|
+
kind: AssetCentricKindExtended
|
|
16
16
|
|
|
17
17
|
@abstractmethod
|
|
18
18
|
def get_ingestion_mappings(self) -> list[str]:
|
|
@@ -41,7 +41,7 @@ class MigrationCSVFileSelector(AssetCentricMigrationSelector):
|
|
|
41
41
|
|
|
42
42
|
class MigrateDataSetSelector(AssetCentricMigrationSelector):
|
|
43
43
|
type: Literal["migrateDataSet"] = "migrateDataSet"
|
|
44
|
-
kind:
|
|
44
|
+
kind: AssetCentricKindExtended
|
|
45
45
|
data_set_external_id: str
|
|
46
46
|
ingestion_mapping: str | None = None
|
|
47
47
|
preferred_consumer_view: ViewId | None = None
|
|
@@ -63,4 +63,9 @@ class MigrateDataSetSelector(AssetCentricMigrationSelector):
|
|
|
63
63
|
return [self.ingestion_mapping] if self.ingestion_mapping else []
|
|
64
64
|
|
|
65
65
|
def as_asset_centric_selector(self) -> DataSetSelector:
|
|
66
|
-
|
|
66
|
+
if self.kind == "Annotations":
|
|
67
|
+
# Annotations are connected to file metadata, so we need to download the file metadata
|
|
68
|
+
# and look up the annotations connected to each file metadata.
|
|
69
|
+
return DataSetSelector(data_set_external_id=self.data_set_external_id, kind="FileMetadata")
|
|
70
|
+
else:
|
|
71
|
+
return DataSetSelector(data_set_external_id=self.data_set_external_id, kind=self.kind)
|
|
@@ -21,7 +21,7 @@ from rich.spinner import Spinner
|
|
|
21
21
|
from rich.table import Table
|
|
22
22
|
|
|
23
23
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
24
|
-
from cognite_toolkit._cdf_tk.client.data_classes.raw import RawProfileResults, RawTable
|
|
24
|
+
from cognite_toolkit._cdf_tk.client.data_classes.legacy.raw import RawProfileResults, RawTable
|
|
25
25
|
from cognite_toolkit._cdf_tk.constants import MAX_ROW_ITERATION_RUN_QUERY
|
|
26
26
|
from cognite_toolkit._cdf_tk.exceptions import ToolkitMissingDependencyError, ToolkitThrottledError, ToolkitValueError
|
|
27
27
|
from cognite_toolkit._cdf_tk.utils.aggregators import (
|
|
@@ -7,12 +7,7 @@ from typing import Literal, cast
|
|
|
7
7
|
|
|
8
8
|
import questionary
|
|
9
9
|
from cognite.client.data_classes import DataSetUpdate
|
|
10
|
-
from cognite.client.data_classes.
|
|
11
|
-
from cognite.client.data_classes.data_modeling import (
|
|
12
|
-
EdgeList,
|
|
13
|
-
NodeId,
|
|
14
|
-
NodeList,
|
|
15
|
-
)
|
|
10
|
+
from cognite.client.data_classes.data_modeling import Edge, NodeId
|
|
16
11
|
from cognite.client.data_classes.data_modeling.statistics import SpaceStatistics
|
|
17
12
|
from cognite.client.exceptions import CogniteAPIError
|
|
18
13
|
from cognite.client.utils._identifier import InstanceId
|
|
@@ -21,6 +16,7 @@ from rich.console import Console
|
|
|
21
16
|
from rich.panel import Panel
|
|
22
17
|
|
|
23
18
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
19
|
+
from cognite_toolkit._cdf_tk.client.data_classes.instance_api import TypedInstanceIdentifier
|
|
24
20
|
from cognite_toolkit._cdf_tk.cruds import (
|
|
25
21
|
AssetCRUD,
|
|
26
22
|
ContainerCRUD,
|
|
@@ -46,6 +42,7 @@ from cognite_toolkit._cdf_tk.exceptions import (
|
|
|
46
42
|
AuthorizationError,
|
|
47
43
|
ToolkitMissingResourceError,
|
|
48
44
|
)
|
|
45
|
+
from cognite_toolkit._cdf_tk.protocols import ResourceResponseProtocol
|
|
49
46
|
from cognite_toolkit._cdf_tk.storageio import InstanceIO
|
|
50
47
|
from cognite_toolkit._cdf_tk.storageio.selectors import InstanceSelector
|
|
51
48
|
from cognite_toolkit._cdf_tk.tk_warnings import (
|
|
@@ -63,10 +60,10 @@ from cognite_toolkit._cdf_tk.utils.aggregators import (
|
|
|
63
60
|
TimeSeriesAggregator,
|
|
64
61
|
)
|
|
65
62
|
from cognite_toolkit._cdf_tk.utils.http_client import (
|
|
66
|
-
FailedRequestItems,
|
|
67
|
-
FailedResponseItems,
|
|
68
63
|
HTTPClient,
|
|
69
64
|
ItemsRequest,
|
|
65
|
+
ItemsRequest2,
|
|
66
|
+
ItemsSuccessResponse2,
|
|
70
67
|
SuccessResponseItems,
|
|
71
68
|
)
|
|
72
69
|
from cognite_toolkit._cdf_tk.utils.producer_worker import ProducerWorkerExecutor
|
|
@@ -107,7 +104,7 @@ class ToDelete(ABC):
|
|
|
107
104
|
@abstractmethod
|
|
108
105
|
def get_process_function(
|
|
109
106
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
110
|
-
) -> Callable[[
|
|
107
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
111
108
|
raise NotImplementedError()
|
|
112
109
|
|
|
113
110
|
def get_extra_fields(self) -> dict[str, JsonVal]:
|
|
@@ -118,9 +115,10 @@ class ToDelete(ABC):
|
|
|
118
115
|
class DataModelingToDelete(ToDelete):
|
|
119
116
|
def get_process_function(
|
|
120
117
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
121
|
-
) -> Callable[[
|
|
122
|
-
def as_id(chunk:
|
|
123
|
-
|
|
118
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
119
|
+
def as_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
120
|
+
# We know that all data modeling resources implement as_id
|
|
121
|
+
return [item.as_id().dump(include_type=False) for item in chunk] # type: ignore[attr-defined]
|
|
124
122
|
|
|
125
123
|
return as_id
|
|
126
124
|
|
|
@@ -129,11 +127,11 @@ class DataModelingToDelete(ToDelete):
|
|
|
129
127
|
class EdgeToDelete(ToDelete):
|
|
130
128
|
def get_process_function(
|
|
131
129
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
132
|
-
) -> Callable[[
|
|
133
|
-
def as_id(chunk:
|
|
130
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
131
|
+
def as_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
134
132
|
return [
|
|
135
133
|
{"space": item.space, "externalId": item.external_id, "instanceType": "edge"}
|
|
136
|
-
for item in cast(
|
|
134
|
+
for item in cast(list[Edge], chunk)
|
|
137
135
|
]
|
|
138
136
|
|
|
139
137
|
return as_id
|
|
@@ -146,9 +144,10 @@ class NodesToDelete(ToDelete):
|
|
|
146
144
|
|
|
147
145
|
def get_process_function(
|
|
148
146
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
149
|
-
) -> Callable[[
|
|
150
|
-
def check_for_data(chunk:
|
|
151
|
-
|
|
147
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
148
|
+
def check_for_data(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
149
|
+
# We know that all node resources implement as_id
|
|
150
|
+
node_ids = [item.as_id() for item in chunk] # type: ignore[attr-defined]
|
|
152
151
|
found_ids: set[InstanceId] = set()
|
|
153
152
|
if not self.delete_datapoints:
|
|
154
153
|
timeseries = client.time_series.retrieve_multiple(instance_ids=node_ids, ignore_unknown_ids=True)
|
|
@@ -164,8 +163,7 @@ class NodesToDelete(ToDelete):
|
|
|
164
163
|
dumped = node_id.dump(include_instance_type=True)
|
|
165
164
|
# The delete endpoint expects "instanceType" instead of "type"
|
|
166
165
|
dumped["instanceType"] = dumped.pop("type")
|
|
167
|
-
|
|
168
|
-
result.append(dumped) # type: ignore[arg-type]
|
|
166
|
+
result.append(dumped)
|
|
169
167
|
return result
|
|
170
168
|
|
|
171
169
|
return check_for_data
|
|
@@ -175,9 +173,10 @@ class NodesToDelete(ToDelete):
|
|
|
175
173
|
class IdResourceToDelete(ToDelete):
|
|
176
174
|
def get_process_function(
|
|
177
175
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
178
|
-
) -> Callable[[
|
|
179
|
-
def as_id(chunk:
|
|
180
|
-
|
|
176
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
177
|
+
def as_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
178
|
+
# We know that all id resources have an id attribute
|
|
179
|
+
return [{"id": item.id} for item in chunk] # type: ignore[attr-defined]
|
|
181
180
|
|
|
182
181
|
return as_id
|
|
183
182
|
|
|
@@ -186,9 +185,10 @@ class IdResourceToDelete(ToDelete):
|
|
|
186
185
|
class ExternalIdToDelete(ToDelete):
|
|
187
186
|
def get_process_function(
|
|
188
187
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
189
|
-
) -> Callable[[
|
|
190
|
-
def as_external_id(chunk:
|
|
191
|
-
|
|
188
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
189
|
+
def as_external_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
190
|
+
# We know that all external id resources have an external_id attribute
|
|
191
|
+
return [{"externalId": item.external_id} for item in chunk] # type: ignore[attr-defined]
|
|
192
192
|
|
|
193
193
|
return as_external_id
|
|
194
194
|
|
|
@@ -321,7 +321,7 @@ class PurgeCommand(ToolkitCommand):
|
|
|
321
321
|
iteration_count = item.total // self.BATCH_SIZE_DM + (
|
|
322
322
|
1 if item.total % self.BATCH_SIZE_DM > 0 else 0
|
|
323
323
|
)
|
|
324
|
-
executor = ProducerWorkerExecutor[
|
|
324
|
+
executor = ProducerWorkerExecutor[list[ResourceResponseProtocol], list[JsonVal]](
|
|
325
325
|
download_iterable=self._iterate_batch(
|
|
326
326
|
item.crud, space, data_set_external_id, batch_size=self.BATCH_SIZE_DM
|
|
327
327
|
),
|
|
@@ -348,13 +348,13 @@ class PurgeCommand(ToolkitCommand):
|
|
|
348
348
|
@staticmethod
|
|
349
349
|
def _iterate_batch(
|
|
350
350
|
crud: ResourceCRUD, selected_space: str | None, data_set_external_id: str | None, batch_size: int
|
|
351
|
-
) -> Iterable[
|
|
352
|
-
batch =
|
|
351
|
+
) -> Iterable[list[ResourceResponseProtocol]]:
|
|
352
|
+
batch: list[ResourceResponseProtocol] = []
|
|
353
353
|
for resource in crud.iterate(space=selected_space, data_set_external_id=data_set_external_id):
|
|
354
354
|
batch.append(resource)
|
|
355
355
|
if len(batch) >= batch_size:
|
|
356
356
|
yield batch
|
|
357
|
-
batch =
|
|
357
|
+
batch = []
|
|
358
358
|
if batch:
|
|
359
359
|
yield batch
|
|
360
360
|
|
|
@@ -715,21 +715,18 @@ class PurgeCommand(ToolkitCommand):
|
|
|
715
715
|
results.deleted += len(items)
|
|
716
716
|
return
|
|
717
717
|
|
|
718
|
-
responses = delete_client.
|
|
719
|
-
|
|
720
|
-
delete_client.config.create_api_url("/models/instances/delete"),
|
|
718
|
+
responses = delete_client.request_items_retries(
|
|
719
|
+
ItemsRequest2(
|
|
720
|
+
endpoint_url=delete_client.config.create_api_url("/models/instances/delete"),
|
|
721
721
|
method="POST",
|
|
722
|
-
|
|
723
|
-
items=[DeleteItem(item=item, as_id_fun=InstanceId.load) for item in items], # type: ignore[arg-type]
|
|
722
|
+
items=[TypedInstanceIdentifier._load(item) for item in items],
|
|
724
723
|
)
|
|
725
724
|
)
|
|
726
725
|
for response in responses:
|
|
727
|
-
if isinstance(response,
|
|
726
|
+
if isinstance(response, ItemsSuccessResponse2):
|
|
728
727
|
results.deleted += len(response.ids)
|
|
729
|
-
elif isinstance(response, FailedResponseItems | FailedRequestItems):
|
|
730
|
-
results.failed += len(response.ids)
|
|
731
728
|
else:
|
|
732
|
-
results.failed += len(
|
|
729
|
+
results.failed += len(response.ids)
|
|
733
730
|
|
|
734
731
|
@staticmethod
|
|
735
732
|
def _unlink_timeseries(
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import questionary
|
|
2
|
+
|
|
3
|
+
custom_style_fancy = questionary.Style(
|
|
4
|
+
[
|
|
5
|
+
("qmark", "fg:#673ab7"), # token in front of the question
|
|
6
|
+
("question", "bold"), # question text
|
|
7
|
+
("answer", "fg:#f44336 bold"), # submitted answer text behind the question
|
|
8
|
+
("pointer", "fg:#673ab7 bold"), # pointer used in select and checkbox prompts
|
|
9
|
+
("highlighted", "fg:#673ab7 bold"), # pointed-at choice in select and checkbox prompts
|
|
10
|
+
("selected", "fg:#673ab7"), # style for a selected item of a checkbox
|
|
11
|
+
("separator", "fg:#cc5454"), # separator in lists
|
|
12
|
+
("instruction", ""), # user instructions for select, rawselect, checkbox
|
|
13
|
+
("text", ""), # plain text
|
|
14
|
+
("disabled", "fg:#858585 italic"), # disabled choices for select and checkbox prompts
|
|
15
|
+
]
|
|
16
|
+
)
|