diff --git a/labelbox/schema/data_row.py b/labelbox/schema/data_row.py index d65a222ff..731f2eb98 100644 --- a/labelbox/schema/data_row.py +++ b/labelbox/schema/data_row.py @@ -106,8 +106,10 @@ def get_winning_label_id(self, project_id: str) -> Optional[str]: return res["dataRow"]["labelingActivity"]["selectedLabelId"] - def create_attachment(self, attachment_type, - attachment_value) -> "AssetAttachment": + def create_attachment(self, + attachment_type, + attachment_value, + attachment_name=None) -> "AssetAttachment": """ Adds an AssetAttachment to a DataRow. Labelers can view these attachments while labeling. @@ -117,6 +119,7 @@ def create_attachment(self, attachment_type, attachment_type (str): Asset attachment type, must be one of: VIDEO, IMAGE, TEXT, IMAGE_OVERLAY (AssetAttachment.AttachmentType) attachment_value (str): Asset attachment value. + attachment_name (str): (Optional) Asset attachment name. Returns: `AssetAttachment` DB object. Raises: @@ -126,19 +129,23 @@ def create_attachment(self, attachment_type, attachment_type_param = "type" attachment_value_param = "value" + attachment_name_param = "name" data_row_id_param = "dataRowId" + query_str = """mutation CreateDataRowAttachmentPyApi( - $%s: AttachmentType!, $%s: String!, $%s: ID!) { + $%s: AttachmentType!, $%s: String!, $%s: String, $%s: ID!) { createDataRowAttachment(data: { - type: $%s value: $%s dataRowId: $%s}) {%s}} """ % ( - attachment_type_param, attachment_value_param, data_row_id_param, - attachment_type_param, attachment_value_param, data_row_id_param, + type: $%s value: $%s name: $%s dataRowId: $%s}) {%s}} """ % ( + attachment_type_param, attachment_value_param, + attachment_name_param, data_row_id_param, attachment_type_param, + attachment_value_param, attachment_name_param, data_row_id_param, query.results_query_part(Entity.AssetAttachment)) res = self.client.execute( query_str, { attachment_type_param: attachment_type, attachment_value_param: attachment_value, + attachment_name_param: attachment_name, data_row_id_param: self.uid }) return Entity.AssetAttachment(self.client, diff --git a/tests/integration/test_data_rows.py b/tests/integration/test_data_rows.py index 7f0e6bc8a..677348934 100644 --- a/tests/integration/test_data_rows.py +++ b/tests/integration/test_data_rows.py @@ -133,7 +133,7 @@ def test_lookup_data_rows(client, dataset): assert all([len(x) == 1 for x in lookup.values()]) assert lookup[uid][0] == dr.uid assert lookup[uid2][0] == dr2.uid - #1 external id : 2 uid + # 1 external id : 2 uid dr3 = dataset.create_data_row(row_data="123", external_id=uid2) lookup = client.get_data_row_ids_for_external_ids([uid2]) assert len(lookup) == 1 @@ -621,16 +621,21 @@ def test_data_row_iteration(dataset, image_url) -> None: def test_data_row_attachments(dataset, image_url): - attachments = [("IMAGE", image_url), ("TEXT", "test-text"), - ("IMAGE_OVERLAY", image_url), ("HTML", image_url)] + attachments = [("IMAGE", image_url, "attachment image"), + ("TEXT", "test-text", None), + ("IMAGE_OVERLAY", image_url, "Overlay"), + ("HTML", image_url, None)] task = dataset.create_data_rows([{ - "row_data": image_url, - "external_id": "test-id", + "row_data": + image_url, + "external_id": + "test-id", "attachments": [{ "type": attachment_type, - "value": attachment_value + "value": attachment_value, + "name": attachment_name }] - } for attachment_type, attachment_value in attachments]) + } for attachment_type, attachment_value, attachment_name in attachments]) task.wait_till_done() assert task.status == "COMPLETE" @@ -652,8 +657,10 @@ def test_data_row_attachments(dataset, image_url): def test_create_data_rows_sync_attachments(dataset, image_url): - attachments = [("IMAGE", image_url), ("TEXT", "test-text"), - ("IMAGE_OVERLAY", image_url), ("HTML", image_url)] + attachments = [("IMAGE", image_url, "image URL"), + ("TEXT", "test-text", None), + ("IMAGE_OVERLAY", image_url, "Overlay"), + ("HTML", image_url, None)] attachments_per_data_row = 3 dataset.create_data_rows_sync([{ "row_data": @@ -662,9 +669,10 @@ def test_create_data_rows_sync_attachments(dataset, image_url): "test-id", "attachments": [{ "type": attachment_type, - "value": attachment_value + "value": attachment_value, + "name": attachment_name } for _ in range(attachments_per_data_row)] - } for attachment_type, attachment_value in attachments]) + } for attachment_type, attachment_value, attachment_name in attachments]) data_rows = list(dataset.data_rows()) assert len(data_rows) == len(attachments) for data_row in data_rows: @@ -685,12 +693,24 @@ def test_create_data_rows_sync_mixed_upload(dataset, image_url): def test_delete_data_row_attachment(datarow, image_url): attachments = [] + + # Anonymous attachment to_attach = [("IMAGE", image_url), ("TEXT", "test-text"), ("IMAGE_OVERLAY", image_url), ("HTML", image_url)] for attachment_type, attachment_value in to_attach: attachments.append( datarow.create_attachment(attachment_type, attachment_value)) + # Attachment with a name + to_attach = [("IMAGE", image_url, "Att. Image"), + ("TEXT", "test-text", "Att. Text"), + ("IMAGE_OVERLAY", image_url, "Image Overlay"), + ("HTML", image_url, "Att. HTML")] + for attachment_type, attachment_value, attachment_name in to_attach: + attachments.append( + datarow.create_attachment(attachment_type, attachment_value, + attachment_name)) + for attachment in attachments: attachment.delete() @@ -914,7 +934,8 @@ def test_create_tiled_layer(dataset, tile_content): **tile_content, 'media_type': 'TMS_SIMPLE' }, tile_content, - tile_content['row_data'] # Old way to check for backwards compatibility + # Old way to check for backwards compatibility + tile_content['row_data'] ] dataset.create_data_rows_sync(examples) data_rows = list(dataset.data_rows())