cognite-toolkit 0.7.50__py3-none-any.whl → 0.7.52__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.
@@ -21,6 +21,7 @@ from .api.extraction_pipelines import ExtractionPipelinesAPI
21
21
  from .api.filemetadata import FileMetadataAPI
22
22
  from .api.hosted_extractors import HostedExtractorsAPI
23
23
  from .api.infield import InfieldAPI
24
+ from .api.instances import InstancesAPI
24
25
  from .api.labels import LabelsAPI
25
26
  from .api.lookup import LookUpGroup
26
27
  from .api.migration import MigrationAPI
@@ -51,6 +52,7 @@ class ToolAPI:
51
52
  self.events = EventsAPI(http_client)
52
53
  self.extraction_pipelines = ExtractionPipelinesAPI(http_client)
53
54
  self.hosted_extractors = HostedExtractorsAPI(http_client)
55
+ self.instances = InstancesAPI(http_client)
54
56
  self.labels = LabelsAPI(http_client)
55
57
  self.filemetadata = FileMetadataAPI(http_client)
56
58
  self.raw = RawAPI(http_client)
@@ -83,7 +83,7 @@ class IndustrialCanvasAPI:
83
83
  def create(self, canvas: IndustrialCanvasApply) -> InstancesApplyResultList:
84
84
  instance_ids = canvas.as_instance_ids()
85
85
  existing = self._instance_api.retrieve(
86
- [node for node in instance_ids if isinstance(node, NodeId)],
86
+ nodes=[node for node in instance_ids if isinstance(node, NodeId)],
87
87
  edges=[edge for edge in instance_ids if isinstance(edge, EdgeId)],
88
88
  )
89
89
  if existing.nodes or existing.edges:
@@ -336,7 +336,11 @@ class HTTPClient:
336
336
 
337
337
  def _make_request2(self, message: BaseRequestMessage) -> httpx.Response:
338
338
  headers = self._create_headers(
339
- message.api_version, message.content_type, message.accept, disable_gzip=message.disable_gzip
339
+ message.api_version,
340
+ message.content_type,
341
+ message.accept,
342
+ content_length=message.content_length,
343
+ disable_gzip=message.disable_gzip,
340
344
  )
341
345
  return self.session.request(
342
346
  method=message.method,
@@ -1,11 +1,20 @@
1
1
  import gzip
2
2
  from abc import ABC, abstractmethod
3
+ from collections.abc import Hashable
3
4
  from typing import Any, Literal
4
5
 
5
6
  import httpx
6
7
  from cognite.client import global_config
7
8
  from pydantic import BaseModel, JsonValue, TypeAdapter, model_validator
8
9
 
10
+ from cognite_toolkit._cdf_tk.client.http_client._data_classes import (
11
+ ErrorDetails,
12
+ FailedRequestItems,
13
+ FailedRequestMessage,
14
+ FailedResponseItems,
15
+ ResponseMessage,
16
+ SuccessResponseItems,
17
+ )
9
18
  from cognite_toolkit._cdf_tk.client.http_client._exception import ToolkitAPIError
10
19
  from cognite_toolkit._cdf_tk.utils.useful_types import PrimitiveType
11
20
 
@@ -26,6 +35,29 @@ class HTTPResult2(BaseModel):
26
35
  else:
27
36
  raise ToolkitAPIError("Unknown HTTPResult2 type")
28
37
 
38
+ # Todo: Remove when HTTPResult2 is renamed to HTTPResponse and the old HTTPResponse is deleted
39
+ def as_item_response(self, item_id: Hashable) -> ResponseMessage | FailedRequestMessage:
40
+ if isinstance(self, SuccessResponse2):
41
+ return SuccessResponseItems(
42
+ status_code=self.status_code, content=self.content, ids=[item_id], body=self.body
43
+ )
44
+ elif isinstance(self, FailedResponse2):
45
+ return FailedResponseItems(
46
+ status_code=self.status_code,
47
+ ids=[item_id],
48
+ body=self.body,
49
+ error=ErrorDetails(
50
+ code=self.error.code,
51
+ message=self.error.message,
52
+ missing=self.error.missing,
53
+ duplicated=self.error.duplicated,
54
+ ),
55
+ )
56
+ elif isinstance(self, FailedRequest2):
57
+ return FailedRequestItems(ids=[item_id], error=self.error)
58
+ else:
59
+ raise ToolkitAPIError("Unknown HTTPResult2 type")
60
+
29
61
 
30
62
  class FailedRequest2(HTTPResult2):
31
63
  error: str
@@ -75,6 +107,7 @@ class BaseRequestMessage(BaseModel, ABC):
75
107
  status_attempt: int = 0
76
108
  api_version: str | None = None
77
109
  disable_gzip: bool = False
110
+ content_length: int | None = None
78
111
  content_type: str = "application/json"
79
112
  accept: str = "application/json"
80
113
 
@@ -1,5 +1,6 @@
1
1
  import sys
2
2
  from abc import ABC
3
+ from collections import defaultdict
3
4
  from collections.abc import Sequence
4
5
  from datetime import datetime, timezone
5
6
  from typing import Any, TypeVar
@@ -905,54 +906,86 @@ class IndustrialCanvasApply(CogniteResource):
905
906
  raise TypeError(f"Unexpected instance type: {type(instance)}")
906
907
  return ids
907
908
 
908
- def dump(self, keep_existing_version: bool = True) -> dict[str, JsonVal]:
909
+ def dump(self, camel_case: bool = True, keep_existing_version: bool = True) -> dict[str, JsonVal]:
909
910
  """Dump the IndustrialCanvasApply to a dictionary."""
910
911
  return {
911
- "canvas": self.canvas.dump(keep_existing_version=keep_existing_version),
912
+ "canvas": self.canvas.dump(camel_case=camel_case, keep_existing_version=keep_existing_version),
912
913
  "annotations": [
913
- annotation.dump(keep_existing_version=keep_existing_version) for annotation in self.annotations
914
+ annotation.dump(camel_case=camel_case, keep_existing_version=keep_existing_version)
915
+ for annotation in self.annotations
914
916
  ],
915
917
  "containerReferences": [
916
- container_ref.dump(keep_existing_version=keep_existing_version)
918
+ container_ref.dump(camel_case=camel_case, keep_existing_version=keep_existing_version)
917
919
  for container_ref in self.container_references
918
920
  ],
919
921
  "fdmInstanceContainerReferences": [
920
- fdm_instance_container_ref.dump(keep_existing_version=keep_existing_version)
922
+ fdm_instance_container_ref.dump(camel_case=camel_case, keep_existing_version=keep_existing_version)
921
923
  for fdm_instance_container_ref in self.fdm_instance_container_references
922
924
  ],
923
925
  "solutionTags": [
924
- solution_tag.dump(keep_existing_version=keep_existing_version) for solution_tag in self.solution_tags
926
+ solution_tag.dump(camel_case=camel_case, keep_existing_version=keep_existing_version)
927
+ for solution_tag in self.solution_tags
925
928
  ],
926
929
  }
927
930
 
928
931
  def create_backup(self) -> "IndustrialCanvasApply":
929
- """Create a duplicate of the IndustrialCanvasApply instance."""
932
+ """Create a backup copy of the IndustrialCanvasApply instance with new IDs."""
930
933
  new_canvas_id = str(uuid4())
934
+
931
935
  new_canvas = CanvasApply._load(self.canvas.dump(keep_existing_version=False))
932
936
  new_canvas.external_id = new_canvas_id
933
937
  new_canvas.source_canvas_id = self.canvas.external_id
934
938
  new_canvas.updated_at = datetime.now(tz=timezone.utc)
935
939
  # Solution tags are not duplicated, they are reused
936
- new_container = IndustrialCanvasApply(new_canvas, [], [], [], solution_tags=self.solution_tags)
940
+ canvas_backup = IndustrialCanvasApply(new_canvas, [], [], [], solution_tags=self.solution_tags)
937
941
  items: list[ContainerReferenceApply] | list[CanvasAnnotationApply] | list[FdmInstanceContainerReferenceApply]
938
942
  item_cls: type[CanvasAnnotationApply] | type[ContainerReferenceApply] | type[FdmInstanceContainerReferenceApply]
939
943
  new_item_list: list[NodeApply]
944
+ generator: dict[str, str] = defaultdict(lambda: str(uuid4()))
940
945
  for items, item_cls, new_item_list in [ # type: ignore[assignment]
941
- (self.annotations, CanvasAnnotationApply, new_container.annotations),
942
- (self.container_references, ContainerReferenceApply, new_container.container_references),
946
+ (self.annotations, CanvasAnnotationApply, canvas_backup.annotations),
947
+ (self.container_references, ContainerReferenceApply, canvas_backup.container_references),
943
948
  (
944
949
  self.fdm_instance_container_references,
945
950
  FdmInstanceContainerReferenceApply,
946
- new_container.fdm_instance_container_references,
951
+ canvas_backup.fdm_instance_container_references,
947
952
  ),
948
953
  ]:
949
954
  for item in items:
950
955
  # Serialize the item to create a new instance
951
956
  new_item = item_cls._load(item.dump(keep_existing_version=False))
952
- new_item.id_ = str(uuid4())
953
- new_item.external_id = f"{new_canvas_id}_{new_item.external_id}"
957
+ new_item.id_ = generator[new_item.id_]
958
+ new_item.external_id = f"{new_canvas_id}_{new_item.id_}"
954
959
  new_item_list.append(new_item)
955
- return new_container
960
+
961
+ return canvas_backup.replace_ids(generator)
962
+
963
+ def replace_ids(self, id_mapping_old_by_new: dict[str, str]) -> "IndustrialCanvasApply":
964
+ """Replace IDs in the IndustrialCanvasApply instance based on the provided ID mapping.
965
+
966
+ Args:
967
+ id_mapping_old_by_new: A dictionary mapping old IDs to new IDs.
968
+ Returns:
969
+ A new IndustrialCanvasApply instance with IDs replaced according to the mapping.
970
+ """
971
+ # There can be references to the old IDs in properties, for example, in annotations
972
+ # the properties field there can be fromId and toId set.
973
+ # We don't know all the places the Canvas application will have undocumented references,
974
+ # so we do a recursive search and replace based on the id mapping we have created.
975
+ dumped_data = self.dump(camel_case=True)
976
+
977
+ def _replace_ids_recursively(data: Any, id_map: dict[str, str]) -> Any:
978
+ if isinstance(data, dict):
979
+ return {key: _replace_ids_recursively(value, id_map) for key, value in data.items()}
980
+ if isinstance(data, list):
981
+ return [_replace_ids_recursively(item, id_map) for item in data]
982
+ if isinstance(data, str) and data in id_map:
983
+ return id_map[data]
984
+ return data
985
+
986
+ updated_data = _replace_ids_recursively(dumped_data, id_mapping_old_by_new)
987
+
988
+ return IndustrialCanvasApply._load(updated_data)
956
989
 
957
990
  @classmethod
958
991
  def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
@@ -401,6 +401,7 @@ class CanvasMapper(DataMapper[CanvasSelector, IndustrialCanvas, IndustrialCanvas
401
401
 
402
402
  remaining_container_references: list[ContainerReferenceApply] = []
403
403
  new_fdm_references: list[FdmInstanceContainerReferenceApply] = []
404
+ uuid_generator: dict[str, str] = defaultdict(lambda: str(uuid4()))
404
405
  for ref in update.container_references or []:
405
406
  if ref.container_reference_type not in self.asset_centric_resource_types:
406
407
  remaining_container_references.append(ref)
@@ -410,7 +411,9 @@ class CanvasMapper(DataMapper[CanvasSelector, IndustrialCanvas, IndustrialCanvas
410
411
  issue.missing_reference_ids.append(ref.as_asset_centric_id())
411
412
  else:
412
413
  consumer_view = self._get_consumer_view_id(ref.resource_id, ref.container_reference_type)
413
- fdm_ref = self.migrate_container_reference(ref, canvas.canvas.external_id, node_id, consumer_view)
414
+ fdm_ref = self.migrate_container_reference(
415
+ ref, canvas.canvas.external_id, node_id, consumer_view, uuid_generator
416
+ )
414
417
  new_fdm_references.append(fdm_ref)
415
418
  if issue.missing_reference_ids and self.skip_on_missing_ref:
416
419
  return None, issue
@@ -426,14 +429,22 @@ class CanvasMapper(DataMapper[CanvasSelector, IndustrialCanvas, IndustrialCanvas
426
429
  f"Failed to create backup for canvas '{canvas.canvas.name}': {e!s}. "
427
430
  ) from e
428
431
 
432
+ # There might annotations or other components that reference the old IDs, so we need to update those as well.
433
+ update = update.replace_ids(uuid_generator)
434
+
429
435
  return update, issue
430
436
 
431
437
  @classmethod
432
438
  def migrate_container_reference(
433
- cls, reference: ContainerReferenceApply, canvas_external_id: str, instance_id: NodeId, consumer_view: ViewId
439
+ cls,
440
+ reference: ContainerReferenceApply,
441
+ canvas_external_id: str,
442
+ instance_id: NodeId,
443
+ consumer_view: ViewId,
444
+ uuid_generator: dict[str, str],
434
445
  ) -> FdmInstanceContainerReferenceApply:
435
446
  """Migrate a single container reference by replacing the asset-centric ID with the data model instance ID."""
436
- new_id = str(uuid4())
447
+ new_id = uuid_generator[reference.id_]
437
448
  new_external_id = f"{canvas_external_id}_{new_id}"
438
449
  return FdmInstanceContainerReferenceApply(
439
450
  external_id=new_external_id,
@@ -10,7 +10,7 @@ from cognite_toolkit._cdf_tk.client.http_client import (
10
10
  HTTPClient,
11
11
  HTTPMessage,
12
12
  ItemsRequest,
13
- SimpleBodyRequest,
13
+ RequestMessage2,
14
14
  SuccessResponseItems,
15
15
  ToolkitAPIError,
16
16
  )
@@ -464,14 +464,14 @@ class ThreeDMigrationIO(UploadableStorageIO[ThreeDSelector, ThreeDModelResponse,
464
464
  for data in data_chunk:
465
465
  if data.source_id not in success_ids:
466
466
  continue
467
- revision = http_client.request_with_retries(
468
- message=SimpleBodyRequest(
467
+ revision = http_client.request_single_retries(
468
+ message=RequestMessage2(
469
469
  endpoint_url=self.client.config.create_api_url(self.REVISION_ENDPOINT),
470
470
  method="POST",
471
471
  body_content={"items": [data.item.revision.dump(camel_case=True)]},
472
472
  )
473
473
  )
474
- results.extend(revision.as_item_responses(data.source_id))
474
+ results.append(revision.as_item_response(data.source_id))
475
475
  return results
476
476
 
477
477
 
@@ -540,13 +540,14 @@ class BuildCommand(ToolkitCommand):
540
540
  continue
541
541
  elif client and self._check_resource_exists_in_cdf(client, loader_cls, id_):
542
542
  continue
543
- elif loader_cls.resource_cls is RawDatabase:
544
- # Raw Databases are automatically created when a Raw Table is created.
545
- continue
546
- required_by = {
547
- (required, path.relative_to(project_config_dir))
548
- for required, path in self._dependencies_by_required[(loader_cls, id_)]
549
- }
543
+ required_by: set[tuple[Hashable, Path]] = set()
544
+ for required, path in self._dependencies_by_required[(loader_cls, id_)]:
545
+ if path.name.endswith(RawTableCRUD.kind) and loader_cls is RawDatabaseCRUD:
546
+ # RAW Databases are automatically created when a Raw Table is created.
547
+ continue
548
+ relative_path = path.relative_to(project_config_dir)
549
+
550
+ required_by.add((required, relative_path))
550
551
  has_checked_cdf = client is not None
551
552
  self.warn(MissingDependencyWarning(loader_cls.resource_cls.__name__, id_, required_by, has_checked_cdf))
552
553
 
@@ -1,8 +1,17 @@
1
1
  from collections.abc import Iterable, Sequence
2
+ from itertools import zip_longest
2
3
  from typing import Any
3
4
 
5
+ from pydantic import JsonValue
6
+
4
7
  from cognite_toolkit._cdf_tk.client import ToolkitClient
5
- from cognite_toolkit._cdf_tk.client.http_client import HTTPClient, HTTPMessage, SimpleBodyRequest
8
+ from cognite_toolkit._cdf_tk.client.http_client import (
9
+ HTTPClient,
10
+ HTTPMessage,
11
+ HTTPResult2,
12
+ RequestMessage2,
13
+ SuccessResponse2,
14
+ )
6
15
  from cognite_toolkit._cdf_tk.client.resource_classes.legacy.canvas import (
7
16
  IndustrialCanvas,
8
17
  IndustrialCanvasApply,
@@ -185,23 +194,52 @@ class CanvasIO(UploadableStorageIO[CanvasSelector, IndustrialCanvas, IndustrialC
185
194
  results: list[HTTPMessage] = []
186
195
  for item in data_chunk:
187
196
  instances = item.item.as_instances()
188
- items: list[dict[str, JsonVal]] = []
197
+ upsert_items: list[dict[str, JsonValue]] = []
189
198
  for instance in instances:
190
199
  dumped = instance.dump()
191
200
  if self.exclude_existing_version:
192
201
  dumped.pop("existingVersion", None)
193
- items.append(dumped)
194
-
195
- responses = http_client.request_with_retries(
196
- message=SimpleBodyRequest(
197
- endpoint_url=config.create_api_url("/models/instances"),
198
- method="POST",
199
- # MyPy does not understand that .dump is valid json
200
- body_content={"items": items}, # type: ignore[dict-item]
201
- )
202
- )
203
- results.extend(responses.as_item_responses(item.source_id))
202
+ upsert_items.append(dumped)
203
+
204
+ canvas = item.item.canvas
205
+ existing = self.client.canvas.industrial.retrieve(canvas.external_id)
206
+ if existing is not None:
207
+ existing_instance_ids = existing.as_write().as_instance_ids(include_solution_tags=False)
208
+ delete_set = set(existing_instance_ids) - set(item.item.as_instance_ids())
209
+ to_delete: list[Any] = [
210
+ {
211
+ "space": instance_id.space,
212
+ "externalId": instance_id.external_id,
213
+ "instanceType": instance_id.instance_type,
214
+ }
215
+ for instance_id in delete_set
216
+ ]
217
+ else:
218
+ to_delete = []
204
219
 
220
+ last_response: HTTPResult2 | None = None
221
+ for upsert_chunk, delete_chunk in zip_longest(
222
+ chunker_sequence(upsert_items, 1000), chunker_sequence(to_delete, 1000), fillvalue=None
223
+ ):
224
+ body_content: dict[str, JsonValue] = {}
225
+ if upsert_chunk:
226
+ # MyPy fails do understand that list[dict[str, JsonValue]] is a subtype of JsonValue
227
+ body_content["items"] = upsert_chunk # type: ignore[assignment]
228
+ if delete_chunk:
229
+ body_content["delete"] = delete_chunk
230
+
231
+ response = http_client.request_single_retries(
232
+ message=RequestMessage2(
233
+ endpoint_url=config.create_api_url("/models/instances"),
234
+ method="POST",
235
+ body_content=body_content,
236
+ )
237
+ )
238
+ if not isinstance(response, SuccessResponse2):
239
+ results.append(response.as_item_response(item.source_id))
240
+ last_response = response
241
+ if last_response is not None:
242
+ results.append(last_response.as_item_response(item.source_id))
205
243
  return results
206
244
 
207
245
  def data_to_json_chunk(
@@ -10,14 +10,15 @@ from cognite.client.data_classes.data_modeling import ViewId
10
10
 
11
11
  from cognite_toolkit._cdf_tk.client import ToolkitClient
12
12
  from cognite_toolkit._cdf_tk.client.http_client import (
13
- DataBodyRequest,
14
13
  ErrorDetails,
15
- FailedResponse,
14
+ FailedResponse2,
16
15
  FailedResponseItems,
17
16
  HTTPClient,
18
17
  HTTPMessage,
19
- ResponseList,
18
+ HTTPResult2,
19
+ RequestMessage2,
20
20
  SimpleBodyRequest,
21
+ SuccessResponse2,
21
22
  )
22
23
  from cognite_toolkit._cdf_tk.client.resource_classes.data_modeling import NodeReference
23
24
  from cognite_toolkit._cdf_tk.client.resource_classes.filemetadata import FileMetadataRequest, FileMetadataResponse
@@ -274,8 +275,8 @@ class FileContentIO(UploadableStorageIO[FileContentSelector, MetadataWithFilePat
274
275
  continue
275
276
 
276
277
  content_bytes = item.file_path.read_bytes()
277
- upload_response = http_client.request_with_retries(
278
- message=DataBodyRequest(
278
+ upload_response = http_client.request_single_retries(
279
+ RequestMessage2(
279
280
  endpoint_url=upload_url,
280
281
  method="PUT",
281
282
  content_type=item.mime_type,
@@ -283,21 +284,21 @@ class FileContentIO(UploadableStorageIO[FileContentSelector, MetadataWithFilePat
283
284
  content_length=len(content_bytes),
284
285
  )
285
286
  )
286
- results.extend(upload_response.as_item_responses(item.as_id()))
287
+ results.append(upload_response.as_item_response(item.as_id()))
287
288
  return results
288
289
 
289
290
  def _upload_url_asset_centric(
290
291
  self, item: UploadFileContentItem, http_client: HTTPClient, results: MutableSequence[HTTPMessage]
291
292
  ) -> str | None:
292
- responses = http_client.request_with_retries(
293
- message=SimpleBodyRequest(
293
+ response = http_client.request_single_retries(
294
+ message=RequestMessage2(
294
295
  endpoint_url=http_client.config.create_api_url(self.UPLOAD_ENDPOINT),
295
296
  method="POST",
296
297
  # MyPy does not understand that .dump is valid json
297
298
  body_content=item.dump(), # type: ignore[arg-type]
298
299
  )
299
300
  )
300
- return self._parse_upload_link_response(responses, item, results)
301
+ return self._parse_upload_link_response(response, item, results)
301
302
 
302
303
  def _upload_url_data_modeling(
303
304
  self,
@@ -324,29 +325,27 @@ class FileContentIO(UploadableStorageIO[FileContentSelector, MetadataWithFilePat
324
325
  """
325
326
  # We know that instance_id is always set for data modeling uploads
326
327
  instance_id = cast(NodeReference, item.item.instance_id)
327
- responses = http_client.request_with_retries(
328
- message=SimpleBodyRequest(
328
+ response = http_client.request_single_retries(
329
+ message=RequestMessage2(
329
330
  endpoint_url=http_client.config.create_api_url("/files/uploadlink"),
330
331
  method="POST",
331
332
  body_content={"items": [{"instanceId": instance_id.dump()}]},
332
333
  )
333
334
  )
334
- # We know there is only one response since we only requested one upload link
335
- response = responses[0]
336
- if isinstance(response, FailedResponse) and response.error.missing and not created_node:
335
+ if isinstance(response, FailedResponse2) and response.error.missing and not created_node:
337
336
  if self._create_cognite_file_node(instance_id, http_client, item.as_id(), results):
338
337
  return self._upload_url_data_modeling(item, http_client, results, created_node=True)
339
338
  else:
340
339
  return None
341
340
 
342
- return self._parse_upload_link_response(responses, item, results)
341
+ return self._parse_upload_link_response(response, item, results)
343
342
 
344
343
  @classmethod
345
344
  def _create_cognite_file_node(
346
345
  cls, instance_id: NodeReference, http_client: HTTPClient, upload_id: str, results: MutableSequence[HTTPMessage]
347
346
  ) -> bool:
348
- node_creation = http_client.request_with_retries(
349
- message=SimpleBodyRequest(
347
+ node_creation = http_client.request_single_retries(
348
+ message=RequestMessage2(
350
349
  endpoint_url=http_client.config.create_api_url("/models/instances"),
351
350
  method="POST",
352
351
  body_content={
@@ -366,25 +365,33 @@ class FileContentIO(UploadableStorageIO[FileContentSelector, MetadataWithFilePat
366
365
  },
367
366
  )
368
367
  )
369
- try:
370
- _ = node_creation.get_first_body()
371
- except ValueError:
372
- results.extend(node_creation.as_item_responses(upload_id))
373
- return False
374
- return True
368
+ if isinstance(node_creation, SuccessResponse2):
369
+ # Node created successfully
370
+ return True
371
+ results.append(node_creation.as_item_response(instance_id))
372
+ return False
375
373
 
376
374
  @classmethod
377
375
  def _parse_upload_link_response(
378
- cls, responses: ResponseList, item: UploadFileContentItem, results: MutableSequence[HTTPMessage]
376
+ cls, response: HTTPResult2, item: UploadFileContentItem, results: MutableSequence[HTTPMessage]
379
377
  ) -> str | None:
378
+ if not isinstance(response, SuccessResponse2):
379
+ results.append(response.as_item_response(item.as_id()))
380
+ return None
380
381
  try:
381
- body = responses.get_first_body()
382
+ body = response.body_json
382
383
  except ValueError:
383
- results.extend(responses.as_item_responses(item.as_id()))
384
+ results.append(
385
+ FailedResponseItems(
386
+ status_code=response.status_code,
387
+ body=response.body,
388
+ error=ErrorDetails(code=response.status_code, message="Invalid JSON response"),
389
+ ids=[item.as_id()],
390
+ )
391
+ )
384
392
  return None
385
-
386
393
  if "items" in body and isinstance(body["items"], list) and len(body["items"]) > 0:
387
- body = body["items"][0] # type: ignore[assignment]
394
+ body = body["items"][0]
388
395
  try:
389
396
  upload_url = cast(str, body["uploadUrl"])
390
397
  except (KeyError, IndexError):
@@ -12,7 +12,7 @@ jobs:
12
12
  environment: dev
13
13
  name: Deploy
14
14
  container:
15
- image: cognite/toolkit:0.7.50
15
+ image: cognite/toolkit:0.7.52
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.50
13
+ image: cognite/toolkit:0.7.52
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.50"
7
+ version = "0.7.52"
8
8
 
9
9
 
10
10
  [plugins]
@@ -1 +1 @@
1
- __version__ = "0.7.50"
1
+ __version__ = "0.7.52"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cognite_toolkit
3
- Version: 0.7.50
3
+ Version: 0.7.52
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>
@@ -30,7 +30,7 @@ cognite_toolkit/_cdf_tk/cdf_toml.py,sha256=VSWV9h44HusWIaKpWgjrOMrc3hDoPTTXBXlp6
30
30
  cognite_toolkit/_cdf_tk/client/__init__.py,sha256=a6rQXDGfW2g7K5WwrOW5oakh1TdFlBjUVjf9wusOox8,135
31
31
  cognite_toolkit/_cdf_tk/client/_constants.py,sha256=COUGcea37mDF2sf6MGqJXWmecTY_6aCImslxXrYW1I0,73
32
32
  cognite_toolkit/_cdf_tk/client/_resource_base.py,sha256=Zbo-Z3K9xGbF7WjRl_aIWQjxIa9V94Yc7RvKI2CF5fQ,7227
33
- cognite_toolkit/_cdf_tk/client/_toolkit_client.py,sha256=b-1uzvgUKIt6On_qtm4RGmlwEd1FDHg-LmIglsd9fFI,5206
33
+ cognite_toolkit/_cdf_tk/client/_toolkit_client.py,sha256=P3zJeXdUDShf40XCAf9i9SjhZn7myo_COyMlJHfWr6s,5297
34
34
  cognite_toolkit/_cdf_tk/client/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  cognite_toolkit/_cdf_tk/client/api/agents.py,sha256=nhbPsDtU-WOS4NTyvci2691JN3u__robPvO7jIrMMis,3903
36
36
  cognite_toolkit/_cdf_tk/client/api/annotations.py,sha256=7uTMiJ6P-gJtHsDjWWDpfUVK0jECDNp0Y8-Fg-gIi3g,4638
@@ -54,7 +54,7 @@ cognite_toolkit/_cdf_tk/client/api/infield.py,sha256=LLc0WUG_QqJMPTaqMYRgMwH59bP
54
54
  cognite_toolkit/_cdf_tk/client/api/instances.py,sha256=HO9PkueqnF7YpaATGseXbCLz59iNqXPfP_I48bicVzo,5620
55
55
  cognite_toolkit/_cdf_tk/client/api/labels.py,sha256=oWM_dsDlazIO6IFwipckkkrj4WGVWWWsK9CcioCan9o,4360
56
56
  cognite_toolkit/_cdf_tk/client/api/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- cognite_toolkit/_cdf_tk/client/api/legacy/canvas.py,sha256=jLiuztUvpkfMsddc-1eZGVa5naSOHIiDczNCbhCvGGA,9307
57
+ cognite_toolkit/_cdf_tk/client/api/legacy/canvas.py,sha256=Xyded-e7dqu-l2PR3U9PZ3maSKyjH56ApTJTpCPAh08,9313
58
58
  cognite_toolkit/_cdf_tk/client/api/legacy/charts.py,sha256=5NtyySLHfITYEw1D7osSZjW75js0Uu7ow34_CJq-pSc,4964
59
59
  cognite_toolkit/_cdf_tk/client/api/legacy/dml.py,sha256=8b1lo86JdvfEsz9mP2rx0Mp9fyWsU6mbXHqLBtvSidU,3546
60
60
  cognite_toolkit/_cdf_tk/client/api/legacy/extended_data_modeling.py,sha256=XgVMPDDERqlB6wphWmNcWYJ1kS0XIkTYqMQDJUZLTTw,12978
@@ -110,9 +110,9 @@ cognite_toolkit/_cdf_tk/client/cdf_client/api.py,sha256=QaL5P3HyyI51j3xprm02K0Pc
110
110
  cognite_toolkit/_cdf_tk/client/cdf_client/responses.py,sha256=UVhvU_8UKCLsjCFaSiVFF6uk72pHOx87ZLk88dhuOYk,1050
111
111
  cognite_toolkit/_cdf_tk/client/config.py,sha256=weMR43z-gqHMn-Jqvfmh_nJ0HbgEdyeCGtISuEf3OuY,4269
112
112
  cognite_toolkit/_cdf_tk/client/http_client/__init__.py,sha256=-RNm4iXlNX9f_JLW4QKXiet7LrWotCE36ZOlIqyhZT8,1504
113
- cognite_toolkit/_cdf_tk/client/http_client/_client.py,sha256=6xmwelwCZzdv5_eLOq_F7DmlBGxun4bbVI1ouks2vZs,22664
113
+ cognite_toolkit/_cdf_tk/client/http_client/_client.py,sha256=a9ZcW46Ht5mt7wtJJH_ty34E9IxUJTv1NY0xclNUeCg,22752
114
114
  cognite_toolkit/_cdf_tk/client/http_client/_data_classes.py,sha256=c-Uau6qOi5TLM5cPE84CkTfrKB_dGhoYHWLXSEOo5AM,15438
115
- cognite_toolkit/_cdf_tk/client/http_client/_data_classes2.py,sha256=NgAXetqUTIjSSxDc_N5bEv2fSeWl1QBR8zAhsCLRIjE,4106
115
+ cognite_toolkit/_cdf_tk/client/http_client/_data_classes2.py,sha256=2aV1pmwBxyuUnEYoNr294GnZSykGH3hQyfMyjE-9hq4,5439
116
116
  cognite_toolkit/_cdf_tk/client/http_client/_exception.py,sha256=9dE5tm1qTviG93JppLql6ltlmAgm8TxWh9wWPdm0ITA,428
117
117
  cognite_toolkit/_cdf_tk/client/http_client/_item_classes.py,sha256=BRilwk05WTHoM03DifyUBQx-4-OHIHp8gOoQPh1zNBg,4474
118
118
  cognite_toolkit/_cdf_tk/client/http_client/_tracker.py,sha256=pu6oA-XpOeaOLdoeD_mGfJXC3BFGWfh5oGcRDpb6maw,1407
@@ -169,7 +169,7 @@ cognite_toolkit/_cdf_tk/client/resource_classes/instance_api.py,sha256=-zt7T_QpH
169
169
  cognite_toolkit/_cdf_tk/client/resource_classes/label.py,sha256=-w7VxTOmHZkgiEjQ-trGY2JOWo-ZU4nqhmM2UrpkhEI,650
170
170
  cognite_toolkit/_cdf_tk/client/resource_classes/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
171
  cognite_toolkit/_cdf_tk/client/resource_classes/legacy/apm_config_v1.py,sha256=0bPq7R0qvdf8SMFS06kX7TXHIClDcJNHwdTBweQB-GU,20150
172
- cognite_toolkit/_cdf_tk/client/resource_classes/legacy/canvas.py,sha256=pXJEyH_9bmpPEdxbgV5SPQbLgT2RIEdwmWSRJfHtmts,50732
172
+ cognite_toolkit/_cdf_tk/client/resource_classes/legacy/canvas.py,sha256=Wf064-S3iBJiqxHgelFG0DCbtX0ZipAsfMU7FS6E66g,52450
173
173
  cognite_toolkit/_cdf_tk/client/resource_classes/legacy/charts.py,sha256=pshXpYVc51j4nwG4lf-_98TU5VnHkOSRqjuofJTavGQ,3749
174
174
  cognite_toolkit/_cdf_tk/client/resource_classes/legacy/extendable_cognite_file.py,sha256=0iyLiXEzB4WBU-DL6DZS6nD5E526cDsftMGEYXwI8r8,9764
175
175
  cognite_toolkit/_cdf_tk/client/resource_classes/legacy/extended_filemetadata.py,sha256=8zfXl_bhkums3quJzdOwAjxVNY6B0hpAs6jbkekn79o,5488
@@ -227,11 +227,11 @@ cognite_toolkit/_cdf_tk/commands/_migrate/command.py,sha256=S5ZB7POjJ2ue3D54kW8T
227
227
  cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py,sha256=-sZktmsDIqkhNg-kg95Ty6eTm7FiyFRi1ZQLOkZ5x2w,17889
228
228
  cognite_toolkit/_cdf_tk/commands/_migrate/creators.py,sha256=Gp3CKruTxeSDS3HiWiLsQ4mN2SZ4BQB5xQ50o68GTs8,9616
229
229
  cognite_toolkit/_cdf_tk/commands/_migrate/data_classes.py,sha256=4hv_TKTfEZoC9h6lIlAW_ewKlT6F4KrquQpqUz8M1iw,11679
230
- cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py,sha256=qRCXI68Fq4eU4UcUwbiQNt2FCgBT_nWKzzUiEtWzfzI,27707
230
+ cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py,sha256=qHYeFCBBGPejbgC_g_uHNM8fJLBkxWBBNKLFILkPaTI,28097
231
231
  cognite_toolkit/_cdf_tk/commands/_migrate/data_model.py,sha256=0lRyDRJ8zo00OngwWagQgHQIaemK4eufW9kbWwZ9Yo0,7901
232
232
  cognite_toolkit/_cdf_tk/commands/_migrate/default_mappings.py,sha256=nH_wC0RzcI721sXwH_pThOxPv1nq4-oBd1rCDSGbr9Y,5555
233
233
  cognite_toolkit/_cdf_tk/commands/_migrate/issues.py,sha256=SFkfLBCLI4nZBIWSRnyu6G4xcdS-csYJwzmzc4Jmzho,6988
234
- cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py,sha256=ClRvEzJDOft_oQJGlKpYt8wBRjrfJ_jtpVmRe7YO8a8,26801
234
+ cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py,sha256=ZrmI_jx6sf7G027-G9arVjtr0DyUn8onUAMmsEFn67E,26798
235
235
  cognite_toolkit/_cdf_tk/commands/_migrate/prepare.py,sha256=RfqaNoso5CyBwc-p6ckwcYqBfZXKhdJgdGIyd0TATaI,2635
236
236
  cognite_toolkit/_cdf_tk/commands/_migrate/selectors.py,sha256=N1H_-rBpPUD6pbrlcofn1uEK1bA694EUXEe1zIXeqyo,2489
237
237
  cognite_toolkit/_cdf_tk/commands/_profile.py,sha256=c42Na8r1Xcd1zSIJtU8eZMQTFBTzNmxtTIBLKBePzyA,43131
@@ -242,7 +242,7 @@ cognite_toolkit/_cdf_tk/commands/_utils.py,sha256=UxMJW5QYKts4om5n6x2Tq2ihvfO9gW
242
242
  cognite_toolkit/_cdf_tk/commands/_virtual_env.py,sha256=GFAid4hplixmj9_HkcXqU5yCLj-fTXm4cloGD6U2swY,2180
243
243
  cognite_toolkit/_cdf_tk/commands/about.py,sha256=pEXNdCeJYONOalH8x-7QRsKLgj-9gdIqN16pPxA3bhg,9395
244
244
  cognite_toolkit/_cdf_tk/commands/auth.py,sha256=TX_8YuVCjMVIQjEdfBE66bSDrojJhCnxf_jcT3-9wM8,32550
245
- cognite_toolkit/_cdf_tk/commands/build_cmd.py,sha256=vpEEf9plCeY1OJnvm4P38wsqVLLSVH00TMjpwAHw-IY,28970
245
+ cognite_toolkit/_cdf_tk/commands/build_cmd.py,sha256=NuHbOj0xMbyuESlP716GHZuD1IY-OMoSaTtx0NUnVmk,29092
246
246
  cognite_toolkit/_cdf_tk/commands/build_v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
247
247
  cognite_toolkit/_cdf_tk/commands/build_v2/_module_parser.py,sha256=B_Ddt8oB3tWto0Ocja9kvWaoIZyt8Oa-ukuoptQBYww,5916
248
248
  cognite_toolkit/_cdf_tk/commands/build_v2/_modules_parser.py,sha256=se9IhfwtbvWusqNeN2BzDnUEK3j97sN4Yugoh5xlc5U,6782
@@ -370,12 +370,12 @@ cognite_toolkit/_cdf_tk/resource_classes/workflow_trigger.py,sha256=aSN0WFPupQ38
370
370
  cognite_toolkit/_cdf_tk/resource_classes/workflow_version.py,sha256=ZCn7xJyTEQCjWbvceny6yJYhqFcS64LbR228dbGjLXI,10195
371
371
  cognite_toolkit/_cdf_tk/storageio/__init__.py,sha256=h5Wr4i7zNIgsslrsRJxmp7ls4bNRKl0uZzQ7GLRMP7g,1920
372
372
  cognite_toolkit/_cdf_tk/storageio/_annotations.py,sha256=QcFrikDgz-9VjNy4Xq7wchM4VOQh-z2JaHcWR2C1sEs,4879
373
- cognite_toolkit/_cdf_tk/storageio/_applications.py,sha256=w408KhJhYzoLvnz7t7QCydCp6TqQS8fMnZTmSo_I0lw,19708
373
+ cognite_toolkit/_cdf_tk/storageio/_applications.py,sha256=8XYcXHnrshxw0wB6ehtbiVZXgQxx-ci7czmUbwP-tXE,21338
374
374
  cognite_toolkit/_cdf_tk/storageio/_asset_centric.py,sha256=IM17Ouq-5ozbvr6LbE6-fiijorHUV734VRj7S2JjbJw,32822
375
375
  cognite_toolkit/_cdf_tk/storageio/_base.py,sha256=EBAueJQBSkMShRCt5PYoscGAxOeKuQEteG5lSEFrXf0,13158
376
376
  cognite_toolkit/_cdf_tk/storageio/_data_classes.py,sha256=s3TH04BJ1q7rXndRhEbVMEnoOXjxrGg4n-w9Z5uUL-o,3480
377
377
  cognite_toolkit/_cdf_tk/storageio/_datapoints.py,sha256=sgO5TAD87gHn8gxTwRM3yn__yVDsOrNR_MDoOpZwcUg,20207
378
- cognite_toolkit/_cdf_tk/storageio/_file_content.py,sha256=R1f2A9ZkQ-8O0b0kjhku1PNLJnTOlLMTb0tnGSYW-nU,19138
378
+ cognite_toolkit/_cdf_tk/storageio/_file_content.py,sha256=Flfh2yekYQQKjx9TKclQ6LvaifZlDAK2PNLFGgBhfuo,19408
379
379
  cognite_toolkit/_cdf_tk/storageio/_instances.py,sha256=2mb9nTC63cn3r1B9YqA0wAmHcbJhMDiET78T7XY5Yco,10821
380
380
  cognite_toolkit/_cdf_tk/storageio/_raw.py,sha256=VqzAF79ON3hjrVRTBsSiSGK9B_Xmm-PWhFxvA0YKgPE,5162
381
381
  cognite_toolkit/_cdf_tk/storageio/logger.py,sha256=RDQvauxSjtlVX-V5XGkFCtqiWpv4KdjJrEcPFVNqPF0,5557
@@ -432,14 +432,14 @@ cognite_toolkit/_repo_files/.gitignore,sha256=ip9kf9tcC5OguF4YF4JFEApnKYw0nG0vPi
432
432
  cognite_toolkit/_repo_files/AzureDevOps/.devops/README.md,sha256=OLA0D7yCX2tACpzvkA0IfkgQ4_swSd-OlJ1tYcTBpsA,240
433
433
  cognite_toolkit/_repo_files/AzureDevOps/.devops/deploy-pipeline.yml,sha256=brULcs8joAeBC_w_aoWjDDUHs3JheLMIR9ajPUK96nc,693
434
434
  cognite_toolkit/_repo_files/AzureDevOps/.devops/dry-run-pipeline.yml,sha256=OBFDhFWK1mlT4Dc6mDUE2Es834l8sAlYG50-5RxRtHk,723
435
- cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml,sha256=ITEPjM1_JU4L_wL3S7xPIuRRiVOUSji9ilNanqfCMOA,667
436
- cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml,sha256=HBdIygaLnjtyFOKjUdtghhIT0J3tYezMQEcs7BALh5A,2430
437
- cognite_toolkit/_resources/cdf.toml,sha256=vrQOgtY6R7zl1zJiANMcmA3RrsekHMyCgTTf1puKma8,475
438
- cognite_toolkit/_version.py,sha256=C8JDDil3jbYwX88n-yDO8-hkoqO-aB7NgT8xZbrabbo,23
435
+ cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml,sha256=xy_q_7MzPwjNb9E76l4uLlB6lin4xoBB6uH3IDkIZqQ,667
436
+ cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml,sha256=anDBld8WwyrcTrZ1nxIPiZMjtglHi7A5DU_xWPDEwh4,2430
437
+ cognite_toolkit/_resources/cdf.toml,sha256=IRD27JLKpdtIwxDb-Gx4a044jvdvJ81rWooGxX7n-yA,475
438
+ cognite_toolkit/_version.py,sha256=a-nEs8L7fsmTx0R5cwwxN_EGLwgnVE5B6NGA6iRovfE,23
439
439
  cognite_toolkit/config.dev.yaml,sha256=M33FiIKdS3XKif-9vXniQ444GTZ-bLXV8aFH86u9iUQ,332
440
440
  cognite_toolkit/demo/__init__.py,sha256=-m1JoUiwRhNCL18eJ6t7fZOL7RPfowhCuqhYFtLgrss,72
441
441
  cognite_toolkit/demo/_base.py,sha256=6xKBUQpXZXGQ3fJ5f7nj7oT0s2n7OTAGIa17ZlKHZ5U,8052
442
- cognite_toolkit-0.7.50.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
443
- cognite_toolkit-0.7.50.dist-info/entry_points.txt,sha256=EtZ17K2mUjh-AY0QNU1CPIB_aDSSOdmtNI_4Fj967mA,84
444
- cognite_toolkit-0.7.50.dist-info/METADATA,sha256=lmuyL3CvrjV2gWrcJyklepqcfpctGOdIcAaJuG-KuMY,5026
445
- cognite_toolkit-0.7.50.dist-info/RECORD,,
442
+ cognite_toolkit-0.7.52.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
443
+ cognite_toolkit-0.7.52.dist-info/entry_points.txt,sha256=EtZ17K2mUjh-AY0QNU1CPIB_aDSSOdmtNI_4Fj967mA,84
444
+ cognite_toolkit-0.7.52.dist-info/METADATA,sha256=vonl6M9nNo9tU-nQZ8sQ5uwdbt-5St5rfU-CxvbCv3A,5026
445
+ cognite_toolkit-0.7.52.dist-info/RECORD,,