cognite-toolkit 0.7.35__py3-none-any.whl → 0.7.37__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.
Files changed (23) hide show
  1. cognite_toolkit/_cdf_tk/apps/_migrate_app.py +101 -0
  2. cognite_toolkit/_cdf_tk/client/api/infield.py +16 -17
  3. cognite_toolkit/_cdf_tk/client/api/streams.py +3 -4
  4. cognite_toolkit/_cdf_tk/client/api/three_d.py +266 -13
  5. cognite_toolkit/_cdf_tk/client/data_classes/api_classes.py +13 -0
  6. cognite_toolkit/_cdf_tk/client/data_classes/base.py +6 -10
  7. cognite_toolkit/_cdf_tk/client/data_classes/instance_api.py +7 -7
  8. cognite_toolkit/_cdf_tk/client/data_classes/three_d.py +59 -0
  9. cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +7 -1
  10. cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +50 -1
  11. cognite_toolkit/_cdf_tk/commands/_migrate/data_model.py +1 -0
  12. cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +119 -8
  13. cognite_toolkit/_cdf_tk/commands/_purge.py +9 -11
  14. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +17 -15
  15. cognite_toolkit/_cdf_tk/utils/http_client/_data_classes2.py +1 -3
  16. cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
  17. cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
  18. cognite_toolkit/_resources/cdf.toml +1 -1
  19. cognite_toolkit/_version.py +1 -1
  20. {cognite_toolkit-0.7.35.dist-info → cognite_toolkit-0.7.37.dist-info}/METADATA +1 -1
  21. {cognite_toolkit-0.7.35.dist-info → cognite_toolkit-0.7.37.dist-info}/RECORD +23 -23
  22. {cognite_toolkit-0.7.35.dist-info → cognite_toolkit-0.7.37.dist-info}/WHEEL +1 -1
  23. {cognite_toolkit-0.7.35.dist-info → cognite_toolkit-0.7.37.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,8 @@
1
+ from collections.abc import Hashable
1
2
  from typing import Literal
2
3
 
4
+ from pydantic import Field
5
+
3
6
  from .base import BaseModelObject, RequestResource, ResponseResource
4
7
 
5
8
 
@@ -51,3 +54,59 @@ class ThreeDModelResponse(ResponseResource[ThreeDModelRequest]):
51
54
  return ThreeDModelClassicRequest._load(self.dump())
52
55
  else:
53
56
  return ThreeDModelDMSRequest._load(self.dump())
57
+
58
+
59
+ class AssetMappingDMRequest(RequestResource):
60
+ node_id: int
61
+ asset_instance_id: NodeReference
62
+ # These fields are part of the path request and not the body schema.
63
+ model_id: int = Field(exclude=True)
64
+ revision_id: int = Field(exclude=True)
65
+
66
+ def as_id(self) -> Hashable:
67
+ return (
68
+ self.model_id,
69
+ self.revision_id,
70
+ self.node_id,
71
+ self.asset_instance_id.space,
72
+ self.asset_instance_id.external_id,
73
+ )
74
+
75
+
76
+ class AssetMappingClassicRequest(RequestResource):
77
+ node_id: int
78
+ asset_id: int | None = None
79
+ asset_instance_id: NodeReference | None = None
80
+ # These fields are part of the path request and not the body schema.
81
+ model_id: int = Field(exclude=True)
82
+ revision_id: int = Field(exclude=True)
83
+
84
+ def as_id(self) -> Hashable:
85
+ if self.asset_id:
86
+ return self.model_id, self.revision_id, self.node_id, self.asset_id
87
+ elif self.asset_instance_id:
88
+ return (
89
+ self.model_id,
90
+ self.revision_id,
91
+ self.node_id,
92
+ self.asset_instance_id.space,
93
+ self.asset_instance_id.external_id,
94
+ )
95
+ else:
96
+ raise AttributeError("asset_id or asset_instance_id is required")
97
+
98
+
99
+ class AssetMappingResponse(ResponseResource[AssetMappingClassicRequest]):
100
+ node_id: int
101
+ asset_id: int | None = None
102
+ asset_instance_id: NodeReference | None = None
103
+ tree_index: int | None = None
104
+ subtree_size: int | None = None
105
+ # These fields are part of the path request and response, but they are included here for convenience.
106
+ model_id: int = Field(exclude=True)
107
+ revision_id: int = Field(exclude=True)
108
+
109
+ def as_request_resource(self) -> AssetMappingClassicRequest:
110
+ return AssetMappingClassicRequest.model_validate(
111
+ {**self.dump(), "modelId": self.model_id, "revisionId": self.revision_id}
112
+ )
@@ -9,6 +9,7 @@ from cognite.client.data_classes.data_modeling import (
9
9
  MappedProperty,
10
10
  NodeApply,
11
11
  NodeId,
12
+ ViewId,
12
13
  )
13
14
  from cognite.client.data_classes.data_modeling.instances import EdgeApply, NodeOrEdgeData, PropertyValueWrite
14
15
  from cognite.client.data_classes.data_modeling.views import ViewProperty
@@ -29,7 +30,7 @@ from cognite_toolkit._cdf_tk.utils.useful_types import (
29
30
  AssetCentricTypeExtended,
30
31
  )
31
32
 
32
- from .data_model import INSTANCE_SOURCE_VIEW_ID
33
+ from .data_model import COGNITE_MIGRATION_SPACE_ID, INSTANCE_SOURCE_VIEW_ID
33
34
  from .issues import ConversionIssue, FailedConversion, InvalidPropertyDataType
34
35
 
35
36
 
@@ -169,6 +170,7 @@ def asset_centric_to_dm(
169
170
  view_source: ResourceViewMappingApply,
170
171
  view_properties: dict[str, ViewProperty],
171
172
  direct_relation_cache: DirectRelationCache,
173
+ preferred_consumer_view: ViewId | None = None,
172
174
  ) -> tuple[NodeApply | EdgeApply | None, ConversionIssue]:
173
175
  """Convert an asset-centric resource to a data model instance.
174
176
 
@@ -178,6 +180,7 @@ def asset_centric_to_dm(
178
180
  view_source (ResourceViewMappingApply): The view source defining how to map the resource to the data model.
179
181
  view_properties (dict[str, ViewProperty]): The defined properties referenced in the view source mapping.
180
182
  direct_relation_cache (DirectRelationCache): Cache for direct relation references.
183
+ preferred_consumer_view (ViewId | None): The preferred consumer view for the instance.
181
184
 
182
185
  Returns:
183
186
  tuple[NodeApply | EdgeApply, ConversionIssue]: A tuple containing the converted NodeApply and any ConversionIssue encountered.
@@ -213,7 +216,10 @@ def asset_centric_to_dm(
213
216
  "id": id_,
214
217
  "dataSetId": data_set_id,
215
218
  "classicExternalId": external_id,
219
+ "resourceViewMapping": {"space": COGNITE_MIGRATION_SPACE_ID, "externalId": view_source.external_id},
216
220
  }
221
+ if preferred_consumer_view:
222
+ instance_source_properties["preferredConsumerViewId"] = preferred_consumer_view.dump()
217
223
  sources.append(NodeOrEdgeData(source=INSTANCE_SOURCE_VIEW_ID, properties=instance_source_properties))
218
224
 
219
225
  instance: NodeApply | EdgeApply
@@ -29,7 +29,13 @@ from cognite_toolkit._cdf_tk.client.data_classes.legacy.canvas import (
29
29
  )
30
30
  from cognite_toolkit._cdf_tk.client.data_classes.legacy.charts import Chart, ChartWrite
31
31
  from cognite_toolkit._cdf_tk.client.data_classes.legacy.migration import ResourceViewMappingApply
32
- from cognite_toolkit._cdf_tk.client.data_classes.three_d import RevisionStatus, ThreeDModelResponse
32
+ from cognite_toolkit._cdf_tk.client.data_classes.three_d import (
33
+ AssetMappingDMRequest,
34
+ AssetMappingResponse,
35
+ NodeReference,
36
+ RevisionStatus,
37
+ ThreeDModelResponse,
38
+ )
33
39
  from cognite_toolkit._cdf_tk.commands._migrate.conversion import DirectRelationCache, asset_centric_to_dm
34
40
  from cognite_toolkit._cdf_tk.commands._migrate.data_classes import (
35
41
  Model,
@@ -141,6 +147,7 @@ class AssetCentricMapper(
141
147
  view_source=view_source,
142
148
  view_properties=view_properties,
143
149
  direct_relation_cache=self._direct_relation_cache,
150
+ preferred_consumer_view=mapping.preferred_consumer_view,
144
151
  )
145
152
  if mapping.instance_id.space == MISSING_INSTANCE_SPACE:
146
153
  conversion_issue.missing_instance_space = f"Missing instance space for dataset ID {mapping.data_set_id!r}"
@@ -469,3 +476,45 @@ class ThreeDMapper(DataMapper[ThreeDSelector, ThreeDModelResponse, ThreeDMigrati
469
476
  return "PointCloud"
470
477
  else:
471
478
  return None
479
+
480
+
481
+ class ThreeDAssetMapper(DataMapper[ThreeDSelector, AssetMappingResponse, AssetMappingDMRequest]):
482
+ def __init__(self, client: ToolkitClient) -> None:
483
+ self.client = client
484
+
485
+ def map(
486
+ self, source: Sequence[AssetMappingResponse]
487
+ ) -> Sequence[tuple[AssetMappingDMRequest | None, MigrationIssue]]:
488
+ output: list[tuple[AssetMappingDMRequest | None, MigrationIssue]] = []
489
+ self._populate_cache(source)
490
+ for item in source:
491
+ mapped_item, issue = self._map_single_item(item)
492
+ output.append((mapped_item, issue))
493
+ return output
494
+
495
+ def _populate_cache(self, source: Sequence[AssetMappingResponse]) -> None:
496
+ asset_ids: set[int] = set()
497
+ for mapping in source:
498
+ if mapping.asset_id is not None:
499
+ asset_ids.add(mapping.asset_id)
500
+ self.client.migration.lookup.assets(list(asset_ids))
501
+
502
+ def _map_single_item(
503
+ self, item: AssetMappingResponse
504
+ ) -> tuple[AssetMappingDMRequest | None, ThreeDModelMigrationIssue]:
505
+ issue = ThreeDModelMigrationIssue(model_name=f"AssetMapping_{item.model_id}", model_id=item.model_id)
506
+ asset_instance_id = item.asset_instance_id
507
+ if item.asset_id and asset_instance_id is None:
508
+ asset_node_id = self.client.migration.lookup.assets(item.asset_id)
509
+ if asset_node_id is None:
510
+ issue.error_message.append(f"Missing asset instance for asset ID {item.asset_id!r}")
511
+ return None, issue
512
+ asset_instance_id = NodeReference(space=asset_node_id.space, externalId=asset_node_id.external_id)
513
+
514
+ if asset_instance_id is None:
515
+ issue.error_message.append("Neither assetInstanceId nor assetId provided for mapping.")
516
+ return None, issue
517
+ mapped_request = AssetMappingDMRequest(
518
+ modelId=item.model_id, revisionId=item.revision_id, nodeId=item.node_id, assetInstanceId=asset_instance_id
519
+ )
520
+ return mapped_request, issue
@@ -4,6 +4,7 @@ from cognite.client.data_classes.data_modeling.containers import BTreeIndex
4
4
  SPACE = dm.SpaceApply(
5
5
  "cognite_migration", description="Space for the asset-centric to data modeling migration", name="cdf_migration"
6
6
  )
7
+ COGNITE_MIGRATION_SPACE_ID = SPACE.space
7
8
 
8
9
  RESOURCE_VIEW_MAPPING = dm.ContainerApply(
9
10
  space=SPACE.space,
@@ -1,12 +1,16 @@
1
1
  from collections.abc import Iterable, Iterator, Mapping, Sequence
2
- from typing import ClassVar, cast
2
+ from typing import ClassVar, Literal, cast
3
3
 
4
4
  from cognite.client.data_classes import Annotation
5
5
  from cognite.client.data_classes.data_modeling import EdgeId, InstanceApply, NodeId
6
6
 
7
7
  from cognite_toolkit._cdf_tk.client import ToolkitClient
8
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 ThreeDModelResponse
9
+ from cognite_toolkit._cdf_tk.client.data_classes.three_d import (
10
+ AssetMappingDMRequest,
11
+ AssetMappingResponse,
12
+ ThreeDModelResponse,
13
+ )
10
14
  from cognite_toolkit._cdf_tk.commands._migrate.data_classes import ThreeDMigrationRequest
11
15
  from cognite_toolkit._cdf_tk.constants import MISSING_EXTERNAL_ID, MISSING_INSTANCE_SPACE
12
16
  from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError, ToolkitValueError
@@ -14,6 +18,7 @@ from cognite_toolkit._cdf_tk.storageio import (
14
18
  AnnotationIO,
15
19
  HierarchyIO,
16
20
  InstanceIO,
21
+ T_Selector,
17
22
  UploadableStorageIO,
18
23
  )
19
24
  from cognite_toolkit._cdf_tk.storageio._base import Page, UploadItem
@@ -366,6 +371,14 @@ class AnnotationMigrationIO(
366
371
 
367
372
 
368
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
+
369
382
  KIND = "3DMigration"
370
383
  SUPPORTED_DOWNLOAD_FORMATS = frozenset({".ndjson"})
371
384
  SUPPORTED_COMPRESSIONS = frozenset({".gz"})
@@ -375,9 +388,22 @@ class ThreeDMigrationIO(UploadableStorageIO[ThreeDSelector, ThreeDModelResponse,
375
388
  UPLOAD_ENDPOINT = "/3d/migrate/models"
376
389
  REVISION_ENDPOINT = "/3d/migrate/revisions"
377
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
+
378
395
  def as_id(self, item: ThreeDModelResponse) -> str:
379
396
  return f"{item.name}_{item.id!s}"
380
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
+
381
407
  def stream_data(self, selector: ThreeDSelector, limit: int | None = None) -> Iterable[Page[ThreeDModelResponse]]:
382
408
  published: bool | None = None
383
409
  if isinstance(selector, ThreeDModelFilteredSelector):
@@ -392,12 +418,7 @@ class ThreeDMigrationIO(UploadableStorageIO[ThreeDSelector, ThreeDModelResponse,
392
418
  response = self.client.tool.three_d.models.iterate(
393
419
  published=published, include_revision_info=True, limit=request_limit, cursor=cursor
394
420
  )
395
- # Only include asset-centric 3D models
396
- items = [
397
- item
398
- for item in response.items
399
- if item.space is None and (included_models is None or item.id in included_models)
400
- ]
421
+ items = [item for item in response.items if self._is_selected(item, included_models)]
401
422
  total += len(items)
402
423
  if items:
403
424
  yield Page(worker_id="main", items=items, next_cursor=response.next_cursor)
@@ -454,3 +475,93 @@ class ThreeDMigrationIO(UploadableStorageIO[ThreeDSelector, ThreeDModelResponse,
454
475
  )
455
476
  results.extend(revision.as_item_responses(data.source_id))
456
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.")
@@ -16,6 +16,7 @@ from rich.console import Console
16
16
  from rich.panel import Panel
17
17
 
18
18
  from cognite_toolkit._cdf_tk.client import ToolkitClient
19
+ from cognite_toolkit._cdf_tk.client.data_classes.instance_api import TypedInstanceIdentifier
19
20
  from cognite_toolkit._cdf_tk.cruds import (
20
21
  AssetCRUD,
21
22
  ContainerCRUD,
@@ -59,10 +60,10 @@ from cognite_toolkit._cdf_tk.utils.aggregators import (
59
60
  TimeSeriesAggregator,
60
61
  )
61
62
  from cognite_toolkit._cdf_tk.utils.http_client import (
62
- FailedRequestItems,
63
- FailedResponseItems,
64
63
  HTTPClient,
65
64
  ItemsRequest,
65
+ ItemsRequest2,
66
+ ItemsSuccessResponse2,
66
67
  SuccessResponseItems,
67
68
  )
68
69
  from cognite_toolkit._cdf_tk.utils.producer_worker import ProducerWorkerExecutor
@@ -714,21 +715,18 @@ class PurgeCommand(ToolkitCommand):
714
715
  results.deleted += len(items)
715
716
  return
716
717
 
717
- responses = delete_client.request_with_retries(
718
- ItemsRequest(
719
- 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"),
720
721
  method="POST",
721
- # MyPy does not understand that InstanceId.load handles dict[str, JsonVal]
722
- 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],
723
723
  )
724
724
  )
725
725
  for response in responses:
726
- if isinstance(response, SuccessResponseItems):
726
+ if isinstance(response, ItemsSuccessResponse2):
727
727
  results.deleted += len(response.ids)
728
- elif isinstance(response, FailedResponseItems | FailedRequestItems):
729
- results.failed += len(response.ids)
730
728
  else:
731
- results.failed += len(items)
729
+ results.failed += len(response.ids)
732
730
 
733
731
  @staticmethod
734
732
  def _unlink_timeseries(
@@ -13,7 +13,7 @@ from cognite_toolkit._cdf_tk.client.data_classes.infield import (
13
13
  InfieldLocationConfig,
14
14
  InfieldLocationConfigList,
15
15
  )
16
- from cognite_toolkit._cdf_tk.client.data_classes.instance_api import InstanceResult, NodeIdentifier
16
+ from cognite_toolkit._cdf_tk.client.data_classes.instance_api import InstanceResult, TypedNodeIdentifier
17
17
  from cognite_toolkit._cdf_tk.client.data_classes.legacy.apm_config_v1 import (
18
18
  APMConfig,
19
19
  APMConfigList,
@@ -246,7 +246,7 @@ class InfieldV1CRUD(ResourceCRUD[str, APMConfigWrite, APMConfig]):
246
246
 
247
247
 
248
248
  @final
249
- class InFieldLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InfieldLocationConfig, InfieldLocationConfig]):
249
+ class InFieldLocationConfigCRUD(ResourceCRUD[TypedNodeIdentifier, InfieldLocationConfig, InfieldLocationConfig]):
250
250
  folder_name = "cdf_applications"
251
251
  resource_cls = InfieldLocationConfig
252
252
  resource_write_cls = InfieldLocationConfig
@@ -260,13 +260,13 @@ class InFieldLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InfieldLocationConf
260
260
  return "infield location configs"
261
261
 
262
262
  @classmethod
263
- def get_id(cls, item: InfieldLocationConfig | dict) -> NodeIdentifier:
263
+ def get_id(cls, item: InfieldLocationConfig | dict) -> TypedNodeIdentifier:
264
264
  if isinstance(item, dict):
265
- return NodeIdentifier(space=item["space"], external_id=item["externalId"])
266
- return NodeIdentifier(space=item.space, external_id=item.external_id)
265
+ return TypedNodeIdentifier(space=item["space"], external_id=item["externalId"])
266
+ return TypedNodeIdentifier(space=item.space, external_id=item.external_id)
267
267
 
268
268
  @classmethod
269
- def dump_id(cls, id: NodeIdentifier) -> dict[str, Any]:
269
+ def dump_id(cls, id: TypedNodeIdentifier) -> dict[str, Any]:
270
270
  return id.dump(include_type=False)
271
271
 
272
272
  @classmethod
@@ -308,13 +308,13 @@ class InFieldLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InfieldLocationConf
308
308
  # as we only want to count the infield location configs here.
309
309
  return [res for res in created if res.as_id() in config_ids]
310
310
 
311
- def retrieve(self, ids: SequenceNotStr[NodeIdentifier]) -> InfieldLocationConfigList:
311
+ def retrieve(self, ids: SequenceNotStr[TypedNodeIdentifier]) -> InfieldLocationConfigList:
312
312
  return InfieldLocationConfigList(self.client.infield.config.retrieve(list(ids)))
313
313
 
314
314
  def update(self, items: Sequence[InfieldLocationConfig]) -> Sized:
315
315
  return self.create(items)
316
316
 
317
- def delete(self, ids: SequenceNotStr[NodeIdentifier]) -> int:
317
+ def delete(self, ids: SequenceNotStr[TypedNodeIdentifier]) -> int:
318
318
  # We must retrieve the full resource to get hte DataExplorationConfig linked resource deleted as well.
319
319
  retrieved = self.retrieve(list(ids))
320
320
  # Then, we pass the entire resource to the delete method, which will delete both the InfieldLocationConfig
@@ -345,7 +345,9 @@ class InFieldLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InfieldLocationConf
345
345
 
346
346
 
347
347
  @final
348
- class InFieldCDMLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InFieldCDMLocationConfig, InFieldCDMLocationConfig]):
348
+ class InFieldCDMLocationConfigCRUD(
349
+ ResourceCRUD[TypedNodeIdentifier, InFieldCDMLocationConfig, InFieldCDMLocationConfig]
350
+ ):
349
351
  folder_name = "cdf_applications"
350
352
  resource_cls = InFieldCDMLocationConfig
351
353
  resource_write_cls = InFieldCDMLocationConfig
@@ -359,13 +361,13 @@ class InFieldCDMLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InFieldCDMLocati
359
361
  return "infield CDM location configs"
360
362
 
361
363
  @classmethod
362
- def get_id(cls, item: InFieldCDMLocationConfig | dict) -> NodeIdentifier:
364
+ def get_id(cls, item: InFieldCDMLocationConfig | dict) -> TypedNodeIdentifier:
363
365
  if isinstance(item, dict):
364
- return NodeIdentifier(space=item["space"], external_id=item["externalId"])
365
- return NodeIdentifier(space=item.space, external_id=item.external_id)
366
+ return TypedNodeIdentifier(space=item["space"], external_id=item["externalId"])
367
+ return TypedNodeIdentifier(space=item.space, external_id=item.external_id)
366
368
 
367
369
  @classmethod
368
- def dump_id(cls, id: NodeIdentifier) -> dict[str, Any]:
370
+ def dump_id(cls, id: TypedNodeIdentifier) -> dict[str, Any]:
369
371
  return id.dump(include_type=False)
370
372
 
371
373
  @classmethod
@@ -397,13 +399,13 @@ class InFieldCDMLocationConfigCRUD(ResourceCRUD[NodeIdentifier, InFieldCDMLocati
397
399
  def create(self, items: Sequence[InFieldCDMLocationConfig]) -> list[InstanceResult]:
398
400
  return self.client.infield.cdm_config.apply(items)
399
401
 
400
- def retrieve(self, ids: SequenceNotStr[NodeIdentifier]) -> list[InFieldCDMLocationConfig]:
402
+ def retrieve(self, ids: SequenceNotStr[TypedNodeIdentifier]) -> list[InFieldCDMLocationConfig]:
401
403
  return self.client.infield.cdm_config.retrieve(list(ids))
402
404
 
403
405
  def update(self, items: Sequence[InFieldCDMLocationConfig]) -> Sized:
404
406
  return self.create(items)
405
407
 
406
- def delete(self, ids: SequenceNotStr[NodeIdentifier]) -> int:
408
+ def delete(self, ids: SequenceNotStr[TypedNodeIdentifier]) -> int:
407
409
  # We must retrieve the full resource to delete it.
408
410
  retrieved = self.retrieve(list(ids))
409
411
  _ = self.client.infield.cdm_config.delete(retrieved)
@@ -26,9 +26,7 @@ class HTTPResult2(BaseModel):
26
26
  if isinstance(self, SuccessResponse2):
27
27
  return self
28
28
  elif isinstance(self, FailedResponse2):
29
- raise ToolkitAPIError(
30
- f"Request failed with status code {self.status_code}: {self.error.code} - {self.error.message}"
31
- )
29
+ raise ToolkitAPIError(f"Request failed with status code {self.status_code}: {self.error.message}")
32
30
  elif isinstance(self, FailedRequest2):
33
31
  raise ToolkitAPIError(f"Request failed with error: {self.error}")
34
32
  else:
@@ -12,7 +12,7 @@ jobs:
12
12
  environment: dev
13
13
  name: Deploy
14
14
  container:
15
- image: cognite/toolkit:0.7.35
15
+ image: cognite/toolkit:0.7.37
16
16
  env:
17
17
  CDF_CLUSTER: ${{ vars.CDF_CLUSTER }}
18
18
  CDF_PROJECT: ${{ vars.CDF_PROJECT }}
@@ -10,7 +10,7 @@ jobs:
10
10
  environment: dev
11
11
  name: Deploy Dry Run
12
12
  container:
13
- image: cognite/toolkit:0.7.35
13
+ image: cognite/toolkit:0.7.37
14
14
  env:
15
15
  CDF_CLUSTER: ${{ vars.CDF_CLUSTER }}
16
16
  CDF_PROJECT: ${{ vars.CDF_PROJECT }}
@@ -4,7 +4,7 @@ default_env = "<DEFAULT_ENV_PLACEHOLDER>"
4
4
  [modules]
5
5
  # This is the version of the modules. It should not be changed manually.
6
6
  # It will be updated by the 'cdf modules upgrade' command.
7
- version = "0.7.35"
7
+ version = "0.7.37"
8
8
 
9
9
 
10
10
  [plugins]
@@ -1 +1 @@
1
- __version__ = "0.7.35"
1
+ __version__ = "0.7.37"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cognite_toolkit
3
- Version: 0.7.35
3
+ Version: 0.7.37
4
4
  Summary: Official Cognite Data Fusion tool for project templates and configuration deployment
5
5
  Author: Cognite AS
6
6
  Author-email: Cognite AS <support@cognite.com>