Skip to content

Commit 0f516be

Browse files
committed
creation of functions to assign and fetch global keys
1 parent 221f56b commit 0f516be

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

labelbox/client.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import logging
88
import mimetypes
99
import os
10+
import time
1011

1112
from google.api_core import retry
1213
import requests
@@ -31,6 +32,7 @@
3132
from labelbox.schema.user import User
3233
from labelbox.schema.project import Project
3334
from labelbox.schema.role import Role
35+
from labelbox.schema.global_key import AssignGlobalKeyToDataRowInput
3436

3537
from labelbox.schema.media_type import MediaType
3638

@@ -939,3 +941,127 @@ def get_model_run(self, model_run_id: str) -> ModelRun:
939941
A ModelRun object.
940942
"""
941943
return self._get_single(Entity.ModelRun, model_run_id)
944+
945+
def assign_global_keys_to_data_rows(
946+
self,
947+
global_key_to_data_row_inputs: List[AssignGlobalKeyToDataRowInput],
948+
timeout=30) -> List[Dict[str, str]]:
949+
"""
950+
Assigns global keys to the related data rows.
951+
952+
>>> global_key_data_row_inputs = [
953+
AssignGlobalKeyToDataRowInput(data_row_id = "cl7asgri20yvo075b4vtfedjb", global_key = "key1"),
954+
AssignGlobalKeyToDataRowInput(data_row_id = "cl7asgri10yvg075b4pz176ht", global_key = "key2")
955+
]
956+
>>> client.assign_global_keys_to_data_rows(global_key_data_row_inputs)
957+
958+
Args:
959+
A list of AssignGlobalKeyToDataRowInput objects.
960+
Returns:
961+
Returns successful assigned global keys and data rows
962+
"""
963+
964+
mutation_str = """mutation assignGlobalKeysToDataRowsPyApi($globalKeyDataRowLinks: [AssignGlobalKeyToDataRowInput!]!) {
965+
assignGlobalKeysToDataRows(data: {assignInputs: $globalKeyDataRowLinks}) {
966+
jobId
967+
}
968+
}
969+
"""
970+
mutation_params = {
971+
'globalKeyDataRowLinks': [
972+
input.dict(by_alias=True)
973+
for input in global_key_to_data_row_inputs
974+
]
975+
}
976+
assign_global_keys_to_data_rows_job = self.execute(
977+
mutation_str, mutation_params)
978+
979+
get_failed_assignments_str = """query getDataRowsForGlobalKeysPyApi($jobId: ID!) {
980+
assignGlobalKeysToDataRowsResult(jobId: {id: $jobId}) {
981+
sanitizedAssignments {
982+
dataRowId
983+
globalKey
984+
}
985+
invalidGlobalKeyAssignments {
986+
dataRowId
987+
globalKey
988+
}
989+
unmodifiedAssignments {
990+
dataRowId
991+
globalKey
992+
}
993+
accessDeniedAssignments {
994+
dataRowId
995+
globalKey
996+
}}}
997+
"""
998+
get_failed_assignments_params = {
999+
"jobId":
1000+
assign_global_keys_to_data_rows_job["assignGlobalKeysToDataRows"
1001+
]["jobId"]
1002+
}
1003+
1004+
# TODO: Add a timeout to this based on success or not. output looks different than expected.
1005+
# TODO: Current output of sanitized rows is not showing any output. all outputs are empty lists.
1006+
# expected output {data, jobStatus} but seeing the assignment outputs above
1007+
1008+
res = self.execute(get_failed_assignments_str,
1009+
get_failed_assignments_params)
1010+
errors = []
1011+
if res['assignGlobalKeysToDataRowsResult'][
1012+
'invalidGlobalKeyAssignments'] is not None:
1013+
errors.append("Invalid Global Keys: " +
1014+
str(res['invalidGlobalKeyAssignments']))
1015+
if res['assignGlobalKeysToDataRowsResult'][
1016+
'unmodifiedAssignments'] is not None:
1017+
errors.append("Unmodified Assignments: " +
1018+
str(res['unmodifiedAssignments']))
1019+
if res['assignGlobalKeysToDataRowsResult'][
1020+
'accessDeniedAssignments'] is not None:
1021+
errors.append("Access Denied Assignments: " +
1022+
str(res['accessDeniedAssignments']))
1023+
if len(errors) > 0:
1024+
raise Exception("Failed to assign global keys to data rows: " +
1025+
str(errors))
1026+
return res['assignGlobalKeysToDataRowsResult']['sanitizedAssignments']
1027+
1028+
def get_data_row_ids_for_global_keys(self,
1029+
global_keys: List[str],
1030+
timeout=30) -> List[Dict[str, str]]:
1031+
"""
1032+
Gets data row ids for a list of global keys.
1033+
1034+
>>> data_row_ids = client.get_data_row_ids_for_global_keys(["key1",])
1035+
1036+
Args:
1037+
A list of global keys
1038+
Returns:
1039+
A list of data row ids. Returns empty if the global keys are not found.
1040+
"""
1041+
1042+
get_job_query_str = """query getDataRowsForGlobalKeysJobPyApi($globalKeys: [ID!]!) {
1043+
dataRowsForGlobalKeys(where: {ids: $globalKeys}) { jobId}}
1044+
"""
1045+
get_job_params = {"globalKeys": global_keys}
1046+
1047+
data_rows_for_global_keys_job = self.execute(get_job_query_str,
1048+
get_job_params)
1049+
1050+
get_data_rows_str = """query getDataRowsForGlobalKeysPyApi($jobId: ID!) {
1051+
dataRowsForGlobalKeysResult(jobId: {id: $jobId}) { data { fetchedDataRows {id}} jobStatus}}
1052+
"""
1053+
get_data_rows_params = {
1054+
"jobId":
1055+
data_rows_for_global_keys_job["dataRowsForGlobalKeys"]["jobId"]
1056+
}
1057+
1058+
while timeout >= 0:
1059+
res = self.execute(get_data_rows_str, get_data_rows_params)
1060+
if res["dataRowsForGlobalKeysResult"]['jobStatus'] == "COMPLETE":
1061+
return res["dataRowsForGlobalKeysResult"]['data'][
1062+
'fetchedDataRows']
1063+
time.sleep(2)
1064+
timeout -= 2
1065+
1066+
raise TimeoutError(
1067+
"Timed out waiting for data rows for global keys job to complete.")

labelbox/schema/global_key.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from pydantic import BaseModel
2+
3+
from labelbox.utils import camel_case
4+
5+
6+
class _CamelCaseMixin(BaseModel):
7+
8+
class Config:
9+
allow_population_by_field_name = True
10+
alias_generator = camel_case
11+
12+
13+
class AssignGlobalKeyToDataRowInput(_CamelCaseMixin):
14+
data_row_id: str
15+
global_key: str
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from labelbox.schema.global_key import AssignGlobalKeyToDataRowInput
2+
3+
import uuid
4+
5+
6+
def test_assign_global_keys_to_data_rows(client, dataset, image_url):
7+
"""Test that the assign_global_keys_to_data_rows method can be called
8+
with a valid list of AssignGlobalKeyToDataRowInput objects.
9+
"""
10+
11+
dr_1 = dataset.create_data_row(row_data=image_url, external_id="hello")
12+
dr_2 = dataset.create_data_row(row_data=image_url, external_id="world")
13+
row_ids = [dr_1.uid, dr_2.uid]
14+
15+
gk_1 = str(uuid.uuid4())
16+
gk_2 = str(uuid.uuid4())
17+
18+
assignment_inputs = [
19+
AssignGlobalKeyToDataRowInput(data_row_id=dr_1.uid, global_key=gk_1),
20+
AssignGlobalKeyToDataRowInput(data_row_id=dr_2.uid, global_key=gk_2)
21+
]
22+
client.assign_global_keys_to_data_rows(assignment_inputs)
23+
24+
res = client.get_data_row_ids_for_global_keys([gk_1, gk_2])
25+
26+
assert len(res) == 2
27+
for row in res:
28+
assert row['id'] in row_ids
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from labelbox.schema.global_key import AssignGlobalKeyToDataRowInput
2+
3+
4+
def test_global_key_to_data_row_input():
5+
"""Test that the AssignGlobalKeyToDataRowInput class can be instantiated
6+
with a valid data_row_id and global_key.
7+
"""
8+
data_row_id = "cl7asgri20yvo075b4vtfedjb"
9+
global_key = "123cl7cqkdmk000iu0p1hltbb1fb"
10+
assignment_input = AssignGlobalKeyToDataRowInput(data_row_id=data_row_id,
11+
global_key=global_key)
12+
assert assignment_input.data_row_id == data_row_id
13+
assert assignment_input.global_key == global_key

0 commit comments

Comments
 (0)