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,25 +1,68 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Generic
2
+ from collections import defaultdict
3
+ from collections.abc import Callable, Sequence
4
+ from typing import Generic, Literal, cast
5
+ from uuid import uuid4
3
6
 
4
- from cognite.client.data_classes._base import (
5
- T_CogniteResource,
7
+ from cognite.client.data_classes.data_modeling import (
8
+ EdgeApply,
9
+ InstanceApply,
10
+ NodeApply,
11
+ NodeId,
12
+ View,
13
+ ViewId,
6
14
  )
7
- from cognite.client.data_classes.data_modeling import DirectRelationReference, InstanceApply, View, ViewId
15
+ from cognite.client.exceptions import CogniteException
8
16
 
9
17
  from cognite_toolkit._cdf_tk.client import ToolkitClient
10
- from cognite_toolkit._cdf_tk.client.data_classes.migration import ResourceViewMapping
11
- from cognite_toolkit._cdf_tk.commands._migrate.conversion import asset_centric_to_dm
12
- from cognite_toolkit._cdf_tk.commands._migrate.data_classes import AssetCentricMapping
13
- from cognite_toolkit._cdf_tk.commands._migrate.issues import ConversionIssue, MigrationIssue
14
- from cognite_toolkit._cdf_tk.commands._migrate.selectors import AssetCentricMigrationSelector
18
+ from cognite_toolkit._cdf_tk.client.data_classes.charts_data import (
19
+ ChartCoreTimeseries,
20
+ ChartSource,
21
+ ChartTimeseries,
22
+ )
23
+ from cognite_toolkit._cdf_tk.client.data_classes.instance_api import InstanceIdentifier
24
+ from cognite_toolkit._cdf_tk.client.data_classes.legacy.canvas import (
25
+ ContainerReferenceApply,
26
+ FdmInstanceContainerReferenceApply,
27
+ IndustrialCanvas,
28
+ IndustrialCanvasApply,
29
+ )
30
+ from cognite_toolkit._cdf_tk.client.data_classes.legacy.charts import Chart, ChartWrite
31
+ from cognite_toolkit._cdf_tk.client.data_classes.legacy.migration import ResourceViewMappingApply
32
+ from cognite_toolkit._cdf_tk.client.data_classes.three_d import (
33
+ AssetMappingDMRequest,
34
+ AssetMappingResponse,
35
+ NodeReference,
36
+ RevisionStatus,
37
+ ThreeDModelResponse,
38
+ )
39
+ from cognite_toolkit._cdf_tk.commands._migrate.conversion import DirectRelationCache, asset_centric_to_dm
40
+ from cognite_toolkit._cdf_tk.commands._migrate.data_classes import (
41
+ Model,
42
+ ThreeDMigrationRequest,
43
+ ThreeDRevisionMigrationRequest,
44
+ )
45
+ from cognite_toolkit._cdf_tk.commands._migrate.default_mappings import create_default_mappings
46
+ from cognite_toolkit._cdf_tk.commands._migrate.issues import (
47
+ CanvasMigrationIssue,
48
+ ChartMigrationIssue,
49
+ ConversionIssue,
50
+ MigrationIssue,
51
+ ThreeDModelMigrationIssue,
52
+ )
15
53
  from cognite_toolkit._cdf_tk.constants import MISSING_INSTANCE_SPACE
16
- from cognite_toolkit._cdf_tk.exceptions import ToolkitValueError
17
- from cognite_toolkit._cdf_tk.storageio._base import T_Selector, T_WriteCogniteResource
54
+ from cognite_toolkit._cdf_tk.exceptions import ToolkitMigrationError, ToolkitValueError
55
+ from cognite_toolkit._cdf_tk.protocols import T_ResourceRequest, T_ResourceResponse
56
+ from cognite_toolkit._cdf_tk.storageio._base import T_Selector
57
+ from cognite_toolkit._cdf_tk.storageio.selectors import CanvasSelector, ChartSelector, ThreeDSelector
18
58
  from cognite_toolkit._cdf_tk.utils import humanize_collection
19
- from cognite_toolkit._cdf_tk.utils.useful_types import T_AssetCentricResource
59
+ from cognite_toolkit._cdf_tk.utils.useful_types import T_AssetCentricResourceExtended
20
60
 
61
+ from .data_classes import AssetCentricMapping
62
+ from .selectors import AssetCentricMigrationSelector
21
63
 
22
- class DataMapper(Generic[T_Selector, T_CogniteResource, T_WriteCogniteResource], ABC):
64
+
65
+ class DataMapper(Generic[T_Selector, T_ResourceResponse, T_ResourceRequest], ABC):
23
66
  def prepare(self, source_selector: T_Selector) -> None:
24
67
  """Prepare the data mapper with the given source selector.
25
68
 
@@ -31,7 +74,7 @@ class DataMapper(Generic[T_Selector, T_CogniteResource, T_WriteCogniteResource],
31
74
  pass
32
75
 
33
76
  @abstractmethod
34
- def map(self, source: T_CogniteResource) -> tuple[T_WriteCogniteResource | None, MigrationIssue]:
77
+ def map(self, source: Sequence[T_ResourceResponse]) -> Sequence[tuple[T_ResourceRequest | None, MigrationIssue]]:
35
78
  """Map a chunk of source data to the target format.
36
79
 
37
80
  Args:
@@ -45,28 +88,27 @@ class DataMapper(Generic[T_Selector, T_CogniteResource, T_WriteCogniteResource],
45
88
 
46
89
 
47
90
  class AssetCentricMapper(
48
- DataMapper[AssetCentricMigrationSelector, AssetCentricMapping[T_AssetCentricResource], InstanceApply]
91
+ DataMapper[AssetCentricMigrationSelector, AssetCentricMapping[T_AssetCentricResourceExtended], InstanceApply]
49
92
  ):
50
93
  def __init__(self, client: ToolkitClient) -> None:
51
94
  self.client = client
52
95
  self._ingestion_view_by_id: dict[ViewId, View] = {}
53
- self._view_mapping_by_id: dict[str, ResourceViewMapping] = {}
54
- # This is used to keep track of already mapped assets, such that we can creat direct relations
55
- # to them from files, events, and time series.
56
- self._asset_mapping_by_id: dict[int, DirectRelationReference] = {}
57
- self._source_system_mapping_by_id: dict[str, DirectRelationReference] = {}
96
+ self._view_mapping_by_id: dict[str, ResourceViewMappingApply] = {}
97
+ self._direct_relation_cache = DirectRelationCache(client)
58
98
 
59
99
  def prepare(self, source_selector: AssetCentricMigrationSelector) -> None:
60
100
  ingestion_view_ids = source_selector.get_ingestion_mappings()
61
101
  ingestion_views = self.client.migration.resource_view_mapping.retrieve(ingestion_view_ids)
62
- self._view_mapping_by_id = {view.external_id: view for view in ingestion_views}
102
+ defaults = {mapping.external_id: mapping for mapping in create_default_mappings()}
103
+ # Custom mappings from CDF override the default mappings
104
+ self._view_mapping_by_id = defaults | {view.external_id: view.as_write() for view in ingestion_views}
63
105
  missing_mappings = set(ingestion_view_ids) - set(self._view_mapping_by_id.keys())
64
106
  if missing_mappings:
65
107
  raise ToolkitValueError(
66
108
  f"The following ingestion views were not found: {humanize_collection(missing_mappings)}"
67
109
  )
68
110
 
69
- view_ids = list({view.view_id for view in ingestion_views})
111
+ view_ids = list({mapping.view_id for mapping in self._view_mapping_by_id.values()})
70
112
  views = self.client.data_modeling.views.retrieve(view_ids)
71
113
  self._ingestion_view_by_id = {view.as_id(): view for view in views}
72
114
  missing_views = set(view_ids) - set(self._ingestion_view_by_id.keys())
@@ -74,22 +116,23 @@ class AssetCentricMapper(
74
116
  raise ToolkitValueError(
75
117
  f"The following ingestion views were not found in Data Modeling: {humanize_collection(missing_views)}"
76
118
  )
77
- # We just look-up all source system for now. This can be optimized to only
78
- # look-up the ones that are actually used in the ingestion views. However, SourceSystem is typically in
79
- # the order ~10 instances, so this is not a big deal for now. See task CDF-25974.
80
- source_systems = self.client.migration.created_source_system.list(limit=-1)
81
- self._source_system_mapping_by_id = {
82
- source_system.source: source_system.as_direct_relation_reference() for source_system in source_systems
83
- }
84
-
85
- # We look-up all existing asset mappings to be able to create direct relations to already mapped assets.
86
- # This is needed in case the migration is run multiple times, or if assets are mapped
87
- asset_mappings = self.client.migration.instance_source.list(resource_type="asset", limit=-1)
88
- self._asset_mapping_by_id = {mapping.id_: mapping.as_direct_relation_reference() for mapping in asset_mappings}
89
119
 
90
- def map(self, source: AssetCentricMapping[T_AssetCentricResource]) -> tuple[InstanceApply | None, ConversionIssue]:
120
+ def map(
121
+ self, source: Sequence[AssetCentricMapping[T_AssetCentricResourceExtended]]
122
+ ) -> Sequence[tuple[InstanceApply | None, ConversionIssue]]:
91
123
  """Map a chunk of asset-centric data to InstanceApplyList format."""
92
- mapping = source.mapping
124
+ # We update the direct relation cache in bulk for all resources in the chunk.
125
+ self._direct_relation_cache.update(item.resource for item in source)
126
+ output: list[tuple[InstanceApply | None, ConversionIssue]] = []
127
+ for item in source:
128
+ instance, conversion_issue = self._map_single_item(item)
129
+ output.append((instance, conversion_issue))
130
+ return output
131
+
132
+ def _map_single_item(
133
+ self, item: AssetCentricMapping[T_AssetCentricResourceExtended]
134
+ ) -> tuple[NodeApply | EdgeApply | None, ConversionIssue]:
135
+ mapping = item.mapping
93
136
  ingestion_view = mapping.get_ingestion_view()
94
137
  try:
95
138
  view_source = self._view_mapping_by_id[ingestion_view]
@@ -99,19 +142,379 @@ class AssetCentricMapper(
99
142
  f"Failed to lookup mapping or view for ingestion view '{ingestion_view}'. Did you forget to call .prepare()?"
100
143
  ) from e
101
144
  instance, conversion_issue = asset_centric_to_dm(
102
- source.resource,
145
+ item.resource,
103
146
  instance_id=mapping.instance_id,
104
147
  view_source=view_source,
105
148
  view_properties=view_properties,
106
- asset_instance_id_by_id=self._asset_mapping_by_id,
107
- source_instance_id_by_external_id=self._source_system_mapping_by_id,
108
- file_instance_id_by_id={}, # Todo implement file direct relations
149
+ direct_relation_cache=self._direct_relation_cache,
150
+ preferred_consumer_view=mapping.preferred_consumer_view,
109
151
  )
110
152
  if mapping.instance_id.space == MISSING_INSTANCE_SPACE:
111
153
  conversion_issue.missing_instance_space = f"Missing instance space for dataset ID {mapping.data_set_id!r}"
112
-
113
- if mapping.resource_type == "asset":
114
- self._asset_mapping_by_id[mapping.id] = DirectRelationReference(
115
- space=mapping.instance_id.space, external_id=mapping.instance_id.external_id
116
- )
117
154
  return instance, conversion_issue
155
+
156
+
157
+ class ChartMapper(DataMapper[ChartSelector, Chart, ChartWrite]):
158
+ def __init__(self, client: ToolkitClient) -> None:
159
+ self.client = client
160
+
161
+ def map(self, source: Sequence[Chart]) -> Sequence[tuple[ChartWrite | None, MigrationIssue]]:
162
+ self._populate_cache(source)
163
+ output: list[tuple[ChartWrite | None, MigrationIssue]] = []
164
+ for item in source:
165
+ mapped_item, issue = self._map_single_item(item)
166
+ output.append((mapped_item, issue))
167
+ return output
168
+
169
+ def _populate_cache(self, source: Sequence[Chart]) -> None:
170
+ """Populate the internal cache with timeseries from the source charts.
171
+
172
+ Note that the consumption views are also cached as part of the timeseries lookup.
173
+ """
174
+ timeseries_ids: set[int] = set()
175
+ timeseries_external_ids: set[str] = set()
176
+ for chart in source:
177
+ for item in chart.data.time_series_collection or []:
178
+ if item.ts_id:
179
+ timeseries_ids.add(item.ts_id)
180
+ if item.ts_external_id:
181
+ timeseries_external_ids.add(item.ts_external_id)
182
+ if timeseries_ids:
183
+ self.client.migration.lookup.time_series(list(timeseries_ids))
184
+ if timeseries_external_ids:
185
+ self.client.migration.lookup.time_series(external_id=list(timeseries_external_ids))
186
+
187
+ def _map_single_item(self, item: Chart) -> tuple[ChartWrite | None, ChartMigrationIssue]:
188
+ issue = ChartMigrationIssue(chart_external_id=item.external_id)
189
+ time_series_collection = item.data.time_series_collection or []
190
+ timeseries_core_collection = self._create_timeseries_core_collection(time_series_collection, issue)
191
+ if issue.has_issues:
192
+ return None, issue
193
+
194
+ updated_source_collection = self._update_source_collection(
195
+ item.data.source_collection or [], time_series_collection, timeseries_core_collection
196
+ )
197
+
198
+ mapped_chart = item.as_write()
199
+ mapped_chart.data.core_timeseries_collection = timeseries_core_collection
200
+ mapped_chart.data.time_series_collection = None
201
+ mapped_chart.data.source_collection = updated_source_collection
202
+ return mapped_chart, issue
203
+
204
+ def _create_timeseries_core_collection(
205
+ self, time_series_collection: list[ChartTimeseries], issue: ChartMigrationIssue
206
+ ) -> list[ChartCoreTimeseries]:
207
+ timeseries_core_collection: list[ChartCoreTimeseries] = []
208
+ for ts_item in time_series_collection or []:
209
+ node_id, consumer_view_id = self._get_node_id_consumer_view_id(ts_item)
210
+
211
+ if node_id is None:
212
+ if ts_item.ts_id is not None:
213
+ issue.missing_timeseries_ids.append(ts_item.ts_id)
214
+ elif ts_item.ts_external_id is not None:
215
+ issue.missing_timeseries_external_ids.append(ts_item.ts_external_id)
216
+ else:
217
+ issue.missing_timeseries_identifier.append(ts_item.id or "unknown")
218
+ continue
219
+
220
+ core_timeseries = self._create_new_timeseries_core(ts_item, node_id, consumer_view_id)
221
+ timeseries_core_collection.append(core_timeseries)
222
+ return timeseries_core_collection
223
+
224
+ def _create_new_timeseries_core(
225
+ self, ts_item: ChartTimeseries, node_id: NodeId, consumer_view_id: ViewId | None
226
+ ) -> ChartCoreTimeseries:
227
+ dumped = ts_item.model_dump(mode="json", by_alias=True, exclude_unset=True)
228
+ dumped["nodeReference"] = node_id
229
+ dumped["viewReference"] = consumer_view_id
230
+ new_uuid = str(uuid4())
231
+ dumped["id"] = new_uuid
232
+ dumped["type"] = "coreTimeseries"
233
+ # We ignore extra here to only include the fields that are shared between ChartTimeseries and ChartCoreTimeseries
234
+ core_timeseries = ChartCoreTimeseries.model_validate(dumped, extra="ignore")
235
+ return core_timeseries
236
+
237
+ def _get_node_id_consumer_view_id(self, ts_item: ChartTimeseries) -> tuple[NodeId | None, ViewId | None]:
238
+ """Look up the node ID and consumer view ID for a given timeseries item.
239
+
240
+ Prioritizes lookup by internal ID, then by external ID.
241
+
242
+ Args:
243
+ ts_item: The ChartTimeseries item to look up.
244
+
245
+ Returns:
246
+ A tuple containing the consumer view ID and node ID, or None if not found.
247
+ """
248
+ node_id: NodeId | None = None
249
+ consumer_view_id: ViewId | None = None
250
+ for id_name, id_value in [("id", ts_item.ts_id), ("external_id", ts_item.ts_external_id)]:
251
+ if id_value is None:
252
+ continue
253
+ arg = {id_name: id_value}
254
+ node_id = self.client.migration.lookup.time_series(**arg) # type: ignore[arg-type]
255
+ consumer_view_id = self.client.migration.lookup.time_series.consumer_view(**arg) # type: ignore[arg-type]
256
+ if node_id is not None:
257
+ break
258
+ return node_id, consumer_view_id
259
+
260
+ def _update_source_collection(
261
+ self,
262
+ source_collection: list[ChartSource],
263
+ time_series_collection: list[ChartTimeseries],
264
+ timeseries_core_collection: list[ChartCoreTimeseries],
265
+ ) -> list[ChartSource]:
266
+ remove_ids = {ts_item.id for ts_item in time_series_collection if ts_item.id is not None}
267
+ updated_source_collection = [ts_item for ts_item in source_collection if ts_item.id not in remove_ids]
268
+ for core_ts_item in timeseries_core_collection:
269
+ # We cast there two as we set them in the _create_timeseries_core_collection method
270
+ new_source_item = ChartSource(id=cast(str, core_ts_item.id), type=cast(str, core_ts_item.type))
271
+ updated_source_collection.append(new_source_item)
272
+ return updated_source_collection
273
+
274
+
275
+ class CanvasMapper(DataMapper[CanvasSelector, IndustrialCanvas, IndustrialCanvasApply]):
276
+ # Note sequences are not supported in Canvas, so we do not include them here.
277
+ asset_centric_resource_types = tuple(("asset", "event", "timeseries", "file"))
278
+ DEFAULT_ASSET_VIEW = ViewId("cdf_cdm", "CogniteAsset", "v1")
279
+ DEFAULT_EVENT_VIEW = ViewId("cdf_cdm", "CogniteActivity", "v1")
280
+ DEFAULT_FILE_VIEW = ViewId("cdf_cdm", "CogniteFile", "v1")
281
+ DEFAULT_TIMESERIES_VIEW = ViewId("cdf_cdm", "CogniteTimeSeries", "v1")
282
+
283
+ def __init__(self, client: ToolkitClient, dry_run: bool, skip_on_missing_ref: bool = False) -> None:
284
+ self.client = client
285
+ self.dry_run = dry_run
286
+ self.skip_on_missing_ref = skip_on_missing_ref
287
+
288
+ def map(self, source: Sequence[IndustrialCanvas]) -> Sequence[tuple[IndustrialCanvasApply | None, MigrationIssue]]:
289
+ self._populate_cache(source)
290
+ output: list[tuple[IndustrialCanvasApply | None, MigrationIssue]] = []
291
+ for item in source:
292
+ mapped_item, issue = self._map_single_item(item)
293
+ output.append((mapped_item, issue))
294
+ return output
295
+
296
+ @property
297
+ def lookup_methods(self) -> dict[str, Callable]:
298
+ return {
299
+ "asset": self.client.migration.lookup.assets,
300
+ "event": self.client.migration.lookup.events,
301
+ "timeseries": self.client.migration.lookup.time_series,
302
+ "file": self.client.migration.lookup.files,
303
+ }
304
+
305
+ def _populate_cache(self, source: Sequence[IndustrialCanvas]) -> None:
306
+ """Populate the internal cache with references from the source canvases.
307
+
308
+ Note that the consumption views are also cached as part of the timeseries lookup.
309
+ """
310
+ ids_by_type: dict[str, set[int]] = defaultdict(set)
311
+ for canvas in source:
312
+ for ref in canvas.container_references or []:
313
+ if ref.container_reference_type in self.asset_centric_resource_types:
314
+ ids_by_type[ref.container_reference_type].add(ref.resource_id)
315
+
316
+ for resource_type, lookup_method in self.lookup_methods.items():
317
+ ids = ids_by_type.get(resource_type)
318
+ if ids:
319
+ lookup_method(list(ids))
320
+
321
+ def _get_node_id(self, resource_id: int, resource_type: str) -> NodeId | None:
322
+ """Look up the node ID for a given resource ID and type."""
323
+ try:
324
+ return self.lookup_methods[resource_type](resource_id)
325
+ except KeyError:
326
+ raise ToolkitValueError(f"Unsupported resource type '{resource_type}' for container reference migration.")
327
+
328
+ def _get_consumer_view_id(self, resource_id: int, resource_type: str) -> ViewId:
329
+ """Look up the consumer view ID for a given resource ID and type."""
330
+ lookup_map = {
331
+ "asset": (self.client.migration.lookup.assets.consumer_view, self.DEFAULT_ASSET_VIEW),
332
+ "event": (self.client.migration.lookup.events.consumer_view, self.DEFAULT_EVENT_VIEW),
333
+ "timeseries": (self.client.migration.lookup.time_series.consumer_view, self.DEFAULT_TIMESERIES_VIEW),
334
+ "file": (self.client.migration.lookup.files.consumer_view, self.DEFAULT_FILE_VIEW),
335
+ }
336
+ if lookup_tuple := lookup_map.get(resource_type):
337
+ method, fallback = lookup_tuple
338
+ return method(resource_id) or fallback
339
+
340
+ raise ToolkitValueError(f"Unsupported resource type '{resource_type}' for container reference migration.")
341
+
342
+ def _map_single_item(self, canvas: IndustrialCanvas) -> tuple[IndustrialCanvasApply | None, CanvasMigrationIssue]:
343
+ update = canvas.as_write()
344
+ issue = CanvasMigrationIssue(canvas_external_id=canvas.canvas.external_id, canvas_name=canvas.canvas.name)
345
+
346
+ remaining_container_references: list[ContainerReferenceApply] = []
347
+ new_fdm_references: list[FdmInstanceContainerReferenceApply] = []
348
+ for ref in update.container_references or []:
349
+ if ref.container_reference_type not in self.asset_centric_resource_types:
350
+ remaining_container_references.append(ref)
351
+ continue
352
+ node_id = self._get_node_id(ref.resource_id, ref.container_reference_type)
353
+ if node_id is None:
354
+ issue.missing_reference_ids.append(ref.as_asset_centric_id())
355
+ else:
356
+ consumer_view = self._get_consumer_view_id(ref.resource_id, ref.container_reference_type)
357
+ fdm_ref = self.migrate_container_reference(ref, canvas.canvas.external_id, node_id, consumer_view)
358
+ new_fdm_references.append(fdm_ref)
359
+ if issue.missing_reference_ids and self.skip_on_missing_ref:
360
+ return None, issue
361
+
362
+ update.container_references = remaining_container_references
363
+ update.fdm_instance_container_references.extend(new_fdm_references)
364
+ if not self.dry_run:
365
+ backup = canvas.as_write().create_backup()
366
+ try:
367
+ self.client.canvas.industrial.create(backup)
368
+ except CogniteException as e:
369
+ raise ToolkitMigrationError(
370
+ f"Failed to create backup for canvas '{canvas.canvas.name}': {e!s}. "
371
+ ) from e
372
+
373
+ return update, issue
374
+
375
+ @classmethod
376
+ def migrate_container_reference(
377
+ cls, reference: ContainerReferenceApply, canvas_external_id: str, instance_id: NodeId, consumer_view: ViewId
378
+ ) -> FdmInstanceContainerReferenceApply:
379
+ """Migrate a single container reference by replacing the asset-centric ID with the data model instance ID."""
380
+ new_id = str(uuid4())
381
+ new_external_id = f"{canvas_external_id}_{new_id}"
382
+ return FdmInstanceContainerReferenceApply(
383
+ external_id=new_external_id,
384
+ id_=new_id,
385
+ container_reference_type="fdmInstance",
386
+ instance_space=instance_id.space,
387
+ instance_external_id=instance_id.external_id,
388
+ view_space=consumer_view.space,
389
+ view_external_id=consumer_view.external_id,
390
+ view_version=consumer_view.version,
391
+ label=reference.label,
392
+ properties_=reference.properties_,
393
+ x=reference.x,
394
+ y=reference.y,
395
+ width=reference.width,
396
+ height=reference.height,
397
+ max_width=reference.max_width,
398
+ max_height=reference.max_height,
399
+ )
400
+
401
+
402
+ class ThreeDMapper(DataMapper[ThreeDSelector, ThreeDModelResponse, ThreeDMigrationRequest]):
403
+ def __init__(self, client: ToolkitClient) -> None:
404
+ self.client = client
405
+
406
+ def map(
407
+ self, source: Sequence[ThreeDModelResponse]
408
+ ) -> Sequence[tuple[ThreeDMigrationRequest | None, MigrationIssue]]:
409
+ self._populate_cache(source)
410
+ output: list[tuple[ThreeDMigrationRequest | None, MigrationIssue]] = []
411
+ for item in source:
412
+ mapped_item, issue = self._map_single_item(item)
413
+ output.append((mapped_item, issue))
414
+ return output
415
+
416
+ def _populate_cache(self, source: Sequence[ThreeDModelResponse]) -> None:
417
+ dataset_ids: set[int] = set()
418
+ for model in source:
419
+ if model.data_set_id is not None:
420
+ dataset_ids.add(model.data_set_id)
421
+ self.client.migration.space_source.retrieve(list(dataset_ids))
422
+
423
+ def _map_single_item(
424
+ self, item: ThreeDModelResponse
425
+ ) -> tuple[ThreeDMigrationRequest | None, ThreeDModelMigrationIssue]:
426
+ issue = ThreeDModelMigrationIssue(model_name=item.name, model_id=item.id)
427
+ instance_space: str | None = None
428
+ last_revision_id: int | None = None
429
+ model_type: Literal["CAD", "PointCloud", "Image360"] | None = None
430
+ if item.data_set_id is None:
431
+ issue.error_message.append("3D model is not associated with any dataset.")
432
+ else:
433
+ space_source = self.client.migration.space_source.retrieve(item.data_set_id)
434
+ if space_source is not None:
435
+ instance_space = space_source.instance_space
436
+ if instance_space is None and item.data_set_id is not None:
437
+ issue.error_message.append(f"Missing instance space for dataset ID {item.data_set_id!r}")
438
+ if item.last_revision_info is None:
439
+ issue.error_message.append("3D model has no revisions.")
440
+ else:
441
+ model_type = self._get_type(item.last_revision_info)
442
+ last_revision_id = item.last_revision_info.revision_id
443
+ if last_revision_id is None:
444
+ issue.error_message.append("3D model's last revision has no revision ID.")
445
+
446
+ if model_type is None:
447
+ issue.error_message.append("3D model's last revision has no recognized type.")
448
+
449
+ if instance_space is None or last_revision_id is None or model_type is None or issue.has_issues:
450
+ return None, issue
451
+
452
+ mapped_request = ThreeDMigrationRequest(
453
+ modelId=item.id,
454
+ type=model_type,
455
+ space=instance_space,
456
+ revision=ThreeDRevisionMigrationRequest(
457
+ space=instance_space,
458
+ type=model_type,
459
+ revisionId=last_revision_id,
460
+ model=Model(
461
+ instanceId=InstanceIdentifier(
462
+ space=instance_space,
463
+ external_id=f"cog_3d_model_{item.id!s}",
464
+ )
465
+ ),
466
+ ),
467
+ )
468
+ return mapped_request, issue
469
+
470
+ @staticmethod
471
+ def _get_type(revision: RevisionStatus) -> Literal["CAD", "PointCloud", "Image360"] | None:
472
+ types = revision.types or []
473
+ if any("gltf-directory" in t for t in types):
474
+ return "CAD"
475
+ elif any("ept-pointcloud" in t for t in types):
476
+ return "PointCloud"
477
+ else:
478
+ return None
479
+
480
+
481
+ class ThreeDAssetMapper(DataMapper[ThreeDSelector, AssetMappingResponse, AssetMappingDMRequest]):
482
+ def __init__(self, client: ToolkitClient) -> None:
483
+ self.client = client
484
+
485
+ def map(
486
+ self, source: Sequence[AssetMappingResponse]
487
+ ) -> Sequence[tuple[AssetMappingDMRequest | None, MigrationIssue]]:
488
+ output: list[tuple[AssetMappingDMRequest | None, MigrationIssue]] = []
489
+ self._populate_cache(source)
490
+ for item in source:
491
+ mapped_item, issue = self._map_single_item(item)
492
+ output.append((mapped_item, issue))
493
+ return output
494
+
495
+ def _populate_cache(self, source: Sequence[AssetMappingResponse]) -> None:
496
+ asset_ids: set[int] = set()
497
+ for mapping in source:
498
+ if mapping.asset_id is not None:
499
+ asset_ids.add(mapping.asset_id)
500
+ self.client.migration.lookup.assets(list(asset_ids))
501
+
502
+ def _map_single_item(
503
+ self, item: AssetMappingResponse
504
+ ) -> tuple[AssetMappingDMRequest | None, ThreeDModelMigrationIssue]:
505
+ issue = ThreeDModelMigrationIssue(model_name=f"AssetMapping_{item.model_id}", model_id=item.model_id)
506
+ asset_instance_id = item.asset_instance_id
507
+ if item.asset_id and asset_instance_id is None:
508
+ asset_node_id = self.client.migration.lookup.assets(item.asset_id)
509
+ if asset_node_id is None:
510
+ issue.error_message.append(f"Missing asset instance for asset ID {item.asset_id!r}")
511
+ return None, issue
512
+ asset_instance_id = NodeReference(space=asset_node_id.space, externalId=asset_node_id.external_id)
513
+
514
+ if asset_instance_id is None:
515
+ issue.error_message.append("Neither assetInstanceId nor assetId provided for mapping.")
516
+ return None, issue
517
+ mapped_request = AssetMappingDMRequest(
518
+ modelId=item.model_id, revisionId=item.revision_id, nodeId=item.node_id, assetInstanceId=asset_instance_id
519
+ )
520
+ return mapped_request, issue
@@ -4,6 +4,7 @@ from cognite.client.data_classes.data_modeling.containers import BTreeIndex
4
4
  SPACE = dm.SpaceApply(
5
5
  "cognite_migration", description="Space for the asset-centric to data modeling migration", name="cdf_migration"
6
6
  )
7
+ COGNITE_MIGRATION_SPACE_ID = SPACE.space
7
8
 
8
9
  RESOURCE_VIEW_MAPPING = dm.ContainerApply(
9
10
  space=SPACE.space,
@@ -2,7 +2,7 @@ from functools import lru_cache
2
2
 
3
3
  from cognite.client.data_classes.data_modeling import ViewId
4
4
 
5
- from cognite_toolkit._cdf_tk.client.data_classes.migration import ResourceViewMappingApply
5
+ from cognite_toolkit._cdf_tk.client.data_classes.legacy.migration import ResourceViewMappingApply
6
6
 
7
7
  ASSET_ID = "cdf_asset_mapping"
8
8
  EVENT_ID = "cdf_event_mapping"
@@ -93,7 +93,7 @@ def create_default_mappings() -> list[ResourceViewMappingApply]:
93
93
  view_id=ViewId("cdf_cdm", "CogniteDiagramAnnotation", "v1"),
94
94
  property_mapping={
95
95
  # We are ignoring the symbol region in the default mapping.
96
- "annotatedResource.id": "edge.startNode",
96
+ "annotatedResourceId": "edge.startNode",
97
97
  "annotationType": "edge.type.externalId",
98
98
  "creatingUser": "sourceCreatedUser",
99
99
  "creatingApp": "sourceId",
@@ -114,16 +114,16 @@ def create_default_mappings() -> list[ResourceViewMappingApply]:
114
114
  ResourceViewMappingApply(
115
115
  external_id=FILE_ANNOTATIONS_ID,
116
116
  resource_type="fileAnnotation",
117
- view_id=ViewId("cdf_cdm", "CogniteFileAnnotation", "v1"),
117
+ view_id=ViewId("cdf_cdm", "CogniteDiagramAnnotation", "v1"),
118
118
  property_mapping={
119
- "annotatedResource.id": "edge.startNode",
119
+ "annotatedResourceId": "edge.startNode",
120
120
  "annotationType": "edge.type.externalId",
121
121
  "creatingUser": "sourceCreatedUser",
122
122
  "creatingApp": "sourceId",
123
123
  "creatingAppVersion": "sourceContext",
124
124
  "status": "status",
125
- "data.fileRef.id": "edge.startNode",
126
- "data.fileRef.externalId": "edge.startNode",
125
+ "data.fileRef.id": "edge.endNode",
126
+ "data.fileRef.externalId": "edge.endNode",
127
127
  "data.description": "description",
128
128
  "data.pageNumber": "startNodePageNumber",
129
129
  "data.textRegion.confidence": "confidence",
@@ -6,7 +6,7 @@ from cognite.client.utils._identifier import InstanceId
6
6
  from cognite.client.utils._text import to_camel_case
7
7
  from pydantic import BaseModel, Field, field_serializer
8
8
 
9
- from cognite_toolkit._cdf_tk.client.data_classes.migration import AssetCentricId
9
+ from cognite_toolkit._cdf_tk.client.data_classes.legacy.migration import AssetCentricId
10
10
  from cognite_toolkit._cdf_tk.utils.useful_types import JsonVal
11
11
 
12
12
 
@@ -30,6 +30,57 @@ class MigrationIssue(MigrationObject):
30
30
  return True
31
31
 
32
32
 
33
+ class ThreeDModelMigrationIssue(MigrationIssue):
34
+ """Represents a 3D model migration issue encountered during migration.
35
+
36
+ Attributes:
37
+ model_external_id (str): The external ID of the 3D model that could not be migrated.
38
+ """
39
+
40
+ type: ClassVar[str] = "threeDModelMigration"
41
+ model_name: str
42
+ model_id: int
43
+ error_message: list[str] = Field(default_factory=list)
44
+
45
+ @property
46
+ def has_issues(self) -> bool:
47
+ """Check if there are any issues recorded in this ThreeDModelMigrationIssue."""
48
+ return bool(self.error_message)
49
+
50
+
51
+ class ChartMigrationIssue(MigrationIssue):
52
+ """Represents a chart migration issue encountered during migration.
53
+
54
+ Attributes:
55
+ chart_external_id (str): The external ID of the chart that could not be migrated.
56
+ """
57
+
58
+ type: ClassVar[str] = "chartMigration"
59
+ chart_external_id: str
60
+ missing_timeseries_ids: list[int] = Field(default_factory=list)
61
+ missing_timeseries_external_ids: list[str] = Field(default_factory=list)
62
+ missing_timeseries_identifier: list[str] = Field(default_factory=list)
63
+
64
+ @property
65
+ def has_issues(self) -> bool:
66
+ """Check if there are any issues recorded in this ChartMigrationIssue."""
67
+ return bool(
68
+ self.missing_timeseries_ids or self.missing_timeseries_external_ids or self.missing_timeseries_identifier
69
+ )
70
+
71
+
72
+ class CanvasMigrationIssue(MigrationIssue):
73
+ type: ClassVar[str] = "canvasMigration"
74
+ canvas_external_id: str
75
+ canvas_name: str
76
+ missing_reference_ids: list[AssetCentricId] = Field(default_factory=list)
77
+
78
+ @property
79
+ def has_issues(self) -> bool:
80
+ """Check if there are any issues recorded in this CanvasMigrationIssue."""
81
+ return bool(self.missing_reference_ids)
82
+
83
+
33
84
  class ReadIssue(MigrationIssue):
34
85
  """Represents a read issue encountered during migration."""
35
86