cognite-toolkit 0.7.41__py3-none-any.whl → 0.7.43__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 (40) hide show
  1. cognite_toolkit/_cdf_tk/client/_toolkit_client.py +1 -1
  2. cognite_toolkit/_cdf_tk/client/api/events.py +20 -2
  3. cognite_toolkit/_cdf_tk/client/api/timeseries.py +20 -2
  4. cognite_toolkit/_cdf_tk/client/data_classes/agent.py +6 -9
  5. cognite_toolkit/_cdf_tk/client/data_classes/asset.py +7 -14
  6. cognite_toolkit/_cdf_tk/client/data_classes/base.py +2 -2
  7. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/__init__.py +148 -0
  8. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_constraints.py +37 -0
  9. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_container.py +50 -0
  10. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_data_model.py +73 -0
  11. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_data_types.py +116 -0
  12. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_indexes.py +26 -0
  13. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_references.py +78 -0
  14. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_space.py +26 -0
  15. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_view.py +143 -0
  16. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_view_property.py +152 -0
  17. cognite_toolkit/_cdf_tk/client/data_classes/event.py +12 -15
  18. cognite_toolkit/_cdf_tk/client/data_classes/filemetadata.py +8 -18
  19. cognite_toolkit/_cdf_tk/client/data_classes/simulator_model.py +50 -0
  20. cognite_toolkit/_cdf_tk/client/data_classes/timeseries.py +15 -18
  21. cognite_toolkit/_cdf_tk/client/testing.py +1 -1
  22. cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +7 -5
  23. cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +4 -4
  24. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/auth.py +5 -1
  25. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +40 -39
  26. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +2 -2
  27. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +48 -47
  28. cognite_toolkit/_cdf_tk/resource_classes/__init__.py +2 -0
  29. cognite_toolkit/_cdf_tk/resource_classes/simulator_model.py +17 -0
  30. cognite_toolkit/_cdf_tk/resource_classes/workflow_version.py +13 -4
  31. cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +54 -46
  32. cognite_toolkit/_cdf_tk/utils/useful_types2.py +5 -3
  33. cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
  34. cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
  35. cognite_toolkit/_resources/cdf.toml +1 -1
  36. cognite_toolkit/_version.py +1 -1
  37. {cognite_toolkit-0.7.41.dist-info → cognite_toolkit-0.7.43.dist-info}/METADATA +1 -1
  38. {cognite_toolkit-0.7.41.dist-info → cognite_toolkit-0.7.43.dist-info}/RECORD +40 -28
  39. {cognite_toolkit-0.7.41.dist-info → cognite_toolkit-0.7.43.dist-info}/WHEEL +0 -0
  40. {cognite_toolkit-0.7.41.dist-info → cognite_toolkit-0.7.43.dist-info}/entry_points.txt +0 -0
@@ -449,15 +449,15 @@ class ThreeDMapper(DataMapper[ThreeDSelector, ThreeDModelResponse, ThreeDMigrati
449
449
  return None, issue
450
450
 
451
451
  mapped_request = ThreeDMigrationRequest(
452
- modelId=item.id,
452
+ model_id=item.id,
453
453
  type=model_type,
454
454
  space=instance_space,
455
455
  revision=ThreeDRevisionMigrationRequest(
456
456
  space=instance_space,
457
457
  type=model_type,
458
- revisionId=last_revision_id,
458
+ revision_id=last_revision_id,
459
459
  model=Model(
460
- instanceId=InstanceIdentifier(
460
+ instance_id=InstanceIdentifier(
461
461
  space=instance_space,
462
462
  external_id=f"cog_3d_model_{item.id!s}",
463
463
  )
@@ -508,7 +508,7 @@ class ThreeDAssetMapper(DataMapper[ThreeDSelector, AssetMappingResponse, AssetMa
508
508
  if asset_node_id is None:
509
509
  issue.error_message.append(f"Missing asset instance for asset ID {item.asset_id!r}")
510
510
  return None, issue
511
- asset_instance_id = NodeReference(space=asset_node_id.space, externalId=asset_node_id.external_id)
511
+ asset_instance_id = NodeReference(space=asset_node_id.space, external_id=asset_node_id.external_id)
512
512
 
513
513
  if asset_instance_id is None:
514
514
  issue.error_message.append("Neither assetInstanceId nor assetId provided for mapping.")
@@ -41,6 +41,7 @@ from rich.console import Console
41
41
  from rich.markup import escape
42
42
 
43
43
  from cognite_toolkit._cdf_tk.client import ToolkitClient
44
+ from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
44
45
  from cognite_toolkit._cdf_tk.client.data_classes.legacy.raw import RawDatabase, RawTable
45
46
  from cognite_toolkit._cdf_tk.cruds._base_cruds import ResourceCRUD
46
47
  from cognite_toolkit._cdf_tk.exceptions import ToolkitWrongResourceError
@@ -190,7 +191,10 @@ class GroupCRUD(ResourceCRUD[str, GroupWrite, Group]):
190
191
  loader = LocationFilterCRUD
191
192
  if loader is not None and isinstance(ids, dict) and "ids" in ids:
192
193
  for id_ in ids["ids"]:
193
- yield loader, id_
194
+ if loader is TimeSeriesCRUD:
195
+ yield TimeSeriesCRUD, ExternalId(external_id=id_)
196
+ else:
197
+ yield loader, id_
194
198
 
195
199
  def _substitute_scope_ids(self, group: dict[str, Any], is_dry_run: bool, reverse: bool = False) -> dict[str, Any]:
196
200
  replace_method_by_acl = self._create_replace_method_by_acl_and_scope()
@@ -5,15 +5,12 @@ from pathlib import Path
5
5
  from typing import Any, final
6
6
 
7
7
  import pandas as pd
8
+ from cognite.client.data_classes import Sequence as CDFSequence
8
9
  from cognite.client.data_classes import (
9
- Event,
10
- EventList,
11
- EventWrite,
12
10
  SequenceList,
13
11
  SequenceWrite,
14
12
  capabilities,
15
13
  )
16
- from cognite.client.data_classes import Sequence as CDFSequence
17
14
  from cognite.client.data_classes.capabilities import Capability
18
15
  from cognite.client.exceptions import CogniteAPIError, CogniteNotFoundError
19
16
  from cognite.client.utils.useful_types import SequenceNotStr
@@ -25,6 +22,7 @@ from cognite_toolkit._cdf_tk.client.data_classes.asset import (
25
22
  AssetRequest,
26
23
  AssetResponse,
27
24
  )
25
+ from cognite_toolkit._cdf_tk.client.data_classes.event import EventRequest, EventResponse
28
26
  from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId, InternalOrExternalId
29
27
  from cognite_toolkit._cdf_tk.client.data_classes.legacy.sequences import (
30
28
  ToolkitSequenceRows,
@@ -496,10 +494,10 @@ class SequenceRowCRUD(ResourceCRUD[str, ToolkitSequenceRowsWrite, ToolkitSequenc
496
494
 
497
495
 
498
496
  @final
499
- class EventCRUD(ResourceCRUD[str, EventWrite, Event]):
497
+ class EventCRUD(ResourceCRUD[ExternalId, EventRequest, EventResponse]):
500
498
  folder_name = "classic"
501
- resource_cls = Event
502
- resource_write_cls = EventWrite
499
+ resource_cls = EventResponse
500
+ resource_write_cls = EventRequest
503
501
  yaml_cls = EventYAML
504
502
  kind = "Event"
505
503
  dependencies = frozenset({DataSetsCRUD, AssetCRUD})
@@ -510,15 +508,15 @@ class EventCRUD(ResourceCRUD[str, EventWrite, Event]):
510
508
  return "events"
511
509
 
512
510
  @classmethod
513
- def get_id(cls, item: Event | EventWrite | dict) -> str:
511
+ def get_id(cls, item: EventRequest | EventResponse | dict) -> ExternalId:
514
512
  if isinstance(item, dict):
515
- return item["externalId"]
513
+ return ExternalId(external_id=item["externalId"])
516
514
  if not item.external_id:
517
515
  raise KeyError("Event must have external_id")
518
- return item.external_id
516
+ return ExternalId(external_id=item.external_id)
519
517
 
520
518
  @classmethod
521
- def get_internal_id(cls, item: Event | dict) -> int:
519
+ def get_internal_id(cls, item: EventResponse | dict) -> int:
522
520
  if isinstance(item, dict):
523
521
  return item["id"]
524
522
  if not item.id:
@@ -526,12 +524,12 @@ class EventCRUD(ResourceCRUD[str, EventWrite, Event]):
526
524
  return item.id
527
525
 
528
526
  @classmethod
529
- def dump_id(cls, id: str) -> dict[str, Any]:
530
- return {"externalId": id}
527
+ def dump_id(cls, id: ExternalId) -> dict[str, Any]:
528
+ return id.dump()
531
529
 
532
530
  @classmethod
533
531
  def get_required_capability(
534
- cls, items: collections.abc.Sequence[EventWrite] | None, read_only: bool
532
+ cls, items: collections.abc.Sequence[EventRequest] | None, read_only: bool
535
533
  ) -> Capability | list[Capability]:
536
534
  if not items and items is not None:
537
535
  return []
@@ -551,35 +549,38 @@ class EventCRUD(ResourceCRUD[str, EventWrite, Event]):
551
549
 
552
550
  return capabilities.EventsAcl(actions, scope)
553
551
 
554
- def create(self, items: Sequence[EventWrite]) -> EventList:
555
- return self.client.events.create(items)
552
+ def create(self, items: collections.abc.Sequence[EventRequest]) -> list[EventResponse]:
553
+ return self.client.tool.events.create(items)
556
554
 
557
- def retrieve(self, ids: SequenceNotStr[str]) -> EventList:
558
- return self.client.events.retrieve_multiple(external_ids=ids, ignore_unknown_ids=True)
555
+ def retrieve(self, ids: SequenceNotStr[ExternalId]) -> list[EventResponse]:
556
+ return self.client.tool.events.retrieve(list(ids), ignore_unknown_ids=True)
559
557
 
560
- def update(self, items: Sequence[EventWrite]) -> EventList:
561
- return self.client.events.update(items, mode="replace")
558
+ def update(self, items: collections.abc.Sequence[EventRequest]) -> list[EventResponse]:
559
+ return self.client.tool.events.update(items, mode="replace")
562
560
 
563
- def delete(self, ids: SequenceNotStr[str | int]) -> int:
564
- internal_ids, external_ids = self._split_ids(ids)
565
- try:
566
- self.client.events.delete(id=internal_ids, external_id=external_ids)
567
- except (CogniteAPIError, CogniteNotFoundError) as e:
568
- non_existing = set(e.failed or [])
569
- if existing := [id_ for id_ in ids if id_ not in non_existing]:
570
- internal_ids, external_ids = self._split_ids(existing)
571
- self.client.events.delete(id=internal_ids, external_id=external_ids)
572
- return len(existing)
573
- else:
574
- return len(ids)
561
+ def delete(self, ids: SequenceNotStr[InternalOrExternalId]) -> int:
562
+ if not ids:
563
+ return 0
564
+ self.client.tool.events.delete(list(ids), ignore_unknown_ids=True)
565
+ return len(ids)
575
566
 
576
567
  def _iterate(
577
568
  self,
578
569
  data_set_external_id: str | None = None,
579
570
  space: str | None = None,
580
571
  parent_ids: list[Hashable] | None = None,
581
- ) -> Iterable[Event]:
582
- return iter(self.client.events(data_set_external_ids=[data_set_external_id] if data_set_external_id else None))
572
+ ) -> Iterable[EventResponse]:
573
+ cursor: str | None = None
574
+ while True:
575
+ page = self.client.tool.events.iterate(
576
+ data_set_external_ids=[data_set_external_id] if data_set_external_id else None,
577
+ limit=1000,
578
+ cursor=cursor,
579
+ )
580
+ yield from page.items
581
+ if not page.next_cursor or not page.items:
582
+ break
583
+ cursor = page.next_cursor
583
584
 
584
585
  @classmethod
585
586
  def get_dependent_items(cls, item: dict) -> Iterable[tuple[type[ResourceCRUD], Hashable]]:
@@ -594,15 +595,15 @@ class EventCRUD(ResourceCRUD[str, EventWrite, Event]):
594
595
  if isinstance(asset_id, str):
595
596
  yield AssetCRUD, ExternalId(external_id=asset_id)
596
597
 
597
- def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> EventWrite:
598
- if ds_external_id := resource.get("dataSetExternalId", None):
598
+ def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> EventRequest:
599
+ if ds_external_id := resource.pop("dataSetExternalId", None):
599
600
  resource["dataSetId"] = self.client.lookup.data_sets.id(ds_external_id, is_dry_run)
600
601
  if asset_external_ids := resource.pop("assetExternalIds", []):
601
602
  resource["assetIds"] = self.client.lookup.assets.id(asset_external_ids, is_dry_run)
602
- return EventWrite._load(resource)
603
+ return EventRequest.model_validate(resource)
603
604
 
604
- def dump_resource(self, resource: Event, local: dict[str, Any] | None = None) -> dict[str, Any]:
605
- dumped = resource.as_write().dump()
605
+ def dump_resource(self, resource: EventResponse, local: dict[str, Any] | None = None) -> dict[str, Any]:
606
+ dumped = resource.as_request_resource().dump()
606
607
  local = local or {}
607
608
  if data_set_id := dumped.pop("dataSetId", None):
608
609
  dumped["dataSetExternalId"] = self.client.lookup.data_sets.external_id(data_set_id)
@@ -128,11 +128,11 @@ class RelationshipCRUD(ResourceCRUD[str, RelationshipWrite, Relationship]):
128
128
  elif type_value == "sequence":
129
129
  yield SequenceCRUD, id_value
130
130
  elif type_value == "timeseries":
131
- yield TimeSeriesCRUD, id_value
131
+ yield TimeSeriesCRUD, ExternalId(external_id=id_value)
132
132
  elif type_value == "file":
133
133
  yield FileMetadataCRUD, id_value
134
134
  elif type_value == "event":
135
- yield EventCRUD, id_value
135
+ yield EventCRUD, ExternalId(external_id=id_value)
136
136
 
137
137
  def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> RelationshipWrite:
138
138
  if ds_external_id := resource.pop("dataSetExternalId", None):
@@ -2,16 +2,13 @@ import json
2
2
  from collections.abc import Hashable, Iterable, Sequence
3
3
  from itertools import zip_longest
4
4
  from pathlib import Path
5
- from typing import Any, Literal, cast, final
5
+ from typing import Any, Literal, final
6
6
 
7
7
  from cognite.client.data_classes import (
8
8
  DatapointSubscription,
9
9
  DatapointSubscriptionList,
10
10
  DataPointSubscriptionUpdate,
11
11
  DataPointSubscriptionWrite,
12
- TimeSeries,
13
- TimeSeriesList,
14
- TimeSeriesWrite,
15
12
  )
16
13
  from cognite.client.data_classes.capabilities import (
17
14
  Capability,
@@ -23,7 +20,8 @@ from cognite.client.data_classes.datapoints_subscriptions import TimeSeriesIDLis
23
20
  from cognite.client.exceptions import CogniteAPIError, CogniteNotFoundError
24
21
  from cognite.client.utils.useful_types import SequenceNotStr
25
22
 
26
- from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId
23
+ from cognite_toolkit._cdf_tk.client.data_classes.identifiers import ExternalId, InternalOrExternalId
24
+ from cognite_toolkit._cdf_tk.client.data_classes.timeseries import TimeSeriesRequest, TimeSeriesResponse
27
25
  from cognite_toolkit._cdf_tk.constants import MAX_TIMESTAMP_MS, MIN_TIMESTAMP_MS
28
26
  from cognite_toolkit._cdf_tk.cruds._base_cruds import ResourceContainerCRUD, ResourceCRUD
29
27
  from cognite_toolkit._cdf_tk.exceptions import (
@@ -42,11 +40,11 @@ from .data_organization import DataSetsCRUD
42
40
 
43
41
 
44
42
  @final
45
- class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
43
+ class TimeSeriesCRUD(ResourceContainerCRUD[ExternalId, TimeSeriesRequest, TimeSeriesResponse]):
46
44
  item_name = "datapoints"
47
45
  folder_name = "timeseries"
48
- resource_cls = TimeSeries
49
- resource_write_cls = TimeSeriesWrite
46
+ resource_cls = TimeSeriesResponse
47
+ resource_write_cls = TimeSeriesRequest
50
48
  yaml_cls = TimeSeriesYAML
51
49
  kind = "TimeSeries"
52
50
  dependencies = frozenset({DataSetsCRUD, GroupAllScopedCRUD, AssetCRUD})
@@ -58,7 +56,7 @@ class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
58
56
 
59
57
  @classmethod
60
58
  def get_required_capability(
61
- cls, items: Sequence[TimeSeriesWrite] | None, read_only: bool
59
+ cls, items: Sequence[TimeSeriesRequest] | None, read_only: bool
62
60
  ) -> Capability | list[Capability]:
63
61
  if not items and items is not None:
64
62
  return []
@@ -73,22 +71,22 @@ class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
73
71
  return TimeSeriesAcl(actions, scope)
74
72
 
75
73
  @classmethod
76
- def get_id(cls, item: TimeSeries | TimeSeriesWrite | dict) -> str:
74
+ def get_id(cls, item: TimeSeriesRequest | TimeSeriesResponse | dict) -> ExternalId:
77
75
  if isinstance(item, dict):
78
- return item["externalId"]
76
+ return ExternalId(external_id=item["externalId"])
79
77
  if item.external_id is None:
80
78
  raise ToolkitRequiredValueError("TimeSeries must have external_id set.")
81
- return item.external_id
79
+ return ExternalId(external_id=item.external_id)
82
80
 
83
81
  @classmethod
84
- def get_internal_id(cls, item: TimeSeries | dict) -> int:
82
+ def get_internal_id(cls, item: TimeSeriesResponse | dict) -> int:
85
83
  if isinstance(item, dict):
86
84
  return item["id"]
87
85
  return item.id
88
86
 
89
87
  @classmethod
90
- def dump_id(cls, id: str) -> dict[str, Any]:
91
- return {"externalId": id}
88
+ def dump_id(cls, id: ExternalId) -> dict[str, Any]:
89
+ return id.dump()
92
90
 
93
91
  @classmethod
94
92
  def get_dependent_items(cls, item: dict) -> Iterable[tuple[type[ResourceCRUD], Hashable]]:
@@ -100,7 +98,7 @@ class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
100
98
  if "assetExternalId" in item:
101
99
  yield AssetCRUD, ExternalId(external_id=item["assetExternalId"])
102
100
 
103
- def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> TimeSeriesWrite:
101
+ def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> TimeSeriesRequest:
104
102
  if ds_external_id := resource.pop("dataSetExternalId", None):
105
103
  resource["dataSetId"] = self.client.lookup.data_sets.id(ds_external_id, is_dry_run)
106
104
  if security_categories_names := resource.pop("securityCategoryNames", []):
@@ -109,10 +107,10 @@ class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
109
107
  )
110
108
  if asset_external_id := resource.pop("assetExternalId", None):
111
109
  resource["assetId"] = self.client.lookup.assets.id(asset_external_id, is_dry_run)
112
- return TimeSeriesWrite._load(resource)
110
+ return TimeSeriesRequest.model_validate(resource)
113
111
 
114
- def dump_resource(self, resource: TimeSeries, local: dict[str, Any] | None = None) -> dict[str, Any]:
115
- dumped = resource.as_write().dump()
112
+ def dump_resource(self, resource: TimeSeriesResponse, local: dict[str, Any] | None = None) -> dict[str, Any]:
113
+ dumped = resource.as_request_resource().dump()
116
114
  if data_set_id := dumped.pop("dataSetId", None):
117
115
  dumped["dataSetExternalId"] = self.client.lookup.data_sets.external_id(data_set_id)
118
116
  if security_categories := dumped.pop("securityCategories", []):
@@ -121,53 +119,56 @@ class TimeSeriesCRUD(ResourceContainerCRUD[str, TimeSeriesWrite, TimeSeries]):
121
119
  dumped["assetExternalId"] = self.client.lookup.assets.external_id(asset_id)
122
120
  return dumped
123
121
 
124
- def create(self, items: Sequence[TimeSeriesWrite]) -> TimeSeriesList:
125
- return self.client.time_series.create(items)
122
+ def create(self, items: Sequence[TimeSeriesRequest]) -> list[TimeSeriesResponse]:
123
+ return self.client.tool.timeseries.create(items)
126
124
 
127
- def retrieve(self, ids: SequenceNotStr[str | int]) -> TimeSeriesList:
128
- internal_ids, external_ids = self._split_ids(ids)
129
- return self.client.time_series.retrieve_multiple(
130
- ids=internal_ids, external_ids=external_ids, ignore_unknown_ids=True
131
- )
125
+ def retrieve(self, ids: SequenceNotStr[ExternalId]) -> list[TimeSeriesResponse]:
126
+ return self.client.tool.timeseries.retrieve(list(ids), ignore_unknown_ids=True)
132
127
 
133
- def update(self, items: Sequence[TimeSeriesWrite]) -> TimeSeriesList:
134
- return self.client.time_series.update(items, mode="replace")
128
+ def update(self, items: Sequence[TimeSeriesRequest]) -> list[TimeSeriesResponse]:
129
+ return self.client.tool.timeseries.update(items, mode="replace")
135
130
 
136
- def delete(self, ids: SequenceNotStr[str | int]) -> int:
137
- existing = self.retrieve(ids)
138
- if existing:
139
- self.client.time_series.delete(id=existing.as_ids(), ignore_unknown_ids=True)
140
- return len(existing)
131
+ def delete(self, ids: SequenceNotStr[InternalOrExternalId]) -> int:
132
+ if not ids:
133
+ return 0
134
+ self.client.tool.timeseries.delete(list(ids), ignore_unknown_ids=True)
135
+ return len(ids)
141
136
 
142
137
  def _iterate(
143
138
  self,
144
139
  data_set_external_id: str | None = None,
145
140
  space: str | None = None,
146
141
  parent_ids: list[Hashable] | None = None,
147
- ) -> Iterable[TimeSeries]:
148
- return iter(
149
- self.client.time_series(data_set_external_ids=[data_set_external_id] if data_set_external_id else None)
150
- )
142
+ ) -> Iterable[TimeSeriesResponse]:
143
+ cursor: str | None = None
144
+ while True:
145
+ page = self.client.tool.timeseries.iterate(
146
+ data_set_external_ids=[data_set_external_id] if data_set_external_id else None,
147
+ limit=1000,
148
+ cursor=cursor,
149
+ )
150
+ yield from page.items
151
+ if not page.next_cursor or not page.items:
152
+ break
153
+ cursor = page.next_cursor
151
154
 
152
- def count(self, ids: str | dict[str, Any] | SequenceNotStr[str | dict[str, Any]] | None) -> int:
155
+ def count(self, ids: SequenceNotStr[ExternalId]) -> int:
153
156
  datapoints = self.client.time_series.data.retrieve(
154
- external_id=ids, # type: ignore[arg-type]
157
+ external_id=[id.external_id for id in ids],
155
158
  start=MIN_TIMESTAMP_MS,
156
159
  end=MAX_TIMESTAMP_MS + 1,
157
160
  aggregates="count",
158
161
  granularity="1000d",
159
162
  ignore_unknown_ids=True,
160
163
  )
161
- return sum(sum(data.count or []) for data in datapoints) # type: ignore[union-attr, misc, arg-type]
164
+ return sum(sum(data.count or []) for data in datapoints)
162
165
 
163
- def drop_data(self, ids: SequenceNotStr[str] | None) -> int:
166
+ def drop_data(self, ids: SequenceNotStr[ExternalId]) -> int:
164
167
  count = self.count(ids)
165
- existing = self.client.time_series.retrieve_multiple(
166
- external_ids=cast(SequenceNotStr[str], ids), ignore_unknown_ids=True
167
- ).as_external_ids()
168
- for external_id in existing:
168
+ existing = self.client.tool.timeseries.retrieve(list(ids), ignore_unknown_ids=True)
169
+ for ts in existing:
169
170
  self.client.time_series.data.delete_range(
170
- external_id=external_id, start=MIN_TIMESTAMP_MS, end=MAX_TIMESTAMP_MS + 1
171
+ external_id=ts.external_id, start=MIN_TIMESTAMP_MS, end=MAX_TIMESTAMP_MS + 1
171
172
  )
172
173
  return count
173
174
 
@@ -220,7 +221,7 @@ class DatapointSubscriptionCRUD(
220
221
  if "dataSetExternalId" in item:
221
222
  yield DataSetsCRUD, item["dataSetExternalId"]
222
223
  for timeseries_id in item.get("timeSeriesIds", []):
223
- yield TimeSeriesCRUD, timeseries_id
224
+ yield TimeSeriesCRUD, ExternalId(external_id=timeseries_id)
224
225
 
225
226
  @classmethod
226
227
  def get_required_capability(
@@ -40,6 +40,7 @@ from .robotics import RobotCapabilityYAML, RobotDataPostProcessingYAML, RobotFra
40
40
  from .search_config import SearchConfigYAML
41
41
  from .securitycategories import SecurityCategoriesYAML
42
42
  from .sequence import SequenceRowYAML, SequenceYAML
43
+ from .simulator_model import SimulatorModelYAML
43
44
  from .space import SpaceYAML
44
45
  from .streamlit_ import StreamlitYAML
45
46
  from .streams import StreamYAML
@@ -94,6 +95,7 @@ __all__ = [
94
95
  "SecurityCategoriesYAML",
95
96
  "SequenceRowYAML",
96
97
  "SequenceYAML",
98
+ "SimulatorModelYAML",
97
99
  "SpaceYAML",
98
100
  "StreamYAML",
99
101
  "StreamlitYAML",
@@ -0,0 +1,17 @@
1
+ from pydantic import Field
2
+
3
+ from .base import ToolkitResource
4
+
5
+
6
+ class SimulatorModelYAML(ToolkitResource):
7
+ """Simulator model YAML resource class.
8
+
9
+ Based on: https://api-docs.cognite.com/20230101/tag/Simulator-Models/operation/create_simulator_model_simulators_models_post
10
+ """
11
+
12
+ external_id: str = Field(description="External ID of the simulator model.", min_length=1, max_length=255)
13
+ simulator_external_id: str = Field(description="External id of the simulator.", min_length=1, max_length=50)
14
+ name: str = Field(description="The name of the simulator model.", min_length=1, max_length=50)
15
+ description: str | None = Field(None, description="Description of the simulator model.", max_length=500)
16
+ data_set_external_id: str = Field(description="The external ID of the dataset this simulator model belongs to.")
17
+ type: str = Field(description="The type of the simulator model.", min_length=1, max_length=50)
@@ -93,10 +93,19 @@ class DynamicTaskParameters(BaseModelResource):
93
93
  dynamic: DynamicRef = Field(description="Reference to another task to use as the definition for this task.")
94
94
 
95
95
 
96
- class SubworkflowRef(BaseModelResource):
97
- tasks: "WorkflowVersionId | list[Task]" = Field(
98
- description="Reference to the subworkflow to execute. This can be either a reference to an existing workflow version or an inline definition of tasks."
99
- )
96
+ class SubworkflowInlineTasks(BaseModelResource):
97
+ """Inline definition of tasks for a subworkflow."""
98
+
99
+ tasks: "list[Task]" = Field(description="Inline definition of tasks for the subworkflow.")
100
+
101
+
102
+ # SubworkflowRef can be either a reference to an existing workflow version OR an inline definition of tasks
103
+ SubworkflowRef = Annotated[
104
+ WorkflowVersionId | SubworkflowInlineTasks,
105
+ Field(
106
+ description="Reference to the subworkflow to execute. This can be either a reference to an existing workflow version (with workflowExternalId and version) or an inline definition of tasks."
107
+ ),
108
+ ]
100
109
 
101
110
 
102
111
  class SubworkflowTaskParameters(BaseModelResource):