22
33import itertools
44import logging
5+ import warnings
56from typing import TYPE_CHECKING , Optional
67
78from kili .adapters .kili_api_gateway .helpers .queries import QueryOptions
89from kili .adapters .kili_api_gateway .project .types import CopyProjectInput
910from kili .domain .asset import AssetFilters
1011from kili .domain .label import LabelFilters
11- from kili .domain .project import ProjectId
12+ from kili .domain .project import InputTypeEnum , ProjectId
1213
1314if TYPE_CHECKING :
1415 from kili .client import Kili
@@ -22,9 +23,13 @@ class ProjectCopier: # pylint: disable=too-few-public-methods
2223 "description" ,
2324 "id" ,
2425 "dataConnections.id" ,
26+ "inputType" ,
27+ "jsonInterface" ,
28+ "workflowVersion" ,
2529 )
2630
2731 def __init__ (self , kili : "Kili" ) -> None :
32+ """Simple initialization."""
2833 self .disable_tqdm = False
2934 self .kili = kili
3035
@@ -62,6 +67,15 @@ def copy_project( # pylint: disable=too-many-arguments
6267 if src_project ["dataConnections" ] and copy_assets :
6368 raise NotImplementedError ("Copying projects with cloud storage is not supported." )
6469
70+ if src_project ["inputType" ] in [
71+ InputTypeEnum .LLM_INSTR_FOLLOWING ,
72+ InputTypeEnum .LLM_RLHF ,
73+ InputTypeEnum .LLM_STATIC ,
74+ ]:
75+ raise NotImplementedError (
76+ f"Copying projects with input type { src_project ['inputType' ]} is not supported."
77+ )
78+
6579 logger .info ("Copying new project..." )
6680
6781 new_project_id = self .kili .kili_api_gateway .copy_project (
@@ -72,7 +86,7 @@ def copy_project( # pylint: disable=too-many-arguments
7286 ),
7387 )
7488
75- logger .info (f "Created new project { new_project_id } " )
89+ logger .info ("Created new project %s" , new_project_id )
7690
7791 self .kili .update_properties_in_project (
7892 project_id = new_project_id ,
@@ -84,7 +98,18 @@ def copy_project( # pylint: disable=too-many-arguments
8498
8599 if copy_labels :
86100 logger .info ("Copying labels..." )
87- self ._copy_labels (from_project_id , new_project_id )
101+ if src_project ["workflowVersion" ] == "V2" :
102+ self ._copy_labels (from_project_id = from_project_id , new_project_id = new_project_id )
103+ else :
104+ warnings .warn (
105+ "Warning: "
106+ "copying a project of an old workflow mode may cause problems in asset status and assignation. "
107+ "Consider creating a new project instead." ,
108+ DeprecationWarning ,
109+ )
110+ self ._copy_labels_legacy (
111+ from_project_id = from_project_id , new_project_id = new_project_id
112+ )
88113
89114 return new_project_id
90115
@@ -100,8 +125,58 @@ def _generate_project_title(self, src_title: str) -> str:
100125 i += 1
101126 return new_title
102127
103- # pylint: disable=too-many-locals
104128 def _copy_labels (self , from_project_id : str , new_project_id : str ) -> None :
129+ """Method to copy labels from the source project to the new project : applicable for WFV2."""
130+ nb_labels_to_copy = self .kili .kili_api_gateway .count_labels (
131+ LabelFilters (project_id = ProjectId (from_project_id ))
132+ )
133+
134+ if nb_labels_to_copy == 0 :
135+ return
136+
137+ assets_src_project = self .kili .kili_api_gateway .list_assets (
138+ AssetFilters (project_id = ProjectId (from_project_id )),
139+ ["id" , "externalId" , "labels.id" ],
140+ QueryOptions (disable_tqdm = True ),
141+ )
142+
143+ assets_dst_project = self .kili .kili_api_gateway .list_assets (
144+ AssetFilters (project_id = ProjectId (new_project_id )),
145+ ["id" , "externalId" ],
146+ QueryOptions (disable_tqdm = True ),
147+ )
148+
149+ # Iterate on assets of the source project
150+ # to copy labels to the new projectq
151+ assets_src_project_list = [
152+ asset
153+ for asset in assets_src_project
154+ if "labels" in asset and asset ["labels" ] and len (asset ["labels" ]) > 0
155+ ]
156+ assets_dst_project_map = {asset ["externalId" ]: asset ["id" ] for asset in assets_dst_project }
157+
158+ for src_asset in assets_src_project_list :
159+ src_asset_id = src_asset ["id" ]
160+ dst_asset_id = assets_dst_project_map .get (src_asset ["externalId" ])
161+ if not dst_asset_id :
162+ raise ValueError (
163+ f"Asset with externalId { src_asset ['externalId' ]} not found in new project { new_project_id } ."
164+ )
165+
166+ self .kili .kili_api_gateway .copy_labels (
167+ src_asset_id = src_asset_id ,
168+ dst_asset_id = dst_asset_id ,
169+ project_id = new_project_id ,
170+ )
171+
172+ # pylint: disable=too-many-locals
173+ def _copy_labels_legacy (self , from_project_id : str , new_project_id : str ) -> None :
174+ """Legacy mlethod to copy labels from the source project to the new project : applicable for WFV1.
175+
176+ !!! warning
177+ This method is deprecated and will be removed in the next major release.
178+ Asset with send back labels are not supported (status wise) and asset assignation is not supported.
179+ """
105180 assets_new_project = self .kili .kili_api_gateway .list_assets (
106181 AssetFilters (project_id = ProjectId (new_project_id )),
107182 ["id" , "externalId" ],
0 commit comments