11import json
22import logging
3+ from string import Template
34import time
45import warnings
56from collections import namedtuple
67from datetime import datetime , timezone
78from pathlib import Path
8- from typing import TYPE_CHECKING , Any , Dict , Iterable , List , Optional , TypeVar , Union , overload
9+ from typing import TYPE_CHECKING , Any , Dict , Iterable , List , Optional , Tuple , TypeVar , Union , overload
910from urllib .parse import urlparse
1011
1112import requests
2829from labelbox .schema .export_filters import ProjectExportFilters , validate_datetime , build_filters
2930from labelbox .schema .export_params import ProjectExportParams
3031from labelbox .schema .export_task import ExportTask
32+ from labelbox .schema .id_type import IdType
33+ from labelbox .schema .identifiable import DataRowIdentifier , GlobalKey , UniqueId
3134from labelbox .schema .identifiables import DataRowIdentifiers , UniqueIds
3235from labelbox .schema .media_type import MediaType
3336from labelbox .schema .queue_mode import QueueMode
4346except ImportError :
4447 pass
4548
49+ DataRowPriority = int
50+ LabelingParameterOverrideInput = Tuple [Union [DataRow , DataRowIdentifier ],
51+ DataRowPriority ]
52+
4653logger = logging .getLogger (__name__ )
4754
4855
56+ def validate_labeling_parameter_overrides (
57+ data : List [LabelingParameterOverrideInput ]) -> None :
58+ for idx , row in enumerate (data ):
59+ if len (row ) < 2 :
60+ raise TypeError (
61+ f"Data must be a list of tuples each containing two elements: a DataRow or a DataRowIdentifier and priority (int). Found { len (row )} items. Index: { idx } "
62+ )
63+ data_row_identifier = row [0 ]
64+ priority = row [1 ]
65+ valid_types = (Entity .DataRow , UniqueId , GlobalKey )
66+ if not isinstance (data_row_identifier , valid_types ):
67+ raise TypeError (
68+ f"Data row identifier should be be of type DataRow, UniqueId or GlobalKey. Found { type (data_row_identifier )} for data_row_identifier { data_row_identifier } "
69+ )
70+
71+ if not isinstance (priority , int ):
72+ if isinstance (data_row_identifier , Entity .DataRow ):
73+ id = data_row_identifier .uid
74+ else :
75+ id = data_row_identifier
76+ raise TypeError (
77+ f"Priority must be an int. Found { type (priority )} for data_row_identifier { id } "
78+ )
79+
80+
4981class Project (DbObject , Updateable , Deletable ):
5082 """ A Project is a container that includes a labeling frontend, an ontology,
5183 datasets and labels.
@@ -1129,36 +1161,25 @@ def get_queue_mode(self) -> "QueueMode":
11291161 else :
11301162 raise ValueError ("Status not known" )
11311163
1132- def validate_labeling_parameter_overrides (self , data ) -> None :
1133- for idx , row in enumerate (data ):
1134- if len (row ) < 2 :
1135- raise TypeError (
1136- f"Data must be a list of tuples containing a DataRow and priority (int). Found { len (row )} items. Index: { idx } "
1137- )
1138- data_row = row [0 ]
1139- priority = row [1 ]
1140- if not isinstance (data_row , Entity .DataRow ):
1141- raise TypeError (
1142- f"data_row should be be of type DataRow. Found { type (data_row )} . Index: { idx } "
1143- )
1144-
1145- if not isinstance (priority , int ):
1146- raise TypeError (
1147- f"Priority must be an int. Found { type (priority )} for data_row { data_row } . Index: { idx } "
1148- )
1149-
1150- def set_labeling_parameter_overrides (self , data ) -> bool :
1164+ def set_labeling_parameter_overrides (
1165+ self , data : List [LabelingParameterOverrideInput ]) -> bool :
11511166 """ Adds labeling parameter overrides to this project.
11521167
11531168 See information on priority here:
11541169 https://docs.labelbox.com/en/configure-editor/queue-system#reservation-system
11551170
11561171 >>> project.set_labeling_parameter_overrides([
1157- >>> (data_row_1, 2), (data_row_2, 1)])
1172+ >>> (data_row_id1, 2), (data_row_id2, 1)])
1173+ or
1174+ >>> project.set_labeling_parameter_overrides([
1175+ >>> (data_row_gk1, 2), (data_row_gk2, 1)])
11581176
11591177 Args:
11601178 data (iterable): An iterable of tuples. Each tuple must contain
1161- (DataRow, priority<int>) for the new override.
1179+ either (DataRow, DataRowPriority<int>)
1180+ or (DataRowIdentifier, priority<int>) for the new override.
1181+ DataRowIdentifier is an object representing a data row id or a global key. A DataIdentifier object can be a UniqueIds or GlobalKeys class.
1182+ NOTE - passing whole DatRow is deprecated. Please use a DataRowIdentifier instead.
11621183
11631184 Priority:
11641185 * Data will be labeled in priority order.
@@ -1174,15 +1195,31 @@ def set_labeling_parameter_overrides(self, data) -> bool:
11741195 bool, indicates if the operation was a success.
11751196 """
11761197 data = [t [:2 ] for t in data ]
1177- self .validate_labeling_parameter_overrides (data )
1178- data_str = ",\n " .join ("{dataRow: {id: \" %s\" }, priority: %d }" %
1179- (data_row .uid , priority )
1180- for data_row , priority in data )
1181- id_param = "projectId"
1182- query_str = """mutation SetLabelingParameterOverridesPyApi($%s: ID!){
1183- project(where: { id: $%s }) {setLabelingParameterOverrides
1184- (data: [%s]) {success}}} """ % (id_param , id_param , data_str )
1185- res = self .client .execute (query_str , {id_param : self .uid })
1198+ validate_labeling_parameter_overrides (data )
1199+
1200+ template = Template (
1201+ """mutation SetLabelingParameterOverridesPyApi($$projectId: ID!)
1202+ {project(where: { id: $$projectId })
1203+ {setLabelingParameterOverrides
1204+ (dataWithDataRowIdentifiers: [$dataWithDataRowIdentifiers])
1205+ {success}}}
1206+ """ )
1207+
1208+ data_rows_with_identifiers = ""
1209+ for data_row , priority in data :
1210+ if isinstance (data_row , DataRow ):
1211+ data_rows_with_identifiers += f"{{dataRowIdentifier: {{id: \" { data_row .uid } \" , idType: { IdType .DataRowId } }}, priority: { priority } }},"
1212+ elif isinstance (data_row , UniqueId ) or isinstance (
1213+ data_row , GlobalKey ):
1214+ data_rows_with_identifiers += f"{{dataRowIdentifier: {{id: \" { data_row .key } \" , idType: { data_row .id_type } }}, priority: { priority } }},"
1215+ else :
1216+ raise TypeError (
1217+ f"Data row identifier should be be of type DataRow or Data Row Identifier. Found { type (data_row )} ."
1218+ )
1219+
1220+ query_str = template .substitute (
1221+ dataWithDataRowIdentifiers = data_rows_with_identifiers )
1222+ res = self .client .execute (query_str , {"projectId" : self .uid })
11861223 return res ["project" ]["setLabelingParameterOverrides" ]["success" ]
11871224
11881225 @overload
0 commit comments