cognite-toolkit 0.7.9__py3-none-any.whl → 0.7.11__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.
- cognite_toolkit/_cdf_tk/commands/_purge.py +27 -28
- cognite_toolkit/_cdf_tk/commands/_upload.py +6 -2
- cognite_toolkit/_cdf_tk/commands/clean.py +11 -13
- cognite_toolkit/_cdf_tk/commands/deploy.py +9 -17
- cognite_toolkit/_cdf_tk/commands/dump_resource.py +6 -4
- cognite_toolkit/_cdf_tk/commands/pull.py +6 -19
- cognite_toolkit/_cdf_tk/cruds/_base_cruds.py +7 -25
- cognite_toolkit/_cdf_tk/cruds/_data_cruds.py +3 -6
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/agent.py +4 -6
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/auth.py +4 -12
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +19 -36
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/configuration.py +4 -10
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/data_organization.py +4 -12
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/datamodel.py +16 -41
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/extraction_pipeline.py +5 -15
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +8 -21
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +6 -22
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/function.py +5 -15
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/hosted_extractors.py +12 -26
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/industrial_tool.py +3 -6
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/location.py +3 -14
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/migration.py +4 -8
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/raw.py +4 -8
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +3 -6
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/robotics.py +15 -34
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +2 -5
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/three_d_model.py +3 -6
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +5 -13
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/transformation.py +4 -19
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/workflow.py +20 -37
- cognite_toolkit/_cdf_tk/cruds/_worker.py +13 -30
- cognite_toolkit/_cdf_tk/storageio/__init__.py +3 -3
- cognite_toolkit/_cdf_tk/storageio/_base.py +23 -0
- cognite_toolkit/_cdf_tk/storageio/_file_content.py +4 -0
- cognite_toolkit/_cdf_tk/storageio/selectors/_datapoints.py +1 -1
- cognite_toolkit/_cdf_tk/utils/fileio/_readers.py +42 -1
- cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
- cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
- cognite_toolkit/_resources/cdf.toml +1 -1
- cognite_toolkit/_version.py +1 -1
- {cognite_toolkit-0.7.9.dist-info → cognite_toolkit-0.7.11.dist-info}/METADATA +1 -1
- {cognite_toolkit-0.7.9.dist-info → cognite_toolkit-0.7.11.dist-info}/RECORD +45 -45
- {cognite_toolkit-0.7.9.dist-info → cognite_toolkit-0.7.11.dist-info}/WHEEL +0 -0
- {cognite_toolkit-0.7.9.dist-info → cognite_toolkit-0.7.11.dist-info}/entry_points.txt +0 -0
- {cognite_toolkit-0.7.9.dist-info → cognite_toolkit-0.7.11.dist-info}/licenses/LICENSE +0 -0
|
@@ -7,12 +7,7 @@ from typing import Literal, cast
|
|
|
7
7
|
|
|
8
8
|
import questionary
|
|
9
9
|
from cognite.client.data_classes import DataSetUpdate
|
|
10
|
-
from cognite.client.data_classes.
|
|
11
|
-
from cognite.client.data_classes.data_modeling import (
|
|
12
|
-
EdgeList,
|
|
13
|
-
NodeId,
|
|
14
|
-
NodeList,
|
|
15
|
-
)
|
|
10
|
+
from cognite.client.data_classes.data_modeling import Edge, NodeId
|
|
16
11
|
from cognite.client.data_classes.data_modeling.statistics import SpaceStatistics
|
|
17
12
|
from cognite.client.exceptions import CogniteAPIError
|
|
18
13
|
from cognite.client.utils._identifier import InstanceId
|
|
@@ -46,6 +41,7 @@ from cognite_toolkit._cdf_tk.exceptions import (
|
|
|
46
41
|
AuthorizationError,
|
|
47
42
|
ToolkitMissingResourceError,
|
|
48
43
|
)
|
|
44
|
+
from cognite_toolkit._cdf_tk.protocols import ResourceResponseProtocol
|
|
49
45
|
from cognite_toolkit._cdf_tk.storageio import InstanceIO
|
|
50
46
|
from cognite_toolkit._cdf_tk.storageio.selectors import InstanceSelector
|
|
51
47
|
from cognite_toolkit._cdf_tk.tk_warnings import (
|
|
@@ -107,7 +103,7 @@ class ToDelete(ABC):
|
|
|
107
103
|
@abstractmethod
|
|
108
104
|
def get_process_function(
|
|
109
105
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
110
|
-
) -> Callable[[
|
|
106
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
111
107
|
raise NotImplementedError()
|
|
112
108
|
|
|
113
109
|
def get_extra_fields(self) -> dict[str, JsonVal]:
|
|
@@ -118,9 +114,10 @@ class ToDelete(ABC):
|
|
|
118
114
|
class DataModelingToDelete(ToDelete):
|
|
119
115
|
def get_process_function(
|
|
120
116
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
121
|
-
) -> Callable[[
|
|
122
|
-
def as_id(chunk:
|
|
123
|
-
|
|
117
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
118
|
+
def as_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
119
|
+
# We know that all data modeling resources implement as_id
|
|
120
|
+
return [item.as_id().dump(include_type=False) for item in chunk] # type: ignore[attr-defined]
|
|
124
121
|
|
|
125
122
|
return as_id
|
|
126
123
|
|
|
@@ -129,11 +126,11 @@ class DataModelingToDelete(ToDelete):
|
|
|
129
126
|
class EdgeToDelete(ToDelete):
|
|
130
127
|
def get_process_function(
|
|
131
128
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
132
|
-
) -> Callable[[
|
|
133
|
-
def as_id(chunk:
|
|
129
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
130
|
+
def as_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
134
131
|
return [
|
|
135
132
|
{"space": item.space, "externalId": item.external_id, "instanceType": "edge"}
|
|
136
|
-
for item in cast(
|
|
133
|
+
for item in cast(list[Edge], chunk)
|
|
137
134
|
]
|
|
138
135
|
|
|
139
136
|
return as_id
|
|
@@ -146,9 +143,10 @@ class NodesToDelete(ToDelete):
|
|
|
146
143
|
|
|
147
144
|
def get_process_function(
|
|
148
145
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
149
|
-
) -> Callable[[
|
|
150
|
-
def check_for_data(chunk:
|
|
151
|
-
|
|
146
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
147
|
+
def check_for_data(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
148
|
+
# We know that all node resources implement as_id
|
|
149
|
+
node_ids = [item.as_id() for item in chunk] # type: ignore[attr-defined]
|
|
152
150
|
found_ids: set[InstanceId] = set()
|
|
153
151
|
if not self.delete_datapoints:
|
|
154
152
|
timeseries = client.time_series.retrieve_multiple(instance_ids=node_ids, ignore_unknown_ids=True)
|
|
@@ -164,8 +162,7 @@ class NodesToDelete(ToDelete):
|
|
|
164
162
|
dumped = node_id.dump(include_instance_type=True)
|
|
165
163
|
# The delete endpoint expects "instanceType" instead of "type"
|
|
166
164
|
dumped["instanceType"] = dumped.pop("type")
|
|
167
|
-
|
|
168
|
-
result.append(dumped) # type: ignore[arg-type]
|
|
165
|
+
result.append(dumped)
|
|
169
166
|
return result
|
|
170
167
|
|
|
171
168
|
return check_for_data
|
|
@@ -175,9 +172,10 @@ class NodesToDelete(ToDelete):
|
|
|
175
172
|
class IdResourceToDelete(ToDelete):
|
|
176
173
|
def get_process_function(
|
|
177
174
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
178
|
-
) -> Callable[[
|
|
179
|
-
def as_id(chunk:
|
|
180
|
-
|
|
175
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
176
|
+
def as_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
177
|
+
# We know that all id resources have an id attribute
|
|
178
|
+
return [{"id": item.id} for item in chunk] # type: ignore[attr-defined]
|
|
181
179
|
|
|
182
180
|
return as_id
|
|
183
181
|
|
|
@@ -186,9 +184,10 @@ class IdResourceToDelete(ToDelete):
|
|
|
186
184
|
class ExternalIdToDelete(ToDelete):
|
|
187
185
|
def get_process_function(
|
|
188
186
|
self, client: ToolkitClient, console: Console, verbose: bool, process_results: ResourceDeployResult
|
|
189
|
-
) -> Callable[[
|
|
190
|
-
def as_external_id(chunk:
|
|
191
|
-
|
|
187
|
+
) -> Callable[[list[ResourceResponseProtocol]], list[JsonVal]]:
|
|
188
|
+
def as_external_id(chunk: list[ResourceResponseProtocol]) -> list[JsonVal]:
|
|
189
|
+
# We know that all external id resources have an external_id attribute
|
|
190
|
+
return [{"externalId": item.external_id} for item in chunk] # type: ignore[attr-defined]
|
|
192
191
|
|
|
193
192
|
return as_external_id
|
|
194
193
|
|
|
@@ -321,7 +320,7 @@ class PurgeCommand(ToolkitCommand):
|
|
|
321
320
|
iteration_count = item.total // self.BATCH_SIZE_DM + (
|
|
322
321
|
1 if item.total % self.BATCH_SIZE_DM > 0 else 0
|
|
323
322
|
)
|
|
324
|
-
executor = ProducerWorkerExecutor[
|
|
323
|
+
executor = ProducerWorkerExecutor[list[ResourceResponseProtocol], list[JsonVal]](
|
|
325
324
|
download_iterable=self._iterate_batch(
|
|
326
325
|
item.crud, space, data_set_external_id, batch_size=self.BATCH_SIZE_DM
|
|
327
326
|
),
|
|
@@ -348,13 +347,13 @@ class PurgeCommand(ToolkitCommand):
|
|
|
348
347
|
@staticmethod
|
|
349
348
|
def _iterate_batch(
|
|
350
349
|
crud: ResourceCRUD, selected_space: str | None, data_set_external_id: str | None, batch_size: int
|
|
351
|
-
) -> Iterable[
|
|
352
|
-
batch =
|
|
350
|
+
) -> Iterable[list[ResourceResponseProtocol]]:
|
|
351
|
+
batch: list[ResourceResponseProtocol] = []
|
|
353
352
|
for resource in crud.iterate(space=selected_space, data_set_external_id=data_set_external_id):
|
|
354
353
|
batch.append(resource)
|
|
355
354
|
if len(batch) >= batch_size:
|
|
356
355
|
yield batch
|
|
357
|
-
batch =
|
|
356
|
+
batch = []
|
|
358
357
|
if batch:
|
|
359
358
|
yield batch
|
|
360
359
|
|
|
@@ -215,6 +215,10 @@ class UploadCommand(ToolkitCommand):
|
|
|
215
215
|
reader = MultiFileReader(datafiles)
|
|
216
216
|
if reader.is_table and not isinstance(io, TableUploadableStorageIO):
|
|
217
217
|
raise ToolkitValueError(f"{selector.display_name} does not support {reader.format!r} files.")
|
|
218
|
+
|
|
219
|
+
chunk_count = io.count_chunks(reader)
|
|
220
|
+
iteration_count = chunk_count // io.CHUNK_SIZE + (1 if chunk_count % io.CHUNK_SIZE > 0 else 0)
|
|
221
|
+
|
|
218
222
|
tracker = ProgressTracker[str]([self._UPLOAD])
|
|
219
223
|
executor = ProducerWorkerExecutor[list[tuple[str, dict[str, JsonVal]]], Sequence[UploadItem]](
|
|
220
224
|
download_iterable=io.read_chunks(reader, selector),
|
|
@@ -230,7 +234,7 @@ class UploadCommand(ToolkitCommand):
|
|
|
230
234
|
tracker=tracker,
|
|
231
235
|
console=console,
|
|
232
236
|
),
|
|
233
|
-
iteration_count=
|
|
237
|
+
iteration_count=iteration_count,
|
|
234
238
|
max_queue_size=self._MAX_QUEUE_SIZE,
|
|
235
239
|
download_description=f"Reading {selector.display_name!r} files",
|
|
236
240
|
process_description="Processing",
|
|
@@ -262,7 +266,7 @@ class UploadCommand(ToolkitCommand):
|
|
|
262
266
|
self, selector: Selector, data_file: Path, client: ToolkitClient
|
|
263
267
|
) -> UploadableStorageIO | None:
|
|
264
268
|
try:
|
|
265
|
-
io_cls = get_upload_io(
|
|
269
|
+
io_cls = get_upload_io(selector)
|
|
266
270
|
except ValueError as e:
|
|
267
271
|
self.warn(HighSeverityWarning(f"Could not find StorageIO for selector {selector}: {e}"))
|
|
268
272
|
return None
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import traceback
|
|
2
|
+
from collections.abc import Sequence
|
|
2
3
|
from graphlib import TopologicalSorter
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
@@ -24,14 +25,7 @@ from cognite_toolkit._cdf_tk.cruds import (
|
|
|
24
25
|
ResourceCRUD,
|
|
25
26
|
ResourceWorker,
|
|
26
27
|
)
|
|
27
|
-
from cognite_toolkit._cdf_tk.cruds._base_cruds import
|
|
28
|
-
T_ID,
|
|
29
|
-
Loader,
|
|
30
|
-
T_ResourceRequest,
|
|
31
|
-
T_ResourceRequestList,
|
|
32
|
-
T_ResourceResponse,
|
|
33
|
-
T_ResourceResponseList,
|
|
34
|
-
)
|
|
28
|
+
from cognite_toolkit._cdf_tk.cruds._base_cruds import Loader
|
|
35
29
|
from cognite_toolkit._cdf_tk.data_classes import (
|
|
36
30
|
BuildEnvironment,
|
|
37
31
|
DeployResults,
|
|
@@ -46,6 +40,7 @@ from cognite_toolkit._cdf_tk.exceptions import (
|
|
|
46
40
|
ToolkitValidationError,
|
|
47
41
|
ToolkitValueError,
|
|
48
42
|
)
|
|
43
|
+
from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
|
|
49
44
|
from cognite_toolkit._cdf_tk.tk_warnings import (
|
|
50
45
|
LowSeverityWarning,
|
|
51
46
|
MediumSeverityWarning,
|
|
@@ -57,6 +52,7 @@ from cognite_toolkit._cdf_tk.utils import (
|
|
|
57
52
|
read_yaml_file,
|
|
58
53
|
)
|
|
59
54
|
from cognite_toolkit._cdf_tk.utils.auth import EnvironmentVariables
|
|
55
|
+
from cognite_toolkit._cdf_tk.utils.useful_types import T_ID
|
|
60
56
|
|
|
61
57
|
from ._utils import _print_ids_or_length
|
|
62
58
|
|
|
@@ -66,9 +62,7 @@ AVAILABLE_DATA_TYPES: tuple[str, ...] = tuple(CRUDS_BY_FOLDER_NAME)
|
|
|
66
62
|
class CleanCommand(ToolkitCommand):
|
|
67
63
|
def clean_resources(
|
|
68
64
|
self,
|
|
69
|
-
loader: ResourceCRUD[
|
|
70
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
71
|
-
],
|
|
65
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
72
66
|
env_vars: EnvironmentVariables,
|
|
73
67
|
read_modules: list[ReadModule],
|
|
74
68
|
dry_run: bool = False,
|
|
@@ -139,7 +133,7 @@ class CleanCommand(ToolkitCommand):
|
|
|
139
133
|
return ResourceDeployResult(name=loader.display_name)
|
|
140
134
|
|
|
141
135
|
def _delete_resources(
|
|
142
|
-
self, loaded_resources:
|
|
136
|
+
self, loaded_resources: Sequence[T_ResourceResponse], loader: ResourceCRUD, dry_run: bool, verbose: bool
|
|
143
137
|
) -> int:
|
|
144
138
|
nr_of_deleted = 0
|
|
145
139
|
resource_ids = loader.get_ids(loaded_resources)
|
|
@@ -164,7 +158,11 @@ class CleanCommand(ToolkitCommand):
|
|
|
164
158
|
return nr_of_deleted
|
|
165
159
|
|
|
166
160
|
def _drop_data(
|
|
167
|
-
self,
|
|
161
|
+
self,
|
|
162
|
+
loaded_resources: Sequence[T_ResourceResponse],
|
|
163
|
+
loader: ResourceContainerCRUD,
|
|
164
|
+
dry_run: bool,
|
|
165
|
+
verbose: bool,
|
|
168
166
|
) -> int:
|
|
169
167
|
nr_of_dropped = 0
|
|
170
168
|
resource_ids = loader.get_ids(loaded_resources)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from collections.abc import Hashable
|
|
1
|
+
from collections.abc import Hashable, Sequence
|
|
2
2
|
from graphlib import TopologicalSorter
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import overload
|
|
@@ -46,9 +46,7 @@ from cognite_toolkit._cdf_tk.exceptions import (
|
|
|
46
46
|
)
|
|
47
47
|
from cognite_toolkit._cdf_tk.protocols import (
|
|
48
48
|
T_ResourceRequest,
|
|
49
|
-
T_ResourceRequestList,
|
|
50
49
|
T_ResourceResponse,
|
|
51
|
-
T_ResourceResponseList,
|
|
52
50
|
)
|
|
53
51
|
from cognite_toolkit._cdf_tk.tk_warnings import EnvironmentVariableMissingWarning
|
|
54
52
|
from cognite_toolkit._cdf_tk.tk_warnings.base import WarningList, catch_warnings
|
|
@@ -338,9 +336,7 @@ class DeployCommand(ToolkitCommand):
|
|
|
338
336
|
|
|
339
337
|
def deploy_resource_type(
|
|
340
338
|
self,
|
|
341
|
-
loader: ResourceCRUD[
|
|
342
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
343
|
-
],
|
|
339
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
344
340
|
env_vars: EnvironmentVariables,
|
|
345
341
|
read_modules: list[ReadModule] | None = None,
|
|
346
342
|
dry_run: bool = False,
|
|
@@ -402,10 +398,8 @@ class DeployCommand(ToolkitCommand):
|
|
|
402
398
|
|
|
403
399
|
def actual_deploy(
|
|
404
400
|
self,
|
|
405
|
-
resources: CategorizedResources[T_ID,
|
|
406
|
-
loader: ResourceCRUD[
|
|
407
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
408
|
-
],
|
|
401
|
+
resources: CategorizedResources[T_ID, T_ResourceRequest],
|
|
402
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
409
403
|
env_var_warnings: WarningList | None = None,
|
|
410
404
|
) -> ResourceDeployResult:
|
|
411
405
|
environment_variable_warning_by_id = {
|
|
@@ -436,10 +430,8 @@ class DeployCommand(ToolkitCommand):
|
|
|
436
430
|
|
|
437
431
|
@staticmethod
|
|
438
432
|
def dry_run_deploy(
|
|
439
|
-
resources: CategorizedResources[T_ID,
|
|
440
|
-
loader: ResourceCRUD[
|
|
441
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
442
|
-
],
|
|
433
|
+
resources: CategorizedResources[T_ID, T_ResourceRequest],
|
|
434
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
443
435
|
has_done_drop: bool,
|
|
444
436
|
has_dropped_data: bool,
|
|
445
437
|
) -> ResourceDeployResult:
|
|
@@ -470,7 +462,7 @@ class DeployCommand(ToolkitCommand):
|
|
|
470
462
|
|
|
471
463
|
@staticmethod
|
|
472
464
|
def _verbose_print(
|
|
473
|
-
resources: CategorizedResources[T_ID,
|
|
465
|
+
resources: CategorizedResources[T_ID, T_ResourceRequest],
|
|
474
466
|
loader: ResourceCRUD,
|
|
475
467
|
dry_run: bool,
|
|
476
468
|
) -> None:
|
|
@@ -494,7 +486,7 @@ class DeployCommand(ToolkitCommand):
|
|
|
494
486
|
|
|
495
487
|
def _create_resources(
|
|
496
488
|
self,
|
|
497
|
-
resources:
|
|
489
|
+
resources: Sequence[T_ResourceRequest],
|
|
498
490
|
loader: ResourceCRUD,
|
|
499
491
|
environment_variable_warning_by_id: dict[Hashable, EnvironmentVariableMissingWarning],
|
|
500
492
|
) -> int:
|
|
@@ -517,7 +509,7 @@ class DeployCommand(ToolkitCommand):
|
|
|
517
509
|
|
|
518
510
|
def _update_resources(
|
|
519
511
|
self,
|
|
520
|
-
resources:
|
|
512
|
+
resources: Sequence[T_ResourceRequest],
|
|
521
513
|
loader: ResourceCRUD,
|
|
522
514
|
environment_variable_warning_by_id: dict[Hashable, EnvironmentVariableMissingWarning],
|
|
523
515
|
) -> int:
|
|
@@ -3,7 +3,7 @@ import json
|
|
|
3
3
|
import zipfile
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from collections import defaultdict
|
|
6
|
-
from collections.abc import Hashable, Iterable, Iterator
|
|
6
|
+
from collections.abc import Hashable, Iterable, Iterator, Sequence
|
|
7
7
|
from functools import cached_property
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import Generic, cast
|
|
@@ -22,6 +22,7 @@ from cognite.client.data_classes import (
|
|
|
22
22
|
filters,
|
|
23
23
|
)
|
|
24
24
|
from cognite.client.data_classes._base import (
|
|
25
|
+
CogniteResource,
|
|
25
26
|
CogniteResourceList,
|
|
26
27
|
)
|
|
27
28
|
from cognite.client.data_classes.agents import (
|
|
@@ -113,7 +114,7 @@ class ResourceFinder(Iterable, ABC, Generic[T_ID]):
|
|
|
113
114
|
raise NotImplementedError
|
|
114
115
|
|
|
115
116
|
# Can be implemented in subclasses
|
|
116
|
-
def update(self, resources:
|
|
117
|
+
def update(self, resources: Sequence[CogniteResource]) -> None: ...
|
|
117
118
|
|
|
118
119
|
|
|
119
120
|
class DataModelFinder(ResourceFinder[DataModelId]):
|
|
@@ -178,7 +179,7 @@ class DataModelFinder(ResourceFinder[DataModelId]):
|
|
|
178
179
|
self.data_model = models_by_version[selected_model]
|
|
179
180
|
return self.data_model.as_id()
|
|
180
181
|
|
|
181
|
-
def update(self, resources:
|
|
182
|
+
def update(self, resources: Sequence[CogniteResource]) -> None:
|
|
182
183
|
if isinstance(resources, dm.DataModelList):
|
|
183
184
|
self.view_ids |= {
|
|
184
185
|
view.as_id() if isinstance(view, dm.View) else view for item in resources for view in item.views
|
|
@@ -187,7 +188,7 @@ class DataModelFinder(ResourceFinder[DataModelId]):
|
|
|
187
188
|
self.container_ids |= resources.referenced_containers()
|
|
188
189
|
elif isinstance(resources, dm.SpaceList):
|
|
189
190
|
return
|
|
190
|
-
self.space_ids |= {item.space for item in resources}
|
|
191
|
+
self.space_ids |= {item.space for item in resources if hasattr(item, "space")}
|
|
191
192
|
|
|
192
193
|
def __iter__(self) -> Iterator[tuple[list[Hashable], CogniteResourceList | None, ResourceCRUD, None | str]]:
|
|
193
194
|
self.identifier = self._selected()
|
|
@@ -804,6 +805,7 @@ class DumpResourceCommand(ToolkitCommand):
|
|
|
804
805
|
output_dir.mkdir(exist_ok=True)
|
|
805
806
|
|
|
806
807
|
dumped_ids: list[Hashable] = []
|
|
808
|
+
resources: Sequence[CogniteResource] | None = None
|
|
807
809
|
for identifiers, resources, loader, subfolder in finder:
|
|
808
810
|
if not identifiers and not resources:
|
|
809
811
|
# No resources to dump
|
|
@@ -29,13 +29,6 @@ from cognite_toolkit._cdf_tk.cruds import (
|
|
|
29
29
|
ResourceCRUD,
|
|
30
30
|
StreamlitCRUD,
|
|
31
31
|
)
|
|
32
|
-
from cognite_toolkit._cdf_tk.cruds._base_cruds import (
|
|
33
|
-
T_ID,
|
|
34
|
-
T_ResourceRequest,
|
|
35
|
-
T_ResourceRequestList,
|
|
36
|
-
T_ResourceResponse,
|
|
37
|
-
T_ResourceResponseList,
|
|
38
|
-
)
|
|
39
32
|
from cognite_toolkit._cdf_tk.data_classes import (
|
|
40
33
|
BuildEnvironment,
|
|
41
34
|
BuildVariable,
|
|
@@ -49,6 +42,7 @@ from cognite_toolkit._cdf_tk.data_classes import (
|
|
|
49
42
|
YAMLComments,
|
|
50
43
|
)
|
|
51
44
|
from cognite_toolkit._cdf_tk.exceptions import ToolkitError, ToolkitMissingResourceError, ToolkitValueError
|
|
45
|
+
from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
|
|
52
46
|
from cognite_toolkit._cdf_tk.tk_warnings import LowSeverityWarning, MediumSeverityWarning
|
|
53
47
|
from cognite_toolkit._cdf_tk.utils import (
|
|
54
48
|
YAMLComment,
|
|
@@ -64,6 +58,7 @@ from cognite_toolkit._cdf_tk.utils.modules import (
|
|
|
64
58
|
module_directory_from_path,
|
|
65
59
|
parse_user_selected_modules,
|
|
66
60
|
)
|
|
61
|
+
from cognite_toolkit._cdf_tk.utils.useful_types import T_ID
|
|
67
62
|
|
|
68
63
|
from ._base import ToolkitCommand
|
|
69
64
|
from .build_cmd import BuildCommand
|
|
@@ -547,9 +542,7 @@ class PullCommand(ToolkitCommand):
|
|
|
547
542
|
|
|
548
543
|
def _pull_resources(
|
|
549
544
|
self,
|
|
550
|
-
loader: ResourceCRUD[
|
|
551
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
552
|
-
],
|
|
545
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
553
546
|
resources: BuiltFullResourceList[T_ID],
|
|
554
547
|
dry_run: bool,
|
|
555
548
|
environment_variables: dict[str, str | None],
|
|
@@ -581,9 +574,7 @@ class PullCommand(ToolkitCommand):
|
|
|
581
574
|
local_resource_by_id: dict[T_ID, dict[str, Any]],
|
|
582
575
|
cdf_resource_by_id: dict[T_ID, T_ResourceResponse],
|
|
583
576
|
file_results: ResourceDeployResult,
|
|
584
|
-
loader: ResourceCRUD[
|
|
585
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
586
|
-
],
|
|
577
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
587
578
|
) -> tuple[bool, dict[T_ID, dict[str, Any]]]:
|
|
588
579
|
to_write: dict[T_ID, dict[str, Any]] = {}
|
|
589
580
|
has_changes = False
|
|
@@ -612,9 +603,7 @@ class PullCommand(ToolkitCommand):
|
|
|
612
603
|
@staticmethod
|
|
613
604
|
def _get_local_resource_dict_by_id(
|
|
614
605
|
resources: BuiltFullResourceList[T_ID],
|
|
615
|
-
loader: ResourceCRUD[
|
|
616
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
617
|
-
],
|
|
606
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
618
607
|
environment_variables: dict[str, str | None],
|
|
619
608
|
) -> dict[T_ID, dict[str, Any]]:
|
|
620
609
|
unique_destinations = {r.destination for r in resources if r.destination}
|
|
@@ -651,9 +640,7 @@ class PullCommand(ToolkitCommand):
|
|
|
651
640
|
to_write: dict[T_ID, dict[str, Any]],
|
|
652
641
|
resources: BuiltFullResourceList[T_ID],
|
|
653
642
|
environment_variables: dict[str, str | None],
|
|
654
|
-
loader: ResourceCRUD[
|
|
655
|
-
T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList
|
|
656
|
-
],
|
|
643
|
+
loader: ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse],
|
|
657
644
|
source_file: Path,
|
|
658
645
|
) -> tuple[str, dict[Path, str]]:
|
|
659
646
|
# 1. Replace all variables with placeholders
|
|
@@ -10,12 +10,7 @@ from rich.console import Console
|
|
|
10
10
|
|
|
11
11
|
from cognite_toolkit._cdf_tk.client import ToolkitClient
|
|
12
12
|
from cognite_toolkit._cdf_tk.constants import BUILD_FOLDER_ENCODING, EXCL_FILES
|
|
13
|
-
from cognite_toolkit._cdf_tk.protocols import
|
|
14
|
-
T_ResourceRequest,
|
|
15
|
-
T_ResourceRequestList,
|
|
16
|
-
T_ResourceResponse,
|
|
17
|
-
T_ResourceResponseList,
|
|
18
|
-
)
|
|
13
|
+
from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
|
|
19
14
|
from cognite_toolkit._cdf_tk.resource_classes import ToolkitResource
|
|
20
15
|
from cognite_toolkit._cdf_tk.tk_warnings import ToolkitWarning
|
|
21
16
|
from cognite_toolkit._cdf_tk.utils import load_yaml_inject_variables, safe_read, sanitize_filename
|
|
@@ -133,11 +128,7 @@ class Loader(ABC):
|
|
|
133
128
|
T_Loader = TypeVar("T_Loader", bound=Loader)
|
|
134
129
|
|
|
135
130
|
|
|
136
|
-
class ResourceCRUD(
|
|
137
|
-
Loader,
|
|
138
|
-
ABC,
|
|
139
|
-
Generic[T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList],
|
|
140
|
-
):
|
|
131
|
+
class ResourceCRUD(Loader, ABC, Generic[T_ID, T_ResourceRequest, T_ResourceResponse]):
|
|
141
132
|
"""This is the base class for all resource CRUD.
|
|
142
133
|
|
|
143
134
|
A resource loader consists of the following
|
|
@@ -150,8 +141,6 @@ class ResourceCRUD(
|
|
|
150
141
|
Class attributes:
|
|
151
142
|
resource_write_cls: The API write data class for the resource.
|
|
152
143
|
resource_cls: The API read data class for the resource.
|
|
153
|
-
list_cls: The API read list format for this resource.
|
|
154
|
-
list_write_cls: The API write list format for this resource.
|
|
155
144
|
yaml_cls: The File format for this resource. This is used to validate the user input.
|
|
156
145
|
support_drop: Whether the resource supports the drop flag.
|
|
157
146
|
support_update: Whether the resource supports the update operation.
|
|
@@ -165,8 +154,6 @@ class ResourceCRUD(
|
|
|
165
154
|
# Must be set in the subclass
|
|
166
155
|
resource_write_cls: type[T_ResourceRequest]
|
|
167
156
|
resource_cls: type[T_ResourceResponse]
|
|
168
|
-
list_cls: type[T_ResourceResponseList]
|
|
169
|
-
list_write_cls: type[T_ResourceRequestList]
|
|
170
157
|
yaml_cls: type[ToolkitResource]
|
|
171
158
|
# Optional to set in the subclass
|
|
172
159
|
support_drop = True
|
|
@@ -197,14 +184,14 @@ class ResourceCRUD(
|
|
|
197
184
|
raise NotImplementedError(f"get_required_capability must be implemented for {cls.__name__}.")
|
|
198
185
|
|
|
199
186
|
@abstractmethod
|
|
200
|
-
def create(self, items:
|
|
187
|
+
def create(self, items: Sequence[T_ResourceRequest]) -> Sized:
|
|
201
188
|
raise NotImplementedError
|
|
202
189
|
|
|
203
190
|
@abstractmethod
|
|
204
|
-
def retrieve(self, ids: SequenceNotStr[T_ID]) ->
|
|
191
|
+
def retrieve(self, ids: SequenceNotStr[T_ID]) -> Sequence[T_ResourceResponse]:
|
|
205
192
|
raise NotImplementedError
|
|
206
193
|
|
|
207
|
-
def update(self, items:
|
|
194
|
+
def update(self, items: Sequence[T_ResourceRequest]) -> Sized:
|
|
208
195
|
raise NotImplementedError(f"Update is not supported for {type(self).__name__}.")
|
|
209
196
|
|
|
210
197
|
@abstractmethod
|
|
@@ -390,9 +377,7 @@ class ResourceCRUD(
|
|
|
390
377
|
|
|
391
378
|
# Helper methods
|
|
392
379
|
@classmethod
|
|
393
|
-
def get_ids(
|
|
394
|
-
cls, items: Sequence[T_ResourceRequest | T_ResourceResponse | dict] | T_ResourceResponseList
|
|
395
|
-
) -> list[T_ID]:
|
|
380
|
+
def get_ids(cls, items: Sequence[T_ResourceRequest | T_ResourceResponse | dict]) -> list[T_ID]:
|
|
396
381
|
return [cls.get_id(item) for item in items]
|
|
397
382
|
|
|
398
383
|
@classmethod
|
|
@@ -404,10 +389,7 @@ class ResourceCRUD(
|
|
|
404
389
|
)
|
|
405
390
|
|
|
406
391
|
|
|
407
|
-
class ResourceContainerCRUD(
|
|
408
|
-
ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList],
|
|
409
|
-
ABC,
|
|
410
|
-
):
|
|
392
|
+
class ResourceContainerCRUD(ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse], ABC):
|
|
411
393
|
"""This is the base class for all resource CRUD' containers.
|
|
412
394
|
|
|
413
395
|
A resource container CRUD is a resource that contains data. For example, Timeseries contains datapoints, and another
|
|
@@ -11,9 +11,7 @@ from cognite_toolkit._cdf_tk.client.data_classes.raw import RawTable
|
|
|
11
11
|
from cognite_toolkit._cdf_tk.constants import BUILD_FOLDER_ENCODING
|
|
12
12
|
from cognite_toolkit._cdf_tk.protocols import (
|
|
13
13
|
T_ResourceRequest,
|
|
14
|
-
T_ResourceRequestList,
|
|
15
14
|
T_ResourceResponse,
|
|
16
|
-
T_ResourceResponseList,
|
|
17
15
|
)
|
|
18
16
|
from cognite_toolkit._cdf_tk.utils import read_yaml_content, safe_read
|
|
19
17
|
from cognite_toolkit._cdf_tk.utils.file import read_csv
|
|
@@ -131,17 +129,16 @@ class FileCRUD(DataCRUD):
|
|
|
131
129
|
@staticmethod
|
|
132
130
|
def _read_metadata(
|
|
133
131
|
destination: Path,
|
|
134
|
-
loader: type[
|
|
135
|
-
ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse, T_ResourceRequestList, T_ResourceResponseList]
|
|
136
|
-
],
|
|
132
|
+
loader: type[ResourceCRUD[T_ID, T_ResourceRequest, T_ResourceResponse]],
|
|
137
133
|
identifier: T_ID,
|
|
138
134
|
) -> T_ResourceRequest:
|
|
139
135
|
built_content = read_yaml_content(safe_read(destination, encoding=BUILD_FOLDER_ENCODING))
|
|
140
136
|
if isinstance(built_content, dict):
|
|
141
137
|
return loader.resource_write_cls._load(built_content)
|
|
142
138
|
elif isinstance(built_content, list):
|
|
139
|
+
write_resources = (loader.resource_write_cls._load(content) for content in built_content)
|
|
143
140
|
try:
|
|
144
|
-
return next(m for m in
|
|
141
|
+
return next(m for m in write_resources if loader.get_id(m) == identifier)
|
|
145
142
|
except StopIteration:
|
|
146
143
|
raise RuntimeError(f"Missing metadata for {destination.as_posix()}")
|
|
147
144
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from collections.abc import Hashable, Iterable, Sequence
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from cognite.client.data_classes.agents import Agent, AgentList, AgentUpsert
|
|
4
|
+
from cognite.client.data_classes.agents import Agent, AgentList, AgentUpsert
|
|
5
5
|
from cognite.client.data_classes.capabilities import AgentsAcl, Capability
|
|
6
6
|
from cognite.client.exceptions import CogniteAPIError
|
|
7
7
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
@@ -11,12 +11,10 @@ from cognite_toolkit._cdf_tk.resource_classes import AgentYAML
|
|
|
11
11
|
from cognite_toolkit._cdf_tk.utils.diff_list import diff_list_hashable, diff_list_identifiable
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class AgentCRUD(ResourceCRUD[str, AgentUpsert, Agent
|
|
14
|
+
class AgentCRUD(ResourceCRUD[str, AgentUpsert, Agent]):
|
|
15
15
|
folder_name = "agents"
|
|
16
16
|
resource_cls = Agent
|
|
17
17
|
resource_write_cls = AgentUpsert
|
|
18
|
-
list_cls = AgentList
|
|
19
|
-
list_write_cls = AgentUpsertList
|
|
20
18
|
kind = "Agent"
|
|
21
19
|
yaml_cls = AgentYAML
|
|
22
20
|
_doc_base_url = ""
|
|
@@ -43,13 +41,13 @@ class AgentCRUD(ResourceCRUD[str, AgentUpsert, Agent, AgentUpsertList, AgentList
|
|
|
43
41
|
|
|
44
42
|
return AgentsAcl(actions, AgentsAcl.Scope.All())
|
|
45
43
|
|
|
46
|
-
def create(self, items:
|
|
44
|
+
def create(self, items: Sequence[AgentUpsert]) -> AgentList:
|
|
47
45
|
return self.client.agents.upsert(items)
|
|
48
46
|
|
|
49
47
|
def retrieve(self, ids: SequenceNotStr[str]) -> AgentList:
|
|
50
48
|
return self.client.agents.retrieve(ids, ignore_unknown_ids=True)
|
|
51
49
|
|
|
52
|
-
def update(self, items:
|
|
50
|
+
def update(self, items: Sequence[AgentUpsert]) -> AgentList:
|
|
53
51
|
return self.client.agents.upsert(items)
|
|
54
52
|
|
|
55
53
|
def delete(self, ids: SequenceNotStr[str]) -> int:
|
|
@@ -30,11 +30,9 @@ from cognite.client.data_classes.iam import (
|
|
|
30
30
|
Group,
|
|
31
31
|
GroupList,
|
|
32
32
|
GroupWrite,
|
|
33
|
-
GroupWriteList,
|
|
34
33
|
SecurityCategory,
|
|
35
34
|
SecurityCategoryList,
|
|
36
35
|
SecurityCategoryWrite,
|
|
37
|
-
SecurityCategoryWriteList,
|
|
38
36
|
)
|
|
39
37
|
from cognite.client.exceptions import CogniteAPIError, CogniteNotFoundError
|
|
40
38
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
@@ -65,13 +63,11 @@ class _ReplaceMethod:
|
|
|
65
63
|
id_name: str
|
|
66
64
|
|
|
67
65
|
|
|
68
|
-
class GroupCRUD(ResourceCRUD[str, GroupWrite, Group
|
|
66
|
+
class GroupCRUD(ResourceCRUD[str, GroupWrite, Group]):
|
|
69
67
|
folder_name = "auth"
|
|
70
68
|
kind = "Group"
|
|
71
69
|
resource_cls = Group
|
|
72
70
|
resource_write_cls = GroupWrite
|
|
73
|
-
list_cls = GroupList
|
|
74
|
-
list_write_cls = GroupWriteList
|
|
75
71
|
yaml_cls = GroupYAML
|
|
76
72
|
resource_scopes = frozenset(
|
|
77
73
|
{
|
|
@@ -478,13 +474,9 @@ class GroupAllScopedCRUD(GroupCRUD):
|
|
|
478
474
|
|
|
479
475
|
|
|
480
476
|
@final
|
|
481
|
-
class SecurityCategoryCRUD(
|
|
482
|
-
ResourceCRUD[str, SecurityCategoryWrite, SecurityCategory, SecurityCategoryWriteList, SecurityCategoryList]
|
|
483
|
-
):
|
|
477
|
+
class SecurityCategoryCRUD(ResourceCRUD[str, SecurityCategoryWrite, SecurityCategory]):
|
|
484
478
|
resource_cls = SecurityCategory
|
|
485
479
|
resource_write_cls = SecurityCategoryWrite
|
|
486
|
-
list_cls = SecurityCategoryList
|
|
487
|
-
list_write_cls = SecurityCategoryWriteList
|
|
488
480
|
kind = "SecurityCategory"
|
|
489
481
|
yaml_cls = SecurityCategoriesYAML
|
|
490
482
|
folder_name = "auth"
|
|
@@ -532,7 +524,7 @@ class SecurityCategoryCRUD(
|
|
|
532
524
|
SecurityCategoriesAcl.Scope.All(),
|
|
533
525
|
)
|
|
534
526
|
|
|
535
|
-
def create(self, items:
|
|
527
|
+
def create(self, items: Sequence[SecurityCategoryWrite]) -> SecurityCategoryList:
|
|
536
528
|
return self.client.iam.security_categories.create(items)
|
|
537
529
|
|
|
538
530
|
def retrieve(self, ids: SequenceNotStr[str]) -> SecurityCategoryList:
|
|
@@ -540,7 +532,7 @@ class SecurityCategoryCRUD(
|
|
|
540
532
|
categories = self.client.iam.security_categories.list(limit=-1)
|
|
541
533
|
return SecurityCategoryList([c for c in categories if c.name in names])
|
|
542
534
|
|
|
543
|
-
def update(self, items:
|
|
535
|
+
def update(self, items: Sequence[SecurityCategoryWrite]) -> SecurityCategoryList:
|
|
544
536
|
items_by_name = {item.name: item for item in items}
|
|
545
537
|
retrieved = self.retrieve(list(items_by_name.keys()))
|
|
546
538
|
retrieved_by_name = {item.name: item for item in retrieved}
|