cognite-toolkit 0.6.97__py3-none-any.whl → 0.7.39__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. cognite_toolkit/_cdf.py +21 -23
  2. cognite_toolkit/_cdf_tk/apps/__init__.py +4 -0
  3. cognite_toolkit/_cdf_tk/apps/_core_app.py +19 -5
  4. cognite_toolkit/_cdf_tk/apps/_data_app.py +1 -1
  5. cognite_toolkit/_cdf_tk/apps/_dev_app.py +86 -0
  6. cognite_toolkit/_cdf_tk/apps/_download_app.py +693 -25
  7. cognite_toolkit/_cdf_tk/apps/_dump_app.py +44 -102
  8. cognite_toolkit/_cdf_tk/apps/_import_app.py +41 -0
  9. cognite_toolkit/_cdf_tk/apps/_landing_app.py +18 -4
  10. cognite_toolkit/_cdf_tk/apps/_migrate_app.py +424 -9
  11. cognite_toolkit/_cdf_tk/apps/_modules_app.py +0 -3
  12. cognite_toolkit/_cdf_tk/apps/_purge.py +15 -43
  13. cognite_toolkit/_cdf_tk/apps/_run.py +11 -0
  14. cognite_toolkit/_cdf_tk/apps/_upload_app.py +45 -6
  15. cognite_toolkit/_cdf_tk/builders/__init__.py +2 -2
  16. cognite_toolkit/_cdf_tk/builders/_base.py +28 -42
  17. cognite_toolkit/_cdf_tk/builders/_raw.py +1 -1
  18. cognite_toolkit/_cdf_tk/cdf_toml.py +20 -1
  19. cognite_toolkit/_cdf_tk/client/_toolkit_client.py +32 -12
  20. cognite_toolkit/_cdf_tk/client/api/infield.py +114 -17
  21. cognite_toolkit/_cdf_tk/client/api/{canvas.py → legacy/canvas.py} +15 -7
  22. cognite_toolkit/_cdf_tk/client/api/{charts.py → legacy/charts.py} +1 -1
  23. cognite_toolkit/_cdf_tk/client/api/{extended_data_modeling.py → legacy/extended_data_modeling.py} +1 -1
  24. cognite_toolkit/_cdf_tk/client/api/{extended_files.py → legacy/extended_files.py} +2 -2
  25. cognite_toolkit/_cdf_tk/client/api/{extended_functions.py → legacy/extended_functions.py} +15 -18
  26. cognite_toolkit/_cdf_tk/client/api/{extended_raw.py → legacy/extended_raw.py} +1 -1
  27. cognite_toolkit/_cdf_tk/client/api/{extended_timeseries.py → legacy/extended_timeseries.py} +5 -2
  28. cognite_toolkit/_cdf_tk/client/api/{location_filters.py → legacy/location_filters.py} +1 -1
  29. cognite_toolkit/_cdf_tk/client/api/legacy/robotics/__init__.py +8 -0
  30. cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/capabilities.py +1 -1
  31. cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/data_postprocessing.py +1 -1
  32. cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/frames.py +1 -1
  33. cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/locations.py +1 -1
  34. cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/maps.py +1 -1
  35. cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/robots.py +2 -2
  36. cognite_toolkit/_cdf_tk/client/api/{search_config.py → legacy/search_config.py} +5 -1
  37. cognite_toolkit/_cdf_tk/client/api/migration.py +177 -4
  38. cognite_toolkit/_cdf_tk/client/api/project.py +9 -8
  39. cognite_toolkit/_cdf_tk/client/api/search.py +2 -2
  40. cognite_toolkit/_cdf_tk/client/api/streams.py +88 -0
  41. cognite_toolkit/_cdf_tk/client/api/three_d.py +384 -0
  42. cognite_toolkit/_cdf_tk/client/data_classes/api_classes.py +13 -0
  43. cognite_toolkit/_cdf_tk/client/data_classes/base.py +37 -33
  44. cognite_toolkit/_cdf_tk/client/data_classes/charts_data.py +95 -213
  45. cognite_toolkit/_cdf_tk/client/data_classes/infield.py +32 -18
  46. cognite_toolkit/_cdf_tk/client/data_classes/instance_api.py +18 -13
  47. cognite_toolkit/_cdf_tk/client/data_classes/legacy/__init__.py +0 -0
  48. cognite_toolkit/_cdf_tk/client/data_classes/{canvas.py → legacy/canvas.py} +47 -4
  49. cognite_toolkit/_cdf_tk/client/data_classes/{charts.py → legacy/charts.py} +3 -3
  50. cognite_toolkit/_cdf_tk/client/data_classes/{migration.py → legacy/migration.py} +10 -2
  51. cognite_toolkit/_cdf_tk/client/data_classes/streams.py +90 -0
  52. cognite_toolkit/_cdf_tk/client/data_classes/three_d.py +112 -0
  53. cognite_toolkit/_cdf_tk/client/testing.py +42 -18
  54. cognite_toolkit/_cdf_tk/commands/__init__.py +7 -6
  55. cognite_toolkit/_cdf_tk/commands/_changes.py +3 -42
  56. cognite_toolkit/_cdf_tk/commands/_download.py +21 -11
  57. cognite_toolkit/_cdf_tk/commands/_migrate/__init__.py +0 -2
  58. cognite_toolkit/_cdf_tk/commands/_migrate/command.py +22 -20
  59. cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +140 -92
  60. cognite_toolkit/_cdf_tk/commands/_migrate/creators.py +1 -1
  61. cognite_toolkit/_cdf_tk/commands/_migrate/data_classes.py +108 -26
  62. cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +448 -45
  63. cognite_toolkit/_cdf_tk/commands/_migrate/data_model.py +1 -0
  64. cognite_toolkit/_cdf_tk/commands/_migrate/default_mappings.py +6 -6
  65. cognite_toolkit/_cdf_tk/commands/_migrate/issues.py +52 -1
  66. cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +377 -11
  67. cognite_toolkit/_cdf_tk/commands/_migrate/selectors.py +9 -4
  68. cognite_toolkit/_cdf_tk/commands/_profile.py +1 -1
  69. cognite_toolkit/_cdf_tk/commands/_purge.py +36 -39
  70. cognite_toolkit/_cdf_tk/commands/_questionary_style.py +16 -0
  71. cognite_toolkit/_cdf_tk/commands/_upload.py +109 -86
  72. cognite_toolkit/_cdf_tk/commands/about.py +221 -0
  73. cognite_toolkit/_cdf_tk/commands/auth.py +19 -12
  74. cognite_toolkit/_cdf_tk/commands/build_cmd.py +16 -62
  75. cognite_toolkit/_cdf_tk/commands/build_v2/__init__.py +0 -0
  76. cognite_toolkit/_cdf_tk/commands/build_v2/build_cmd.py +241 -0
  77. cognite_toolkit/_cdf_tk/commands/build_v2/build_input.py +85 -0
  78. cognite_toolkit/_cdf_tk/commands/build_v2/build_issues.py +27 -0
  79. cognite_toolkit/_cdf_tk/commands/clean.py +63 -16
  80. cognite_toolkit/_cdf_tk/commands/deploy.py +20 -17
  81. cognite_toolkit/_cdf_tk/commands/dump_resource.py +10 -8
  82. cognite_toolkit/_cdf_tk/commands/init.py +225 -3
  83. cognite_toolkit/_cdf_tk/commands/modules.py +20 -44
  84. cognite_toolkit/_cdf_tk/commands/pull.py +6 -19
  85. cognite_toolkit/_cdf_tk/commands/resources.py +179 -0
  86. cognite_toolkit/_cdf_tk/commands/run.py +1 -1
  87. cognite_toolkit/_cdf_tk/constants.py +20 -1
  88. cognite_toolkit/_cdf_tk/cruds/__init__.py +19 -5
  89. cognite_toolkit/_cdf_tk/cruds/_base_cruds.py +14 -70
  90. cognite_toolkit/_cdf_tk/cruds/_data_cruds.py +10 -19
  91. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/__init__.py +4 -1
  92. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/agent.py +11 -9
  93. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/auth.py +5 -15
  94. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +45 -44
  95. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/configuration.py +5 -12
  96. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/data_organization.py +4 -13
  97. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/datamodel.py +206 -67
  98. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/extraction_pipeline.py +6 -18
  99. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +126 -35
  100. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +7 -28
  101. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/function.py +23 -30
  102. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/hosted_extractors.py +12 -30
  103. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/industrial_tool.py +4 -8
  104. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/location.py +4 -16
  105. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/migration.py +5 -13
  106. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/raw.py +5 -11
  107. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +3 -8
  108. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/robotics.py +16 -45
  109. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +94 -0
  110. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/three_d_model.py +3 -7
  111. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +5 -15
  112. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/transformation.py +75 -32
  113. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/workflow.py +20 -40
  114. cognite_toolkit/_cdf_tk/cruds/_worker.py +24 -36
  115. cognite_toolkit/_cdf_tk/data_classes/_module_toml.py +1 -0
  116. cognite_toolkit/_cdf_tk/feature_flags.py +16 -36
  117. cognite_toolkit/_cdf_tk/plugins.py +2 -1
  118. cognite_toolkit/_cdf_tk/resource_classes/__init__.py +4 -0
  119. cognite_toolkit/_cdf_tk/resource_classes/capabilities.py +12 -0
  120. cognite_toolkit/_cdf_tk/resource_classes/functions.py +3 -1
  121. cognite_toolkit/_cdf_tk/resource_classes/infield_cdm_location_config.py +109 -0
  122. cognite_toolkit/_cdf_tk/resource_classes/migration.py +8 -17
  123. cognite_toolkit/_cdf_tk/resource_classes/search_config.py +1 -1
  124. cognite_toolkit/_cdf_tk/resource_classes/streams.py +29 -0
  125. cognite_toolkit/_cdf_tk/resource_classes/workflow_version.py +164 -5
  126. cognite_toolkit/_cdf_tk/storageio/__init__.py +9 -21
  127. cognite_toolkit/_cdf_tk/storageio/_annotations.py +19 -16
  128. cognite_toolkit/_cdf_tk/storageio/_applications.py +340 -28
  129. cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +67 -104
  130. cognite_toolkit/_cdf_tk/storageio/_base.py +61 -29
  131. cognite_toolkit/_cdf_tk/storageio/_datapoints.py +276 -20
  132. cognite_toolkit/_cdf_tk/storageio/_file_content.py +435 -0
  133. cognite_toolkit/_cdf_tk/storageio/_instances.py +35 -3
  134. cognite_toolkit/_cdf_tk/storageio/_raw.py +26 -0
  135. cognite_toolkit/_cdf_tk/storageio/selectors/__init__.py +71 -4
  136. cognite_toolkit/_cdf_tk/storageio/selectors/_base.py +14 -2
  137. cognite_toolkit/_cdf_tk/storageio/selectors/_canvas.py +14 -0
  138. cognite_toolkit/_cdf_tk/storageio/selectors/_charts.py +14 -0
  139. cognite_toolkit/_cdf_tk/storageio/selectors/_datapoints.py +23 -3
  140. cognite_toolkit/_cdf_tk/storageio/selectors/_file_content.py +164 -0
  141. cognite_toolkit/_cdf_tk/storageio/selectors/_three_d.py +34 -0
  142. cognite_toolkit/_cdf_tk/tk_warnings/other.py +4 -0
  143. cognite_toolkit/_cdf_tk/tracker.py +2 -2
  144. cognite_toolkit/_cdf_tk/utils/cdf.py +1 -1
  145. cognite_toolkit/_cdf_tk/utils/dtype_conversion.py +9 -3
  146. cognite_toolkit/_cdf_tk/utils/fileio/__init__.py +2 -0
  147. cognite_toolkit/_cdf_tk/utils/fileio/_base.py +5 -1
  148. cognite_toolkit/_cdf_tk/utils/fileio/_readers.py +112 -20
  149. cognite_toolkit/_cdf_tk/utils/fileio/_writers.py +15 -15
  150. cognite_toolkit/_cdf_tk/utils/http_client/__init__.py +28 -0
  151. cognite_toolkit/_cdf_tk/utils/http_client/_client.py +285 -18
  152. cognite_toolkit/_cdf_tk/utils/http_client/_data_classes.py +56 -4
  153. cognite_toolkit/_cdf_tk/utils/http_client/_data_classes2.py +247 -0
  154. cognite_toolkit/_cdf_tk/utils/http_client/_tracker.py +5 -2
  155. cognite_toolkit/_cdf_tk/utils/interactive_select.py +60 -18
  156. cognite_toolkit/_cdf_tk/utils/sql_parser.py +2 -3
  157. cognite_toolkit/_cdf_tk/utils/useful_types.py +6 -2
  158. cognite_toolkit/_cdf_tk/validation.py +83 -1
  159. cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
  160. cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
  161. cognite_toolkit/_resources/cdf.toml +5 -4
  162. cognite_toolkit/_version.py +1 -1
  163. cognite_toolkit/config.dev.yaml +13 -0
  164. {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.39.dist-info}/METADATA +24 -24
  165. cognite_toolkit-0.7.39.dist-info/RECORD +322 -0
  166. cognite_toolkit-0.7.39.dist-info/WHEEL +4 -0
  167. {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.39.dist-info}/entry_points.txt +1 -0
  168. cognite_toolkit/_cdf_tk/client/api/robotics/__init__.py +0 -3
  169. cognite_toolkit/_cdf_tk/commands/_migrate/canvas.py +0 -201
  170. cognite_toolkit/_cdf_tk/commands/dump_data.py +0 -489
  171. cognite_toolkit/_cdf_tk/commands/featureflag.py +0 -27
  172. cognite_toolkit/_cdf_tk/prototypes/import_app.py +0 -41
  173. cognite_toolkit/_cdf_tk/utils/table_writers.py +0 -434
  174. cognite_toolkit-0.6.97.dist-info/RECORD +0 -306
  175. cognite_toolkit-0.6.97.dist-info/WHEEL +0 -4
  176. cognite_toolkit-0.6.97.dist-info/licenses/LICENSE +0 -18
  177. /cognite_toolkit/_cdf_tk/{prototypes/commands → client/api/legacy}/__init__.py +0 -0
  178. /cognite_toolkit/_cdf_tk/client/api/{dml.py → legacy/dml.py} +0 -0
  179. /cognite_toolkit/_cdf_tk/client/api/{fixed_transformations.py → legacy/fixed_transformations.py} +0 -0
  180. /cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/api.py +0 -0
  181. /cognite_toolkit/_cdf_tk/client/api/{robotics → legacy/robotics}/utlis.py +0 -0
  182. /cognite_toolkit/_cdf_tk/client/data_classes/{apm_config_v1.py → legacy/apm_config_v1.py} +0 -0
  183. /cognite_toolkit/_cdf_tk/client/data_classes/{extendable_cognite_file.py → legacy/extendable_cognite_file.py} +0 -0
  184. /cognite_toolkit/_cdf_tk/client/data_classes/{extended_filemetadata.py → legacy/extended_filemetadata.py} +0 -0
  185. /cognite_toolkit/_cdf_tk/client/data_classes/{extended_filemetdata.py → legacy/extended_filemetdata.py} +0 -0
  186. /cognite_toolkit/_cdf_tk/client/data_classes/{extended_timeseries.py → legacy/extended_timeseries.py} +0 -0
  187. /cognite_toolkit/_cdf_tk/client/data_classes/{functions.py → legacy/functions.py} +0 -0
  188. /cognite_toolkit/_cdf_tk/client/data_classes/{graphql_data_models.py → legacy/graphql_data_models.py} +0 -0
  189. /cognite_toolkit/_cdf_tk/client/data_classes/{instances.py → legacy/instances.py} +0 -0
  190. /cognite_toolkit/_cdf_tk/client/data_classes/{location_filters.py → legacy/location_filters.py} +0 -0
  191. /cognite_toolkit/_cdf_tk/client/data_classes/{pending_instances_ids.py → legacy/pending_instances_ids.py} +0 -0
  192. /cognite_toolkit/_cdf_tk/client/data_classes/{project.py → legacy/project.py} +0 -0
  193. /cognite_toolkit/_cdf_tk/client/data_classes/{raw.py → legacy/raw.py} +0 -0
  194. /cognite_toolkit/_cdf_tk/client/data_classes/{robotics.py → legacy/robotics.py} +0 -0
  195. /cognite_toolkit/_cdf_tk/client/data_classes/{search_config.py → legacy/search_config.py} +0 -0
  196. /cognite_toolkit/_cdf_tk/client/data_classes/{sequences.py → legacy/sequences.py} +0 -0
  197. /cognite_toolkit/_cdf_tk/client/data_classes/{streamlit_.py → legacy/streamlit_.py} +0 -0
  198. /cognite_toolkit/_cdf_tk/{prototypes/commands/import_.py → commands/_import_cmd.py} +0 -0
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from collections import defaultdict
3
- from collections.abc import Iterable, MutableSequence, Sequence
3
+ from collections.abc import Iterable, Sequence
4
4
  from typing import Any, ClassVar, Generic
5
5
 
6
6
  from cognite.client.data_classes import (
@@ -8,26 +8,16 @@ from cognite.client.data_classes import (
8
8
  Asset,
9
9
  AssetList,
10
10
  AssetWrite,
11
- AssetWriteList,
12
11
  Event,
13
12
  EventList,
14
13
  EventWrite,
15
- EventWriteList,
16
14
  FileMetadata,
17
15
  FileMetadataList,
18
- FileMetadataWrite,
19
- FileMetadataWriteList,
20
16
  Label,
21
17
  LabelDefinition,
22
18
  TimeSeries,
23
19
  TimeSeriesList,
24
20
  TimeSeriesWrite,
25
- TimeSeriesWriteList,
26
- )
27
- from cognite.client.data_classes._base import (
28
- T_CogniteResourceList,
29
- T_WritableCogniteResource,
30
- T_WriteClass,
31
21
  )
32
22
 
33
23
  from cognite_toolkit._cdf_tk.client import ToolkitClient
@@ -40,6 +30,7 @@ from cognite_toolkit._cdf_tk.cruds import (
40
30
  TimeSeriesCRUD,
41
31
  )
42
32
  from cognite_toolkit._cdf_tk.exceptions import ToolkitMissingResourceError, ToolkitNotImplementedError
33
+ from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
43
34
  from cognite_toolkit._cdf_tk.utils.aggregators import (
44
35
  AssetAggregator,
45
36
  AssetCentricAggregator,
@@ -50,23 +41,10 @@ from cognite_toolkit._cdf_tk.utils.aggregators import (
50
41
  from cognite_toolkit._cdf_tk.utils.cdf import metadata_key_counts
51
42
  from cognite_toolkit._cdf_tk.utils.fileio import FileReader, SchemaColumn
52
43
  from cognite_toolkit._cdf_tk.utils.fileio._readers import TableReader
53
- from cognite_toolkit._cdf_tk.utils.http_client import (
54
- FailedRequestItems,
55
- FailedRequestMessage,
56
- FailedResponse,
57
- FailedResponseItems,
58
- HTTPClient,
59
- HTTPMessage,
60
- SimpleBodyRequest,
61
- SuccessResponse,
62
- SuccessResponseItems,
63
- )
64
44
  from cognite_toolkit._cdf_tk.utils.useful_types import (
65
- T_ID,
66
45
  AssetCentricResource,
67
46
  AssetCentricType,
68
47
  JsonVal,
69
- T_WritableCogniteResourceList,
70
48
  )
71
49
 
72
50
  from ._base import (
@@ -80,11 +58,10 @@ from ._base import (
80
58
  from .selectors import AssetCentricSelector, AssetSubtreeSelector, DataSetSelector
81
59
 
82
60
 
83
- class BaseAssetCentricIO(
84
- Generic[T_ID, T_WriteClass, T_WritableCogniteResource, T_CogniteResourceList, T_WritableCogniteResourceList],
85
- TableStorageIO[AssetCentricSelector, T_WritableCogniteResource],
86
- ConfigurableStorageIO[AssetCentricSelector, T_WritableCogniteResource],
87
- TableUploadableStorageIO[AssetCentricSelector, T_WritableCogniteResource, T_WriteClass],
61
+ class AssetCentricIO(
62
+ Generic[T_ResourceResponse],
63
+ TableStorageIO[AssetCentricSelector, T_ResourceResponse],
64
+ ConfigurableStorageIO[AssetCentricSelector, T_ResourceResponse],
88
65
  ABC,
89
66
  ):
90
67
  RESOURCE_TYPE: ClassVar[AssetCentricType]
@@ -102,7 +79,7 @@ class BaseAssetCentricIO(
102
79
  raise NotImplementedError()
103
80
 
104
81
  @abstractmethod
105
- def retrieve(self, ids: Sequence[int]) -> T_WritableCogniteResourceList:
82
+ def retrieve(self, ids: Sequence[int]) -> Sequence[T_ResourceResponse]:
106
83
  raise NotImplementedError()
107
84
 
108
85
  def count(self, selector: AssetCentricSelector) -> int | None:
@@ -188,6 +165,26 @@ class BaseAssetCentricIO(
188
165
  asset_ids.update(item.asset_ids or [])
189
166
  self.client.lookup.assets.external_id(list(asset_ids))
190
167
 
168
+ def data_to_row(
169
+ self, data_chunk: Sequence[T_ResourceResponse], selector: AssetCentricSelector | None = None
170
+ ) -> list[dict[str, JsonVal]]:
171
+ rows: list[dict[str, JsonVal]] = []
172
+ for chunk in self.data_to_json_chunk(data_chunk, selector):
173
+ if "metadata" in chunk and isinstance(chunk["metadata"], dict):
174
+ metadata = chunk.pop("metadata")
175
+ # MyPy does understand that metadata is a dict here due to the check above.
176
+ for key, value in metadata.items(): # type: ignore[union-attr]
177
+ chunk[f"metadata.{key}"] = value
178
+ rows.append(chunk)
179
+ return rows
180
+
181
+
182
+ class UploadableAssetCentricIO(
183
+ Generic[T_ResourceResponse, T_ResourceRequest],
184
+ AssetCentricIO[T_ResourceResponse],
185
+ TableUploadableStorageIO[AssetCentricSelector, T_ResourceResponse, T_ResourceRequest],
186
+ ABC,
187
+ ):
191
188
  def _populate_data_set_external_id_cache(self, chunk: Sequence[dict[str, Any]]) -> None:
192
189
  data_set_external_ids: set[str] = set()
193
190
  for item in chunk:
@@ -222,22 +219,16 @@ class BaseAssetCentricIO(
222
219
  security_category_names.add(security_category_external_id)
223
220
  self.client.lookup.security_categories.id(list(security_category_names))
224
221
 
225
- def data_to_row(
226
- self, data_chunk: Sequence[T_WritableCogniteResource], selector: AssetCentricSelector | None = None
227
- ) -> list[dict[str, JsonVal]]:
228
- rows: list[dict[str, JsonVal]] = []
229
- for chunk in self.data_to_json_chunk(data_chunk, selector):
230
- if "metadata" in chunk and isinstance(chunk["metadata"], dict):
231
- metadata = chunk.pop("metadata")
232
- # MyPy does understand that metadata is a dict here due to the check above.
233
- for key, value in metadata.items(): # type: ignore[union-attr]
234
- chunk[f"metadata.{key}"] = value
235
- rows.append(chunk)
236
- return rows
222
+ def rows_to_data(
223
+ self, rows: list[tuple[str, dict[str, JsonVal]]], selector: AssetCentricSelector | None = None
224
+ ) -> Sequence[UploadItem[T_ResourceRequest]]:
225
+ # We need to populate caches for any external IDs used in the rows before converting to resources.
226
+ # Thus, we override this method instead of row_to_resource, and reuse the json_to_resource method that
227
+ # does the cache population.
228
+ return self.json_chunk_to_data([(source_id, self.row_to_json(row)) for source_id, row in rows])
237
229
 
238
- def row_to_resource(
239
- self, source_id: str, row: dict[str, JsonVal], selector: AssetCentricSelector | None = None
240
- ) -> T_WriteClass:
230
+ @classmethod
231
+ def row_to_json(cls, row: dict[str, JsonVal]) -> dict[str, JsonVal]:
241
232
  metadata: dict[str, JsonVal] = {}
242
233
  cleaned_row: dict[str, JsonVal] = {}
243
234
  for key, value in row.items():
@@ -248,10 +239,17 @@ class BaseAssetCentricIO(
248
239
  cleaned_row[key] = value
249
240
  if metadata:
250
241
  cleaned_row["metadata"] = metadata
251
- return self.json_to_resource(cleaned_row)
242
+ return cleaned_row
243
+
244
+ def row_to_resource(
245
+ self, source_id: str, row: dict[str, JsonVal], selector: AssetCentricSelector | None = None
246
+ ) -> T_ResourceRequest:
247
+ raise NotImplementedError(
248
+ f"This method should not be called. {type(self).__name__} overrides rows_to_data instead."
249
+ )
252
250
 
253
251
 
254
- class AssetIO(BaseAssetCentricIO[str, AssetWrite, Asset, AssetWriteList, AssetList]):
252
+ class AssetIO(UploadableAssetCentricIO[Asset, AssetWrite]):
255
253
  KIND = "Assets"
256
254
  RESOURCE_TYPE = "asset"
257
255
  SUPPORTED_DOWNLOAD_FORMATS = frozenset({".parquet", ".csv", ".ndjson"})
@@ -319,6 +317,9 @@ class AssetIO(BaseAssetCentricIO[str, AssetWrite, Asset, AssetWriteList, AssetLi
319
317
  asset_subtree_external_ids=asset_subtree_external_ids,
320
318
  data_set_external_ids=data_set_external_ids,
321
319
  aggregated_properties=["child_count", "path", "depth"],
320
+ # We cannot use partitions here as it is not thread safe. This spawn multiple threads
321
+ # that are not shut down until all data is downloaded. We need to be able to abort.
322
+ partitions=None,
322
323
  ):
323
324
  self._collect_dependencies(asset_list, selector)
324
325
  yield Page(worker_id="main", items=asset_list)
@@ -347,7 +348,9 @@ class AssetIO(BaseAssetCentricIO[str, AssetWrite, Asset, AssetWriteList, AssetLi
347
348
  return self.client.assets.retrieve_multiple(ids)
348
349
 
349
350
  @classmethod
350
- def read_chunks(cls, reader: FileReader) -> Iterable[list[tuple[str, dict[str, JsonVal]]]]:
351
+ def read_chunks(
352
+ cls, reader: FileReader, selector: AssetCentricSelector
353
+ ) -> Iterable[list[tuple[str, dict[str, JsonVal]]]]:
351
354
  """Assets require special handling when reading data to ensure parent assets are created first."""
352
355
  current_depth = max_depth = 0
353
356
  data_name = "row" if isinstance(reader, TableReader) else "line"
@@ -375,7 +378,7 @@ class AssetIO(BaseAssetCentricIO[str, AssetWrite, Asset, AssetWriteList, AssetLi
375
378
  current_depth += 1
376
379
 
377
380
 
378
- class FileMetadataIO(BaseAssetCentricIO[str, FileMetadataWrite, FileMetadata, FileMetadataWriteList, FileMetadataList]):
381
+ class FileMetadataIO(AssetCentricIO[FileMetadata]):
379
382
  KIND = "FileMetadata"
380
383
  RESOURCE_TYPE = "file"
381
384
  SUPPORTED_DOWNLOAD_FORMATS = frozenset({".parquet", ".csv", ".ndjson"})
@@ -430,54 +433,20 @@ class FileMetadataIO(BaseAssetCentricIO[str, FileMetadataWrite, FileMetadata, Fi
430
433
  ]
431
434
  return file_schema + metadata_schema
432
435
 
433
- def stream_data(self, selector: AssetCentricSelector, limit: int | None = None) -> Iterable[Page]:
436
+ def stream_data(self, selector: AssetCentricSelector, limit: int | None = None) -> Iterable[Page[FileMetadata]]:
434
437
  asset_subtree_external_ids, data_set_external_ids = self._get_hierarchy_dataset_pair(selector)
435
438
  for file_list in self.client.files(
436
439
  chunk_size=self.CHUNK_SIZE,
437
440
  limit=limit,
438
441
  asset_subtree_external_ids=asset_subtree_external_ids,
439
442
  data_set_external_ids=data_set_external_ids,
443
+ # We cannot use partitions here as it is not thread safe. This spawn multiple threads
444
+ # that are not shut down until all data is downloaded. We need to be able to abort.
445
+ partitions=None,
440
446
  ):
441
447
  self._collect_dependencies(file_list, selector)
442
448
  yield Page(worker_id="main", items=file_list)
443
449
 
444
- def upload_items(
445
- self,
446
- data_chunk: Sequence[UploadItem[FileMetadataWrite]],
447
- http_client: HTTPClient,
448
- selector: AssetCentricSelector | None = None,
449
- ) -> Sequence[HTTPMessage]:
450
- # The /files endpoint only supports creating one file at a time, so we override the default chunked
451
- # upload behavior to upload one by one.
452
- config = http_client.config
453
- results: MutableSequence[HTTPMessage] = []
454
- for item in data_chunk:
455
- responses = http_client.request_with_retries(
456
- message=SimpleBodyRequest(
457
- endpoint_url=config.create_api_url(self.UPLOAD_ENDPOINT),
458
- method="POST",
459
- # MyPy does not understand that .dump is valid json
460
- body_content=item.dump(), # type: ignore[arg-type]
461
- )
462
- )
463
- # Convert the responses to per-item responses
464
- for message in responses:
465
- if isinstance(message, SuccessResponse):
466
- results.append(
467
- SuccessResponseItems(status_code=message.status_code, ids=[item.as_id()], body=message.body)
468
- )
469
- elif isinstance(message, FailedResponse):
470
- results.append(
471
- FailedResponseItems(
472
- status_code=message.status_code, ids=[item.as_id()], body=message.body, error=message.error
473
- )
474
- )
475
- elif isinstance(message, FailedRequestMessage):
476
- results.append(FailedRequestItems(ids=[item.as_id()], error=message.error))
477
- else:
478
- results.append(message)
479
- return results
480
-
481
450
  def retrieve(self, ids: Sequence[int]) -> FileMetadataList:
482
451
  return self.client.files.retrieve_multiple(ids)
483
452
 
@@ -492,20 +461,8 @@ class FileMetadataIO(BaseAssetCentricIO[str, FileMetadataWrite, FileMetadata, Fi
492
461
 
493
462
  return [self._crud.dump_resource(item) for item in data_chunk]
494
463
 
495
- def json_chunk_to_data(
496
- self, data_chunk: list[tuple[str, dict[str, JsonVal]]]
497
- ) -> Sequence[UploadItem[FileMetadataWrite]]:
498
- chunks = [item_json for _, item_json in data_chunk]
499
- self._populate_asset_external_ids_cache(chunks)
500
- self._populate_data_set_external_id_cache(chunks)
501
- self._populate_security_category_name_cache(chunks)
502
- return super().json_chunk_to_data(data_chunk)
503
-
504
- def json_to_resource(self, item_json: dict[str, JsonVal]) -> FileMetadataWrite:
505
- return self._crud.load_resource(item_json)
506
-
507
464
 
508
- class TimeSeriesIO(BaseAssetCentricIO[str, TimeSeriesWrite, TimeSeries, TimeSeriesWriteList, TimeSeriesList]):
465
+ class TimeSeriesIO(UploadableAssetCentricIO[TimeSeries, TimeSeriesWrite]):
509
466
  KIND = "TimeSeries"
510
467
  SUPPORTED_DOWNLOAD_FORMATS = frozenset({".parquet", ".csv", ".ndjson"})
511
468
  SUPPORTED_COMPRESSIONS = frozenset({".gz"})
@@ -533,6 +490,9 @@ class TimeSeriesIO(BaseAssetCentricIO[str, TimeSeriesWrite, TimeSeries, TimeSeri
533
490
  limit=limit,
534
491
  asset_subtree_external_ids=asset_subtree_external_ids,
535
492
  data_set_external_ids=data_set_external_ids,
493
+ # We cannot use partitions here as it is not thread safe. This spawn multiple threads
494
+ # that are not shut down until all data is downloaded. We need to be able to abort.
495
+ partitions=None,
536
496
  ):
537
497
  self._collect_dependencies(ts_list, selector)
538
498
  yield Page(worker_id="main", items=ts_list)
@@ -598,7 +558,7 @@ class TimeSeriesIO(BaseAssetCentricIO[str, TimeSeriesWrite, TimeSeries, TimeSeri
598
558
  return ts_schema + metadata_schema
599
559
 
600
560
 
601
- class EventIO(BaseAssetCentricIO[str, EventWrite, Event, EventWriteList, EventList]):
561
+ class EventIO(UploadableAssetCentricIO[Event, EventWrite]):
602
562
  KIND = "Events"
603
563
  SUPPORTED_DOWNLOAD_FORMATS = frozenset({".parquet", ".csv", ".ndjson"})
604
564
  SUPPORTED_COMPRESSIONS = frozenset({".gz"})
@@ -660,6 +620,9 @@ class EventIO(BaseAssetCentricIO[str, EventWrite, Event, EventWriteList, EventLi
660
620
  limit=limit,
661
621
  asset_subtree_external_ids=asset_subtree_external_ids,
662
622
  data_set_external_ids=data_set_external_ids,
623
+ # We cannot use partitions here as it is not thread safe. This spawn multiple threads
624
+ # that are not shut down until all data is downloaded. We need to be able to abort.
625
+ partitions=None,
663
626
  ):
664
627
  self._collect_dependencies(event_list, selector)
665
628
  yield Page(worker_id="main", items=event_list)
@@ -698,7 +661,7 @@ class HierarchyIO(ConfigurableStorageIO[AssetCentricSelector, AssetCentricResour
698
661
  self._file_io = FileMetadataIO(client)
699
662
  self._timeseries_io = TimeSeriesIO(client)
700
663
  self._event_io = EventIO(client)
701
- self._io_by_kind: dict[str, BaseAssetCentricIO] = {
664
+ self._io_by_kind: dict[str, AssetCentricIO] = {
702
665
  self._asset_io.KIND: self._asset_io,
703
666
  self._file_io.KIND: self._file_io,
704
667
  self._timeseries_io.KIND: self._timeseries_io,
@@ -706,7 +669,7 @@ class HierarchyIO(ConfigurableStorageIO[AssetCentricSelector, AssetCentricResour
706
669
  }
707
670
 
708
671
  def as_id(self, item: AssetCentricResource) -> str:
709
- return item.external_id or BaseAssetCentricIO.create_internal_identifier(item.id, self.client.config.project)
672
+ return item.external_id or AssetCentricIO.create_internal_identifier(item.id, self.client.config.project)
710
673
 
711
674
  def stream_data(
712
675
  self, selector: AssetCentricSelector, limit: int | None = None
@@ -726,5 +689,5 @@ class HierarchyIO(ConfigurableStorageIO[AssetCentricSelector, AssetCentricResour
726
689
  def configurations(self, selector: AssetCentricSelector) -> Iterable[StorageIOConfig]:
727
690
  yield from self.get_resource_io(selector.kind).configurations(selector)
728
691
 
729
- def get_resource_io(self, kind: str) -> BaseAssetCentricIO:
692
+ def get_resource_io(self, kind: str) -> AssetCentricIO:
730
693
  return self._io_by_kind[kind]
@@ -1,17 +1,15 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from collections.abc import Iterable, Mapping, Sequence, Sized
3
3
  from dataclasses import dataclass
4
- from typing import ClassVar, Generic, TypeVar
5
-
6
- from cognite.client.data_classes._base import T_CogniteResource
4
+ from typing import ClassVar, Generic, Literal, TypeVar
7
5
 
8
6
  from cognite_toolkit._cdf_tk.client import ToolkitClient
9
7
  from cognite_toolkit._cdf_tk.exceptions import ToolkitNotImplementedError
8
+ from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
10
9
  from cognite_toolkit._cdf_tk.utils.collection import chunker
11
- from cognite_toolkit._cdf_tk.utils.fileio import FileReader, SchemaColumn
12
- from cognite_toolkit._cdf_tk.utils.fileio._readers import TableReader
10
+ from cognite_toolkit._cdf_tk.utils.fileio import MultiFileReader, SchemaColumn
13
11
  from cognite_toolkit._cdf_tk.utils.http_client import HTTPClient, HTTPMessage, ItemsRequest
14
- from cognite_toolkit._cdf_tk.utils.useful_types import JsonVal, T_WriteCogniteResource
12
+ from cognite_toolkit._cdf_tk.utils.useful_types import JsonVal
15
13
 
16
14
  from .selectors import DataSelector
17
15
 
@@ -28,9 +26,9 @@ T_Selector = TypeVar("T_Selector", bound=DataSelector)
28
26
 
29
27
 
30
28
  @dataclass
31
- class Page(Generic[T_CogniteResource], Sized):
29
+ class Page(Generic[T_ResourceResponse], Sized):
32
30
  worker_id: str
33
- items: Sequence[T_CogniteResource]
31
+ items: Sequence[T_ResourceResponse]
34
32
  next_cursor: str | None = None
35
33
 
36
34
  def __len__(self) -> int:
@@ -38,7 +36,7 @@ class Page(Generic[T_CogniteResource], Sized):
38
36
 
39
37
 
40
38
  @dataclass
41
- class UploadItem(Generic[T_WriteCogniteResource]):
39
+ class UploadItem(Generic[T_ResourceRequest]):
42
40
  """An item to be uploaded to CDF, consisting of a source ID and the writable Cognite resource.
43
41
 
44
42
  Attributes:
@@ -47,7 +45,7 @@ class UploadItem(Generic[T_WriteCogniteResource]):
47
45
  """
48
46
 
49
47
  source_id: str
50
- item: T_WriteCogniteResource
48
+ item: T_ResourceRequest
51
49
 
52
50
  def as_id(self) -> str:
53
51
  return self.source_id
@@ -56,7 +54,7 @@ class UploadItem(Generic[T_WriteCogniteResource]):
56
54
  return self.item.dump(camel_case=True)
57
55
 
58
56
 
59
- class StorageIO(ABC, Generic[T_Selector, T_CogniteResource]):
57
+ class StorageIO(ABC, Generic[T_Selector, T_ResourceResponse]):
60
58
  """This is a base class for all storage classes in Cognite Toolkit
61
59
 
62
60
  It defines the interface for downloading data from CDF. Note this can also be used for multiple
@@ -80,7 +78,7 @@ class StorageIO(ABC, Generic[T_Selector, T_CogniteResource]):
80
78
  self.client = client
81
79
 
82
80
  @abstractmethod
83
- def as_id(self, item: T_CogniteResource) -> str:
81
+ def as_id(self, item: T_ResourceResponse) -> str:
84
82
  """Convert an item to its corresponding ID.
85
83
  Args:
86
84
  item: The item to convert.
@@ -116,7 +114,7 @@ class StorageIO(ABC, Generic[T_Selector, T_CogniteResource]):
116
114
 
117
115
  @abstractmethod
118
116
  def data_to_json_chunk(
119
- self, data_chunk: Sequence[T_CogniteResource], selector: T_Selector | None = None
117
+ self, data_chunk: Sequence[T_ResourceResponse], selector: T_Selector | None = None
120
118
  ) -> list[dict[str, JsonVal]]:
121
119
  """Convert a chunk of data to a JSON-compatible format.
122
120
 
@@ -132,7 +130,7 @@ class StorageIO(ABC, Generic[T_Selector, T_CogniteResource]):
132
130
 
133
131
 
134
132
  class UploadableStorageIO(
135
- Generic[T_Selector, T_CogniteResource, T_WriteCogniteResource], StorageIO[T_Selector, T_CogniteResource], ABC
133
+ Generic[T_Selector, T_ResourceResponse, T_ResourceRequest], StorageIO[T_Selector, T_ResourceResponse], ABC
136
134
  ):
137
135
  """A base class for storage items that support uploading data to CDF.
138
136
 
@@ -145,12 +143,14 @@ class UploadableStorageIO(
145
143
 
146
144
  KIND: ClassVar[str]
147
145
  SUPPORTED_READ_FORMATS: ClassVar[frozenset[str]]
146
+ UPLOAD_ENDPOINT_TYPE: Literal["app", "api"] = "api"
147
+ UPLOAD_ENDPOINT_METHOD: Literal["GET", "POST", "PATCH", "DELETE", "PUT"] = "POST"
148
148
  UPLOAD_ENDPOINT: ClassVar[str]
149
149
  UPLOAD_EXTRA_ARGS: ClassVar[Mapping[str, JsonVal] | None] = None
150
150
 
151
151
  def upload_items(
152
152
  self,
153
- data_chunk: Sequence[UploadItem[T_WriteCogniteResource]],
153
+ data_chunk: Sequence[UploadItem[T_ResourceRequest]],
154
154
  http_client: HTTPClient,
155
155
  selector: T_Selector | None = None,
156
156
  ) -> Sequence[HTTPMessage]:
@@ -170,10 +170,17 @@ class UploadableStorageIO(
170
170
  raise ValueError(f"Data chunk size {len(data_chunk)} exceeds the maximum CHUNK_SIZE of {self.CHUNK_SIZE}.")
171
171
 
172
172
  config = http_client.config
173
+ if self.UPLOAD_ENDPOINT_TYPE == "api":
174
+ url = config.create_api_url(self.UPLOAD_ENDPOINT)
175
+ elif self.UPLOAD_ENDPOINT_TYPE == "app":
176
+ url = config.create_app_url(self.UPLOAD_ENDPOINT)
177
+ else:
178
+ raise ToolkitNotImplementedError(f"Unsupported UPLOAD_ENDPOINT_TYPE {self.UPLOAD_ENDPOINT_TYPE!r}.")
179
+
173
180
  return http_client.request_with_retries(
174
181
  message=ItemsRequest(
175
- endpoint_url=config.create_api_url(self.UPLOAD_ENDPOINT),
176
- method="POST",
182
+ endpoint_url=url,
183
+ method=self.UPLOAD_ENDPOINT_METHOD,
177
184
  items=list(data_chunk),
178
185
  extra_body_fields=dict(self.UPLOAD_EXTRA_ARGS or {}),
179
186
  )
@@ -181,7 +188,7 @@ class UploadableStorageIO(
181
188
 
182
189
  def json_chunk_to_data(
183
190
  self, data_chunk: list[tuple[str, dict[str, JsonVal]]]
184
- ) -> Sequence[UploadItem[T_WriteCogniteResource]]:
191
+ ) -> Sequence[UploadItem[T_ResourceRequest]]:
185
192
  """Convert a JSON-compatible chunk of data back to a writable Cognite resource list.
186
193
 
187
194
  Args:
@@ -190,14 +197,14 @@ class UploadableStorageIO(
190
197
  Returns:
191
198
  A writable Cognite resource list representing the data.
192
199
  """
193
- result: list[UploadItem[T_WriteCogniteResource]] = []
200
+ result: list[UploadItem[T_ResourceRequest]] = []
194
201
  for source_id, item_json in data_chunk:
195
202
  item = self.json_to_resource(item_json)
196
203
  result.append(UploadItem(source_id=source_id, item=item))
197
204
  return result
198
205
 
199
206
  @abstractmethod
200
- def json_to_resource(self, item_json: dict[str, JsonVal]) -> T_WriteCogniteResource:
207
+ def json_to_resource(self, item_json: dict[str, JsonVal]) -> T_ResourceRequest:
201
208
  """Convert a JSON-compatible dictionary back to a writable Cognite resource.
202
209
 
203
210
  Args:
@@ -208,20 +215,45 @@ class UploadableStorageIO(
208
215
  raise NotImplementedError()
209
216
 
210
217
  @classmethod
211
- def read_chunks(cls, reader: FileReader) -> Iterable[list[tuple[str, dict[str, JsonVal]]]]:
212
- data_name = "row" if isinstance(reader, TableReader) else "line"
218
+ def read_chunks(
219
+ cls, reader: MultiFileReader, selector: T_Selector
220
+ ) -> Iterable[list[tuple[str, dict[str, JsonVal]]]]:
221
+ """Read data from a MultiFileReader in chunks.
222
+
223
+ This method yields chunks of data, where each chunk is a list of tuples. Each tuple contains a source ID
224
+ (e.g., line number or row identifier) and a dictionary representing the data in a JSON-compatible format.
225
+
226
+ This method can be overridden by subclasses to customize how data is read and chunked.
227
+ Args:
228
+ reader: An instance of MultiFileReader to read data from.
229
+ selector: The selection criteria to identify the data.
230
+ """
231
+ data_name = "row" if reader.is_table else "line"
213
232
  # Include name of line for better error messages
214
233
  iterable = ((f"{data_name} {line_no}", item) for line_no, item in reader.read_chunks_with_line_numbers())
215
234
 
216
235
  yield from chunker(iterable, cls.CHUNK_SIZE)
217
236
 
237
+ @classmethod
238
+ def count_chunks(cls, reader: MultiFileReader) -> int:
239
+ """Count the number of items in a MultiFileReader.
240
+
241
+ This method can be overridden by subclasses to customize how items are counted.
242
+
243
+ Args:
244
+ reader: An instance of MultiFileReader to count items from.
245
+ Returns:
246
+ The number of items in the reader.
247
+ """
248
+ return reader.count()
249
+
218
250
 
219
- class TableUploadableStorageIO(UploadableStorageIO[T_Selector, T_CogniteResource, T_WriteCogniteResource], ABC):
251
+ class TableUploadableStorageIO(UploadableStorageIO[T_Selector, T_ResourceResponse, T_ResourceRequest], ABC):
220
252
  """A base class for storage items that support uploading data with table schemas."""
221
253
 
222
254
  def rows_to_data(
223
255
  self, rows: list[tuple[str, dict[str, JsonVal]]], selector: T_Selector | None = None
224
- ) -> Sequence[UploadItem[T_WriteCogniteResource]]:
256
+ ) -> Sequence[UploadItem[T_ResourceRequest]]:
225
257
  """Convert a row-based JSON-compatible chunk of data back to a writable Cognite resource list.
226
258
 
227
259
  Args:
@@ -232,7 +264,7 @@ class TableUploadableStorageIO(UploadableStorageIO[T_Selector, T_CogniteResource
232
264
  Returns:
233
265
  A writable Cognite resource list representing the data.
234
266
  """
235
- result: list[UploadItem[T_WriteCogniteResource]] = []
267
+ result: list[UploadItem[T_ResourceRequest]] = []
236
268
  for source_id, row in rows:
237
269
  item = self.row_to_resource(source_id, row, selector=selector)
238
270
  result.append(UploadItem(source_id=source_id, item=item))
@@ -241,7 +273,7 @@ class TableUploadableStorageIO(UploadableStorageIO[T_Selector, T_CogniteResource
241
273
  @abstractmethod
242
274
  def row_to_resource(
243
275
  self, source_id: str, row: dict[str, JsonVal], selector: T_Selector | None = None
244
- ) -> T_WriteCogniteResource:
276
+ ) -> T_ResourceRequest:
245
277
  """Convert a row-based JSON-compatible dictionary back to a writable Cognite resource.
246
278
 
247
279
  Args:
@@ -254,7 +286,7 @@ class TableUploadableStorageIO(UploadableStorageIO[T_Selector, T_CogniteResource
254
286
  raise NotImplementedError()
255
287
 
256
288
 
257
- class ConfigurableStorageIO(StorageIO[T_Selector, T_CogniteResource], ABC):
289
+ class ConfigurableStorageIO(StorageIO[T_Selector, T_ResourceResponse], ABC):
258
290
  """A base class for storage items that support configurations for different storage items."""
259
291
 
260
292
  @abstractmethod
@@ -263,7 +295,7 @@ class ConfigurableStorageIO(StorageIO[T_Selector, T_CogniteResource], ABC):
263
295
  raise NotImplementedError()
264
296
 
265
297
 
266
- class TableStorageIO(StorageIO[T_Selector, T_CogniteResource], ABC):
298
+ class TableStorageIO(StorageIO[T_Selector, T_ResourceResponse], ABC):
267
299
  """A base class for storage items that support table schemas."""
268
300
 
269
301
  @abstractmethod
@@ -281,7 +313,7 @@ class TableStorageIO(StorageIO[T_Selector, T_CogniteResource], ABC):
281
313
 
282
314
  @abstractmethod
283
315
  def data_to_row(
284
- self, data_chunk: Sequence[T_CogniteResource], selector: T_Selector | None = None
316
+ self, data_chunk: Sequence[T_ResourceResponse], selector: T_Selector | None = None
285
317
  ) -> list[dict[str, JsonVal]]:
286
318
  """Convert a chunk of data to a row-based JSON-compatible format.
287
319