cognite-toolkit 0.7.47__py3-none-any.whl → 0.7.49__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 (62) hide show
  1. cognite_toolkit/_cdf_tk/apps/_migrate_app.py +6 -6
  2. cognite_toolkit/_cdf_tk/client/_toolkit_client.py +6 -4
  3. cognite_toolkit/_cdf_tk/client/api/instances.py +139 -0
  4. cognite_toolkit/_cdf_tk/client/api/location_filters.py +177 -0
  5. cognite_toolkit/_cdf_tk/client/api/raw.py +2 -2
  6. cognite_toolkit/_cdf_tk/client/api/robotics.py +19 -0
  7. cognite_toolkit/_cdf_tk/client/api/robotics_capabilities.py +127 -0
  8. cognite_toolkit/_cdf_tk/client/api/robotics_data_postprocessing.py +138 -0
  9. cognite_toolkit/_cdf_tk/client/api/robotics_frames.py +122 -0
  10. cognite_toolkit/_cdf_tk/client/api/robotics_locations.py +127 -0
  11. cognite_toolkit/_cdf_tk/client/api/robotics_maps.py +122 -0
  12. cognite_toolkit/_cdf_tk/client/api/robotics_robots.py +122 -0
  13. cognite_toolkit/_cdf_tk/client/api/search_config.py +101 -0
  14. cognite_toolkit/_cdf_tk/client/api/streams.py +63 -55
  15. cognite_toolkit/_cdf_tk/client/api/three_d.py +293 -277
  16. cognite_toolkit/_cdf_tk/client/cdf_client/api.py +34 -5
  17. cognite_toolkit/_cdf_tk/client/http_client/_client.py +5 -2
  18. cognite_toolkit/_cdf_tk/client/http_client/_data_classes2.py +4 -3
  19. cognite_toolkit/_cdf_tk/client/request_classes/filters.py +45 -1
  20. cognite_toolkit/_cdf_tk/client/resource_classes/apm_config.py +128 -0
  21. cognite_toolkit/_cdf_tk/client/resource_classes/cognite_file.py +53 -0
  22. cognite_toolkit/_cdf_tk/client/resource_classes/data_modeling/__init__.py +4 -0
  23. cognite_toolkit/_cdf_tk/client/resource_classes/data_modeling/_instance.py +22 -11
  24. cognite_toolkit/_cdf_tk/client/resource_classes/identifiers.py +7 -0
  25. cognite_toolkit/_cdf_tk/client/resource_classes/location_filter.py +9 -2
  26. cognite_toolkit/_cdf_tk/client/resource_classes/resource_view_mapping.py +38 -0
  27. cognite_toolkit/_cdf_tk/client/resource_classes/robotics/_map.py +6 -1
  28. cognite_toolkit/_cdf_tk/client/resource_classes/robotics/_robot.py +10 -5
  29. cognite_toolkit/_cdf_tk/client/resource_classes/streams.py +1 -20
  30. cognite_toolkit/_cdf_tk/client/resource_classes/three_d.py +30 -9
  31. cognite_toolkit/_cdf_tk/client/testing.py +2 -2
  32. cognite_toolkit/_cdf_tk/commands/_migrate/command.py +103 -108
  33. cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +6 -1
  34. cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +119 -41
  35. cognite_toolkit/_cdf_tk/commands/_migrate/issues.py +21 -38
  36. cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +14 -12
  37. cognite_toolkit/_cdf_tk/commands/build_v2/_module_parser.py +138 -0
  38. cognite_toolkit/_cdf_tk/commands/build_v2/_modules_parser.py +163 -0
  39. cognite_toolkit/_cdf_tk/commands/build_v2/build_cmd.py +83 -96
  40. cognite_toolkit/_cdf_tk/commands/build_v2/{build_input.py → build_parameters.py} +8 -22
  41. cognite_toolkit/_cdf_tk/commands/build_v2/data_classes/_modules.py +27 -0
  42. cognite_toolkit/_cdf_tk/commands/build_v2/data_classes/_resource.py +22 -0
  43. cognite_toolkit/_cdf_tk/cruds/__init__.py +11 -5
  44. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +14 -30
  45. cognite_toolkit/_cdf_tk/data_classes/__init__.py +3 -0
  46. cognite_toolkit/_cdf_tk/data_classes/_issues.py +36 -0
  47. cognite_toolkit/_cdf_tk/data_classes/_module_directories.py +2 -1
  48. cognite_toolkit/_cdf_tk/storageio/_base.py +2 -0
  49. cognite_toolkit/_cdf_tk/storageio/logger.py +162 -0
  50. cognite_toolkit/_cdf_tk/utils/__init__.py +8 -1
  51. cognite_toolkit/_cdf_tk/utils/interactive_select.py +3 -1
  52. cognite_toolkit/_cdf_tk/utils/modules.py +7 -0
  53. cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
  54. cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
  55. cognite_toolkit/_resources/cdf.toml +1 -1
  56. cognite_toolkit/_version.py +1 -1
  57. {cognite_toolkit-0.7.47.dist-info → cognite_toolkit-0.7.49.dist-info}/METADATA +1 -1
  58. {cognite_toolkit-0.7.47.dist-info → cognite_toolkit-0.7.49.dist-info}/RECORD +61 -43
  59. cognite_toolkit/_cdf_tk/commands/build_v2/build_issues.py +0 -27
  60. /cognite_toolkit/_cdf_tk/client/resource_classes/{search_config_resource.py → search_config.py} +0 -0
  61. {cognite_toolkit-0.7.47.dist-info → cognite_toolkit-0.7.49.dist-info}/WHEEL +0 -0
  62. {cognite_toolkit-0.7.47.dist-info → cognite_toolkit-0.7.49.dist-info}/entry_points.txt +0 -0
@@ -51,15 +51,20 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
51
51
  including creating, retrieving, deleting, and listing resources.
52
52
  """
53
53
 
54
- def __init__(self, http_client: HTTPClient, method_endpoint_map: dict[APIMethod, Endpoint]) -> None:
54
+ def __init__(
55
+ self, http_client: HTTPClient, method_endpoint_map: dict[APIMethod, Endpoint], disable_gzip: bool = False
56
+ ) -> None:
55
57
  """Initialize the resource API.
56
58
 
57
59
  Args:
58
60
  http_client: The HTTP client to use for API requests.
59
61
  method_endpoint_map: A mapping of endpoint suffixes to their properties.
62
+ disable_gzip: Whether to disable gzip compression for requests. Defaults to False.
63
+ This is only used by the robotics API. If that API is dropped, this parameter can be removed.
60
64
  """
61
65
  self._http_client = http_client
62
66
  self._method_endpoint_map = method_endpoint_map
67
+ self._disable_gzip = disable_gzip
63
68
 
64
69
  @classmethod
65
70
  def _serialize_items(cls, items: Sequence[BaseModel]) -> list[dict[str, JsonValue]]:
@@ -151,6 +156,7 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
151
156
  method=endpoint.method,
152
157
  body_content={"items": serialization(chunk), **(extra_body or {})}, # type: ignore[dict-item]
153
158
  parameters=request_params,
159
+ disable_gzip=self._disable_gzip,
154
160
  )
155
161
  response = self._http_client.request_single_retries(request)
156
162
  yield response.get_success_or_raise()
@@ -180,6 +186,27 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
180
186
  response_items.extend(self._validate_page_response(response).items)
181
187
  return response_items
182
188
 
189
+ def _request_item_split_retries_no_response(
190
+ self,
191
+ items: Sequence[_T_BaseModel],
192
+ method: APIMethod,
193
+ params: dict[str, Any] | None = None,
194
+ extra_body: dict[str, Any] | None = None,
195
+ ) -> None:
196
+ """Request items with retries, splitting on failures, without returning any response.
197
+
198
+ This method handles large batches of items by chunking them according to the endpoint's item limit.
199
+ If a single item fails, it splits the request into individual item requests to isolate the failure.
200
+
201
+ Args:
202
+ items: Sequence of items to request.
203
+ method: API method to use for the request.
204
+ params: Optional query parameters for the request.
205
+ extra_body: Optional additional body fields for the request.
206
+ """
207
+ list(self._chunk_requests_items_split_retries(items, method, params, extra_body))
208
+ return None
209
+
183
210
  def _chunk_requests_items_split_retries(
184
211
  self,
185
212
  items: Sequence[_T_BaseModel],
@@ -215,6 +242,7 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
215
242
  parameters=request_params,
216
243
  items=chunk,
217
244
  extra_body_fields=extra_body,
245
+ disable_gzip=self._disable_gzip,
218
246
  )
219
247
  responses = self._http_client.request_items_retries(request)
220
248
  for response in responses:
@@ -230,12 +258,12 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
230
258
 
231
259
  @classmethod
232
260
  def _group_items_by_text_field(
233
- cls, items: Sequence[_T_BaseModel], field_name: str
234
- ) -> dict[str, list[_T_BaseModel]]:
261
+ cls, items: Sequence[_T_BaseModel], *field_names: str
262
+ ) -> dict[tuple[str, ...], list[_T_BaseModel]]:
235
263
  """Group items by a text field."""
236
- grouped_items: dict[str, list[_T_BaseModel]] = defaultdict(list)
264
+ grouped_items: dict[tuple[str, ...], list[_T_BaseModel]] = defaultdict(list)
237
265
  for item in items:
238
- key = str(getattr(item, field_name))
266
+ key = tuple(str(getattr(item, field_name)) for field_name in field_names)
239
267
  grouped_items[key].append(item)
240
268
  return grouped_items
241
269
 
@@ -287,6 +315,7 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
287
315
  method=endpoint.method,
288
316
  parameters=request_params,
289
317
  body_content=body,
318
+ disable_gzip=self._disable_gzip,
290
319
  )
291
320
  result = self._http_client.request_single_retries(request)
292
321
  response = result.get_success_or_raise()
@@ -172,6 +172,7 @@ class HTTPClient:
172
172
  content_type: str = "application/json",
173
173
  accept: str = "application/json",
174
174
  content_length: int | None = None,
175
+ disable_gzip: bool = False,
175
176
  ) -> MutableMapping[str, str]:
176
177
  headers: MutableMapping[str, str] = {}
177
178
  headers["User-Agent"] = f"httpx/{httpx.__version__} {get_user_agent()}"
@@ -184,7 +185,7 @@ class HTTPClient:
184
185
  headers["x-cdp-sdk"] = f"CogniteToolkit:{get_current_toolkit_version()}"
185
186
  headers["x-cdp-app"] = self.config.client_name
186
187
  headers["cdf-version"] = api_version or self.config.api_subversion
187
- if not global_config.disable_gzip and content_length is None:
188
+ if not global_config.disable_gzip and content_length is None and not disable_gzip:
188
189
  headers["Content-Encoding"] = "gzip"
189
190
  return headers
190
191
 
@@ -332,7 +333,9 @@ class HTTPClient:
332
333
  raise TypeError(f"Unexpected result type: {type(result)}")
333
334
 
334
335
  def _make_request2(self, message: BaseRequestMessage) -> httpx.Response:
335
- headers = self._create_headers(message.api_version, message.content_type, message.accept)
336
+ headers = self._create_headers(
337
+ message.api_version, message.content_type, message.accept, disable_gzip=message.disable_gzip
338
+ )
336
339
  return self.session.request(
337
340
  method=message.method,
338
341
  url=message.endpoint_url,
@@ -77,6 +77,7 @@ class BaseRequestMessage(BaseModel, ABC):
77
77
  read_attempt: int = 0
78
78
  status_attempt: int = 0
79
79
  api_version: str | None = None
80
+ disable_gzip: bool = False
80
81
  content_type: str = "application/json"
81
82
  accept: str = "application/json"
82
83
 
@@ -106,13 +107,13 @@ class RequestMessage2(BaseRequestMessage):
106
107
  data: str | bytes | None = None
107
108
  if self.data_content is not None:
108
109
  data = self.data_content
109
- if not global_config.disable_gzip:
110
+ if not global_config.disable_gzip and not self.disable_gzip:
110
111
  data = gzip.compress(data)
111
112
  elif self.body_content is not None:
112
113
  # We serialize using pydantic instead of json.dumps. This is because pydantic is faster
113
114
  # and handles more complex types such as datetime, float('nan'), etc.
114
115
  data = _BODY_SERIALIZER.dump_json(self.body_content)
115
- if not global_config.disable_gzip and isinstance(data, bytes):
116
+ if not global_config.disable_gzip and not self.disable_gzip and isinstance(data, bytes):
116
117
  data = gzip.compress(data)
117
118
  return data
118
119
 
@@ -161,7 +162,7 @@ class ItemsRequest2(BaseRequestMessage):
161
162
  if self.extra_body_fields:
162
163
  body.update(self.extra_body_fields)
163
164
  res = _BODY_SERIALIZER.dump_json(body)
164
- if not global_config.disable_gzip and isinstance(res, bytes):
165
+ if not global_config.disable_gzip and not self.disable_gzip and isinstance(res, bytes):
165
166
  return gzip.compress(res)
166
167
  return res
167
168
 
@@ -1,7 +1,10 @@
1
1
  import sys
2
- from typing import Literal
2
+ from typing import Any, Literal
3
+
4
+ from pydantic import Field
3
5
 
4
6
  from cognite_toolkit._cdf_tk.client.resource_classes.annotation import AnnotationStatus, AnnotationType
7
+ from cognite_toolkit._cdf_tk.client.resource_classes.data_modeling import NodeReference, ViewReference
5
8
  from cognite_toolkit._cdf_tk.client.resource_classes.identifiers import ExternalId, InternalId
6
9
 
7
10
  from .base import BaseModelRequest
@@ -59,6 +62,28 @@ class DataModelFilter(DataModelingFilter):
59
62
  all_versions: bool | None = None
60
63
 
61
64
 
65
+ class InstanceFilter(Filter):
66
+ instance_type: Literal["node", "edge"] | None = None
67
+ source: ViewReference | None = None
68
+ space: list[str] | None = None
69
+
70
+ def dump(self, camel_case: bool = True) -> dict[str, Any]:
71
+ body: dict[str, Any] = {}
72
+ if self.instance_type is not None:
73
+ body["instanceType"] = self.instance_type
74
+ if self.source is not None:
75
+ body["sources"] = [{"source": self.source.dump()}]
76
+ if self.space is not None:
77
+ instance_type = self.instance_type or "node"
78
+ body["filter"] = {
79
+ "in": {
80
+ "property": [instance_type, "space"],
81
+ "values": self.space,
82
+ }
83
+ }
84
+ return body
85
+
86
+
62
87
  class AnnotationFilter(Filter):
63
88
  annotated_resource_type: Literal["file", "threedmodel"]
64
89
  annotated_resource_ids: list[ExternalId | InternalId]
@@ -67,3 +92,22 @@ class AnnotationFilter(Filter):
67
92
  creating_app_version: str | None = None
68
93
  creating_user: str | None = None
69
94
  status: AnnotationStatus | None = None
95
+
96
+
97
+ class ThreeDAssetMappingFilter(Filter): ...
98
+
99
+
100
+ class ThreeDAssetMappingAssetIdFilter(ThreeDAssetMappingFilter):
101
+ asset_ids: list[int] = Field(max_length=100)
102
+
103
+
104
+ class ThreeDAssetMappingAssetInstanceIdFilter(ThreeDAssetMappingFilter):
105
+ asset_instance_ids: list[NodeReference] = Field(max_length=100)
106
+
107
+
108
+ class ThreeDAssetMapping3DNodeFilter(ThreeDAssetMappingFilter):
109
+ node_ids: list[int] = Field(max_length=100)
110
+
111
+
112
+ class ThreeDAssetMappingTreeIndexFilter(ThreeDAssetMappingFilter):
113
+ tree_indexes: list[int] = Field(max_length=100)
@@ -0,0 +1,128 @@
1
+ from typing import ClassVar, Literal
2
+
3
+ from cognite_toolkit._cdf_tk.client.resource_classes.base import (
4
+ BaseModelObject,
5
+ RequestResource,
6
+ ResponseResource,
7
+ )
8
+
9
+ from .data_modeling import ViewReference
10
+ from .identifiers import ExternalId
11
+
12
+
13
+ class ThreeDModelIdentifier(BaseModelObject):
14
+ revision_id: int | None = None
15
+ model_id: int | None = None
16
+ name: str | None = None
17
+
18
+
19
+ class ThreeDConfiguration(BaseModelObject):
20
+ full_weight_models: list[ThreeDModelIdentifier] | None = None
21
+ light_weight_models: list[ThreeDModelIdentifier] | None = None
22
+
23
+
24
+ class ResourceFilters(BaseModelObject):
25
+ data_set_ids: list[int] | None = None
26
+ asset_subtree_external_ids: list[str] | None = None
27
+ root_asset_external_ids: list[str] | None = None
28
+ external_id_prefix: str | None = None
29
+ spaces: list[str] | None = None
30
+
31
+
32
+ class RootLocationDataFilters(BaseModelObject):
33
+ general: ResourceFilters | None = None
34
+ assets: ResourceFilters | None = None
35
+ files: ResourceFilters | None = None
36
+ timeseries: ResourceFilters | None = None
37
+
38
+
39
+ class ObservationFeatureToggles(BaseModelObject):
40
+ is_enabled: bool | None = None
41
+ is_write_back_enabled: bool | None = None
42
+ notifications_endpoint_external_id: str | None = None
43
+ attachments_endpoint_external_id: str | None = None
44
+
45
+
46
+ class RootLocationFeatureToggles(BaseModelObject):
47
+ three_d: bool | None = None
48
+ trends: bool | None = None
49
+ documents: bool | None = None
50
+ workorders: bool | None = None
51
+ notifications: bool | None = None
52
+ media: bool | None = None
53
+ template_checklist_flow: bool | None = None
54
+ workorder_checklist_flow: bool | None = None
55
+ observations: ObservationFeatureToggles | None = None
56
+
57
+
58
+ class ObservationConfigFieldProperty(BaseModelObject):
59
+ display_title: str | None = None
60
+ display_description: str | None = None
61
+ is_required: bool | None = None
62
+
63
+
64
+ class ObservationConfigDropdownPropertyOption(BaseModelObject):
65
+ id: str | None = None
66
+ value: str | None = None
67
+ label: str | None = None
68
+
69
+
70
+ class ObservationConfigDropdownProperty(ObservationConfigFieldProperty):
71
+ options: list[ObservationConfigDropdownPropertyOption] | None = None
72
+
73
+
74
+ class ObservationsConfig(BaseModelObject):
75
+ files: ObservationConfigFieldProperty | None = None
76
+ description: ObservationConfigFieldProperty | None = None
77
+ asset: ObservationConfigFieldProperty | None = None
78
+ troubleshooting: ObservationConfigFieldProperty | None = None
79
+ type: ObservationConfigDropdownProperty | None = None
80
+ priority: ObservationConfigDropdownProperty | None = None
81
+
82
+
83
+ class RootLocationConfiguration(BaseModelObject):
84
+ asset_external_id: str | None = None
85
+ external_id: str | None = None
86
+ display_name: str | None = None
87
+ three_d_configuration: ThreeDConfiguration | None = None
88
+ data_set_id: int | None = None
89
+ template_admins: list[str] | None = None # list of Group Names
90
+ checklist_admins: list[str] | None = None # list of Group Names
91
+ app_data_instance_space: str | None = None
92
+ source_data_instance_space: str | None = None
93
+ data_filters: RootLocationDataFilters | None = None
94
+ feature_toggles: RootLocationFeatureToggles | None = None
95
+ observations: ObservationsConfig | None = None
96
+
97
+
98
+ class FeatureConfiguration(BaseModelObject):
99
+ root_location_configurations: list[RootLocationConfiguration] | None = None
100
+
101
+
102
+ class APMConfig(BaseModelObject):
103
+ space: ClassVar[str] = "APM_Config"
104
+ view_ref: ClassVar[ViewReference] = ViewReference(space="APM_Config", external_id="APM_Config", version="1")
105
+ instance_type: Literal["node"] = "node"
106
+ external_id: str
107
+ name: str | None = None
108
+ app_data_space_id: str | None = None
109
+ app_data_space_version: str | None = None
110
+ customer_data_space_id: str | None = None
111
+ customer_data_space_version: str | None = None
112
+ feature_configuration: FeatureConfiguration | None = None
113
+
114
+ def as_id(self) -> ExternalId:
115
+ return ExternalId(external_id=self.external_id)
116
+
117
+
118
+ class APMConfigRequest(APMConfig, RequestResource):
119
+ existing_version: int | None = None
120
+
121
+
122
+ class APMConfigResponse(APMConfig, ResponseResource[APMConfigRequest]):
123
+ version: int
124
+ created_time: int
125
+ last_updated_time: int
126
+
127
+ def as_request_resource(self) -> APMConfigRequest:
128
+ return APMConfigRequest.model_validate(self.dump(), extra="ignore")
@@ -0,0 +1,53 @@
1
+ from datetime import datetime
2
+ from typing import ClassVar, Literal
3
+
4
+ from cognite_toolkit._cdf_tk.client.resource_classes.base import (
5
+ BaseModelObject,
6
+ RequestResource,
7
+ ResponseResource,
8
+ )
9
+
10
+ from .data_modeling import ViewReference
11
+ from .instance_api import NodeReference, TypedNodeIdentifier
12
+
13
+
14
+ class CogniteFile(BaseModelObject):
15
+ view_ref: ClassVar[ViewReference] = ViewReference(space="cdf_cdm", external_id="CogniteFile", version="v1")
16
+ instance_type: Literal["node"] = "node"
17
+ space: str
18
+ external_id: str
19
+ name: str | None = None
20
+ description: str | None = None
21
+ tags: list[str] | None = None
22
+ aliases: list[str] | None = None
23
+ source_id: str | None = None
24
+ source_context: str | None = None
25
+ source: NodeReference | None = None
26
+ source_created_time: datetime | None = None
27
+ source_updated_time: datetime | None = None
28
+ source_created_user: str | None = None
29
+ source_updated_user: str | None = None
30
+ assets: list[NodeReference] | None = None
31
+ mime_type: str | None = None
32
+ directory: str | None = None
33
+ category: NodeReference | None = None
34
+ type: NodeReference | None = None
35
+
36
+ def as_id(self) -> TypedNodeIdentifier:
37
+ return TypedNodeIdentifier(space=self.space, external_id=self.external_id)
38
+
39
+
40
+ class CogniteFileRequest(CogniteFile, RequestResource):
41
+ existing_version: int | None = None
42
+
43
+
44
+ class CogniteFileResponse(CogniteFile, ResponseResource[CogniteFileRequest]):
45
+ version: int
46
+ created_time: int
47
+ last_updated_time: int
48
+ is_uploaded: bool | None = None
49
+ uploaded_time: datetime | None = None
50
+ deleted_time: int | None = None
51
+
52
+ def as_request_resource(self) -> CogniteFileRequest:
53
+ return CogniteFileRequest.model_validate(self.dump(), extra="ignore")
@@ -46,6 +46,8 @@ from ._instance import (
46
46
  EdgeRequest,
47
47
  EdgeResponse,
48
48
  InstanceDefinition,
49
+ InstanceRequest,
50
+ InstanceResponse,
49
51
  InstanceResponseDefinition,
50
52
  InstanceSource,
51
53
  NodeRequest,
@@ -120,6 +122,8 @@ __all__ = [
120
122
  "IndexAdapter",
121
123
  "IndexDefinition",
122
124
  "InstanceDefinition",
125
+ "InstanceRequest",
126
+ "InstanceResponse",
123
127
  "InstanceResponseDefinition",
124
128
  "InstanceSource",
125
129
  "Int32Property",
@@ -1,7 +1,7 @@
1
1
  from abc import ABC
2
- from typing import Any, Generic, Literal
2
+ from typing import Annotated, Any, Generic, Literal, TypeAlias
3
3
 
4
- from pydantic import JsonValue, field_serializer, field_validator
4
+ from pydantic import Field, JsonValue, field_serializer, field_validator
5
5
 
6
6
  from cognite_toolkit._cdf_tk.client.resource_classes.base import (
7
7
  BaseModelObject,
@@ -9,8 +9,9 @@ from cognite_toolkit._cdf_tk.client.resource_classes.base import (
9
9
  ResponseResource,
10
10
  T_RequestResource,
11
11
  )
12
+ from cognite_toolkit._cdf_tk.client.resource_classes.instance_api import TypedEdgeIdentifier, TypedNodeIdentifier
12
13
 
13
- from ._references import ContainerReference, EdgeReference, NodeReference, ViewReference
14
+ from ._references import ContainerReference, NodeReference, ViewReference
14
15
 
15
16
 
16
17
  class InstanceDefinition(BaseModelObject, ABC):
@@ -87,8 +88,8 @@ class NodeRequest(InstanceRequestDefinition):
87
88
  instance_type: Literal["node"] = "node"
88
89
  type: NodeReference | None = None
89
90
 
90
- def as_id(self) -> NodeReference:
91
- return NodeReference(space=self.space, external_id=self.external_id)
91
+ def as_id(self) -> TypedNodeIdentifier:
92
+ return TypedNodeIdentifier(space=self.space, external_id=self.external_id)
92
93
 
93
94
 
94
95
  class EdgeRequest(InstanceRequestDefinition):
@@ -99,8 +100,8 @@ class EdgeRequest(InstanceRequestDefinition):
99
100
  start_node: NodeReference
100
101
  end_node: NodeReference
101
102
 
102
- def as_id(self) -> EdgeReference:
103
- return EdgeReference(space=self.space, external_id=self.external_id)
103
+ def as_id(self) -> TypedEdgeIdentifier:
104
+ return TypedEdgeIdentifier(space=self.space, external_id=self.external_id)
104
105
 
105
106
 
106
107
  class NodeResponse(InstanceResponseDefinition[NodeRequest]):
@@ -109,8 +110,8 @@ class NodeResponse(InstanceResponseDefinition[NodeRequest]):
109
110
  instance_type: Literal["node"] = "node"
110
111
  type: NodeReference | None = None
111
112
 
112
- def as_id(self) -> NodeReference:
113
- return NodeReference(space=self.space, external_id=self.external_id)
113
+ def as_id(self) -> TypedNodeIdentifier:
114
+ return TypedNodeIdentifier(space=self.space, external_id=self.external_id)
114
115
 
115
116
  def as_request_resource(self) -> NodeRequest:
116
117
  dumped = self.dump()
@@ -130,8 +131,8 @@ class EdgeResponse(InstanceResponseDefinition[EdgeRequest]):
130
131
  start_node: NodeReference
131
132
  end_node: NodeReference
132
133
 
133
- def as_id(self) -> EdgeReference:
134
- return EdgeReference(space=self.space, external_id=self.external_id)
134
+ def as_id(self) -> TypedEdgeIdentifier:
135
+ return TypedEdgeIdentifier(space=self.space, external_id=self.external_id)
135
136
 
136
137
  def as_request_resource(self) -> EdgeRequest:
137
138
  dumped = self.dump()
@@ -141,3 +142,13 @@ class EdgeResponse(InstanceResponseDefinition[EdgeRequest]):
141
142
  ]
142
143
  dumped["existingVersion"] = dumped.pop("version", None)
143
144
  return EdgeRequest.model_validate(dumped, extra="ignore")
145
+
146
+
147
+ InstanceRequest: TypeAlias = Annotated[
148
+ NodeRequest | EdgeRequest,
149
+ Field(discriminator="instance_type"),
150
+ ]
151
+ InstanceResponse: TypeAlias = Annotated[
152
+ NodeResponse | EdgeResponse,
153
+ Field(discriminator="instance_type"),
154
+ ]
@@ -50,3 +50,10 @@ class WorkflowVersionId(Identifier):
50
50
 
51
51
  def __str__(self) -> str:
52
52
  return f"workflowExternalId='{self.workflow_external_id}', version='{self.version}'"
53
+
54
+
55
+ class DataSetId(Identifier):
56
+ data_set_id: int
57
+
58
+ def __str__(self) -> str:
59
+ return f"dataSetId={self.data_set_id}"
@@ -1,5 +1,7 @@
1
1
  from typing import Literal
2
2
 
3
+ from pydantic import Field
4
+
3
5
  from cognite_toolkit._cdf_tk.client.resource_classes.base import BaseModelObject, RequestResource, ResponseResource
4
6
 
5
7
  from .data_modeling import DataModelReference
@@ -61,8 +63,13 @@ class LocationFilter(BaseModelObject):
61
63
  class LocationFilterRequest(LocationFilter, RequestResource):
62
64
  """Request resource for creating/updating location filters."""
63
65
 
64
- def as_id(self) -> ExternalId:
65
- return ExternalId(external_id=self.external_id)
66
+ # This is not part of the request payload, but we need it to identify existing resources for updates.
67
+ id: int | None = Field(default=None, exclude=True)
68
+
69
+ def as_id(self) -> InternalId:
70
+ if self.id is None:
71
+ raise ValueError("Cannot get ID for LocationFilterRequest without 'id' set.")
72
+ return InternalId(id=self.id)
66
73
 
67
74
 
68
75
  class LocationFilterResponse(LocationFilter, ResponseResource[LocationFilterRequest]):
@@ -0,0 +1,38 @@
1
+ from typing import ClassVar, Literal
2
+
3
+ from cognite_toolkit._cdf_tk.client.resource_classes.base import (
4
+ BaseModelObject,
5
+ RequestResource,
6
+ ResponseResource,
7
+ )
8
+
9
+ from .data_modeling import ViewReference
10
+ from .identifiers import ExternalId
11
+
12
+
13
+ class ResourceViewMapping(BaseModelObject):
14
+ space: ClassVar[str] = "cognite_migration"
15
+ view_ref: ClassVar[ViewReference] = ViewReference(
16
+ space="cognite_migration", external_id="ResourceViewMapping", version="v1"
17
+ )
18
+ instance_type: Literal["node"] = "node"
19
+ external_id: str
20
+ resource_type: str
21
+ view_id: ViewReference
22
+ property_mapping: dict[str, str]
23
+
24
+ def as_id(self) -> ExternalId:
25
+ return ExternalId(external_id=self.external_id)
26
+
27
+
28
+ class ResourceViewMappingRequest(ResourceViewMapping, RequestResource):
29
+ existing_version: int | None = None
30
+
31
+
32
+ class ResourceViewMappingResponse(ResourceViewMapping, ResponseResource[ResourceViewMappingRequest]):
33
+ version: int
34
+ created_time: int
35
+ last_updated_time: int
36
+
37
+ def as_request_resource(self) -> ResourceViewMappingRequest:
38
+ return ResourceViewMappingRequest.model_validate(self.dump(), extra="ignore")
@@ -1,4 +1,4 @@
1
- from typing import ClassVar
1
+ from typing import ClassVar, Literal
2
2
 
3
3
  from pydantic import JsonValue
4
4
 
@@ -49,6 +49,11 @@ class RobotMapRequest(RobotMap, RequestUpdateable):
49
49
  {"description", "data", "frame_external_id", "location_external_id", "scale"}
50
50
  )
51
51
 
52
+ def as_update(self, mode: Literal["patch", "replace"]) -> dict[str, JsonValue]:
53
+ update = super().as_update(mode)
54
+ update["update"].pop("mapType", None)
55
+ return update
56
+
52
57
 
53
58
  class RobotMapResponse(RobotMap, ResponseResource[RobotMapRequest]):
54
59
  """Response resource for a RobotMap."""
@@ -1,11 +1,11 @@
1
- from typing import ClassVar
1
+ from typing import Any, ClassVar, Literal
2
2
 
3
3
  from cognite_toolkit._cdf_tk.client.resource_classes.base import (
4
4
  BaseModelObject,
5
5
  RequestUpdateable,
6
6
  ResponseResource,
7
7
  )
8
- from cognite_toolkit._cdf_tk.client.resource_classes.identifiers import NameId
8
+ from cognite_toolkit._cdf_tk.client.resource_classes.identifiers import DataSetId
9
9
 
10
10
  from ._common import RobotType
11
11
 
@@ -32,15 +32,20 @@ class Robot(BaseModelObject):
32
32
  metadata: dict[str, str] | None = None
33
33
  location_external_id: str | None = None
34
34
 
35
- def as_id(self) -> NameId:
36
- return NameId(name=self.name)
35
+ def as_id(self) -> DataSetId:
36
+ return DataSetId(data_set_id=self.data_set_id)
37
37
 
38
38
 
39
39
  class RobotRequest(Robot, RequestUpdateable):
40
40
  """Request resource for creating or updating a Robot."""
41
41
 
42
42
  container_fields: ClassVar[frozenset[str]] = frozenset({"metadata"})
43
- non_nullable_fields: ClassVar[frozenset[str]] = frozenset({"location_external_id"})
43
+ non_nullable_fields: ClassVar[frozenset[str]] = frozenset({"location_external_id", "description"})
44
+
45
+ def as_update(self, mode: Literal["patch", "replace"]) -> dict[str, Any]:
46
+ update = super().as_update(mode)
47
+ update["update"].pop("capabilities", None)
48
+ return update
44
49
 
45
50
 
46
51
  class RobotResponse(Robot, ResponseResource[RobotRequest]):
@@ -1,12 +1,8 @@
1
1
  from typing import Literal
2
2
 
3
3
  from cognite_toolkit._cdf_tk.constants import StreamTemplateName
4
- from cognite_toolkit._cdf_tk.protocols import (
5
- ResourceRequestListProtocol,
6
- ResourceResponseListProtocol,
7
- )
8
4
 
9
- from .base import BaseModelObject, BaseResourceList, RequestResource, ResponseResource
5
+ from .base import BaseModelObject, RequestResource, ResponseResource
10
6
  from .identifiers import ExternalId
11
7
 
12
8
 
@@ -23,12 +19,6 @@ class StreamRequest(Stream, RequestResource):
23
19
  return ExternalId(external_id=self.external_id)
24
20
 
25
21
 
26
- class StreamRequestList(BaseResourceList[StreamRequest], ResourceRequestListProtocol):
27
- """List of Stream request resources."""
28
-
29
- _RESOURCE = StreamRequest
30
-
31
-
32
22
  class LifecycleObject(BaseModelObject):
33
23
  """Lifecycle object."""
34
24
 
@@ -81,12 +71,3 @@ class StreamResponse(Stream, ResponseResource[StreamRequest]):
81
71
  "settings": {"template": {"name": self.created_from_template}},
82
72
  }
83
73
  )
84
-
85
-
86
- class StreamResponseList(BaseResourceList[StreamResponse], ResourceResponseListProtocol):
87
- """List of Stream response resources."""
88
-
89
- _RESOURCE = StreamResponse
90
-
91
- def as_write(self) -> StreamRequestList:
92
- return StreamRequestList([item.as_write() for item in self.data])