From 03f72fc3bb05a6c0cc28007b248ce3c551f67565 Mon Sep 17 00:00:00 2001 From: rllin Date: Mon, 9 Nov 2020 10:33:13 -0800 Subject: [PATCH 01/16] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 341b8e938..ea8d2bee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # Changelog -## Version 2.4.9 (2020-09-10) +## Version 2.4.9 (2020-09-11) ### Fix * 2.4.8 was broken for > Python 3.6 ### Added From c3350bfb62778ae2f276375f0707848b964b9027 Mon Sep 17 00:00:00 2001 From: rllin Date: Mon, 9 Nov 2020 10:33:52 -0800 Subject: [PATCH 02/16] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea8d2bee3..d6e346f7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ # Changelog -## Version 2.4.9 (2020-09-11) +## Version 2.4.9 (2020-11-09) ### Fix * 2.4.8 was broken for > Python 3.6 ### Added * include new `Project.enable_model_assisted_labeling` method for turning on [model-assisted labeling](https://labelbox.com/docs/automation/model-assisted-labeling) -## Version 2.4.8 (2020-09-10) +## Version 2.4.8 (2020-11-06) ### Fix * fix failing `next` call https://github.com/Labelbox/labelbox-python/issues/74 From e6d9f167c2487197d51d45e788378eda32008be5 Mon Sep 17 00:00:00 2001 From: rllin Date: Mon, 9 Nov 2020 10:35:03 -0800 Subject: [PATCH 03/16] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8c0b73379..6baf71b7d 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="labelbox", - version="2.4.8", + version="2.4.9", author="Labelbox", author_email="engineering@labelbox.com", description="Labelbox Python API", From 29b893823dc955e55ee02cee268ab78fc3584d21 Mon Sep 17 00:00:00 2001 From: Matt Sokoloff Date: Sun, 14 Feb 2021 19:09:19 -0500 Subject: [PATCH 04/16] Revert "Update setup.py" This reverts commit e6d9f167c2487197d51d45e788378eda32008be5. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6baf71b7d..8c0b73379 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="labelbox", - version="2.4.9", + version="2.4.8", author="Labelbox", author_email="engineering@labelbox.com", description="Labelbox Python API", From d703104461f786b6a386a1e0cc63a25f59f451f1 Mon Sep 17 00:00:00 2001 From: Matt Sokoloff Date: Sun, 14 Feb 2021 19:09:24 -0500 Subject: [PATCH 05/16] Revert "Update CHANGELOG.md" This reverts commit c3350bfb62778ae2f276375f0707848b964b9027. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6e346f7c..ea8d2bee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ # Changelog -## Version 2.4.9 (2020-11-09) +## Version 2.4.9 (2020-09-11) ### Fix * 2.4.8 was broken for > Python 3.6 ### Added * include new `Project.enable_model_assisted_labeling` method for turning on [model-assisted labeling](https://labelbox.com/docs/automation/model-assisted-labeling) -## Version 2.4.8 (2020-11-06) +## Version 2.4.8 (2020-09-10) ### Fix * fix failing `next` call https://github.com/Labelbox/labelbox-python/issues/74 From e9e94ebc06cee992fe2739a8c46f19db622908b3 Mon Sep 17 00:00:00 2001 From: Matt Sokoloff Date: Sun, 14 Feb 2021 19:09:31 -0500 Subject: [PATCH 06/16] Revert "Update CHANGELOG.md" This reverts commit 03f72fc3bb05a6c0cc28007b248ce3c551f67565. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea8d2bee3..341b8e938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # Changelog -## Version 2.4.9 (2020-09-11) +## Version 2.4.9 (2020-09-10) ### Fix * 2.4.8 was broken for > Python 3.6 ### Added From 464e218c6d02e5ca7ad731233e6c5d80876a24e7 Mon Sep 17 00:00:00 2001 From: Erin Liu Date: Tue, 27 Apr 2021 11:04:27 -0400 Subject: [PATCH 07/16] generalize color rgb --- examples/model_assisted_labeling/image_mal.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/model_assisted_labeling/image_mal.ipynb b/examples/model_assisted_labeling/image_mal.ipynb index ca8bb774f..e787bd058 100644 --- a/examples/model_assisted_labeling/image_mal.ipynb +++ b/examples/model_assisted_labeling/image_mal.ipynb @@ -346,7 +346,7 @@ " },\n", " \"mask\": {\n", " \"instanceURI\": url,\n", - " \"colorRGB\": [255, 0, 0]\n", + " \"colorRGB\": color\n", " }\n", " }\n", " return result\n", @@ -553,4 +553,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file From 25144b73bc6dfdd241dc728e145b3b2dc86bcbfe Mon Sep 17 00:00:00 2001 From: Matt Sokoloff Date: Mon, 7 Jun 2021 12:41:40 -0400 Subject: [PATCH 08/16] wip --- labelbox/schema/__init__.py | 1 + labelbox/schema/asset_attachment.py | 25 ++++++++++ labelbox/schema/asset_metadata.py | 8 ++++ labelbox/schema/data_row.py | 72 ++++++++++++++++++++--------- labelbox/schema/organization.py | 4 +- 5 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 labelbox/schema/asset_attachment.py diff --git a/labelbox/schema/__init__.py b/labelbox/schema/__init__.py index c43b44839..529a9b4ff 100644 --- a/labelbox/schema/__init__.py +++ b/labelbox/schema/__init__.py @@ -1,4 +1,5 @@ import labelbox.schema.asset_metadata +import labelbox.schema.asset_attachment import labelbox.schema.bulk_import_request import labelbox.schema.benchmark import labelbox.schema.data_row diff --git a/labelbox/schema/asset_attachment.py b/labelbox/schema/asset_attachment.py new file mode 100644 index 000000000..6317dbfb5 --- /dev/null +++ b/labelbox/schema/asset_attachment.py @@ -0,0 +1,25 @@ +from enum import Enum +from labelbox.orm.db_object import DbObject +from labelbox.orm.model import Field + +class AssetAttachment(DbObject): + """ Asset attachment provides extra context about an asset while labeling. + + Attributes: + attachment_type (str): IMAGE, VIDEO, TEXT, or IMAGE_OVERLAY + attachment_value (str): URL to an external file or a string of text + """ + + class MetaType(Enum): + VIDEO = "VIDEO" + IMAGE = "IMAGE" + TEXT = "TEXT" + IMAGE_OVERLAY = "IMAGE_OVERLAY" + + # For backwards compatibility + for topic in MetaType: + vars()[topic.name] = topic.value + + + attachment_type = Field.String("attachment_type") + attachment_value = Field.String("attachment_value") diff --git a/labelbox/schema/asset_metadata.py b/labelbox/schema/asset_metadata.py index 5a326d276..93cce94cd 100644 --- a/labelbox/schema/asset_metadata.py +++ b/labelbox/schema/asset_metadata.py @@ -1,8 +1,10 @@ from enum import Enum +import logging from labelbox.orm.db_object import DbObject from labelbox.orm.model import Field +logger = logging.getLogger(__name__) class AssetMetadata(DbObject): """ Asset metadata (AKA Attachments) provides extra context about an asset while labeling. @@ -12,6 +14,12 @@ class AssetMetadata(DbObject): meta_value (str): URL to an external file or a string of text """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + logger.warning( + "`create_metadata` is deprecated. Use `create_attachment` instead." + ) + class MetaType(Enum): VIDEO = "VIDEO" IMAGE = "IMAGE" diff --git a/labelbox/schema/data_row.py b/labelbox/schema/data_row.py index 08328eab5..2aff57c03 100644 --- a/labelbox/schema/data_row.py +++ b/labelbox/schema/data_row.py @@ -1,8 +1,11 @@ from labelbox.orm import query from labelbox.orm.db_object import DbObject, Updateable, BulkDeletable from labelbox.orm.model import Entity, Field, Relationship -from labelbox.schema.asset_metadata import AssetMetadata +from labelbox.schema.asset_attchment import AssetAttachment +import logging + +logger = logging.getLogger(__name__) class DataRow(DbObject, Updateable, BulkDeletable): """ Internal Labelbox representation of a single piece of data (e.g. image, video, text). @@ -33,12 +36,15 @@ class DataRow(DbObject, Updateable, BulkDeletable): created_by = Relationship.ToOne("User", False, "created_by") organization = Relationship.ToOne("Organization", False) labels = Relationship.ToMany("Label", True) + metadata = Relationship.ToMany("AssetMetadata", False, "metadata") + # attachments + attachment = Relationship.ToMany("AssetAttachment", False, "attachment") predictions = Relationship.ToMany("Prediction", False) - supported_meta_types = { - meta_type.value for meta_type in AssetMetadata.MetaType + supported_meta_types = supported_attachment_types = { + attachment_type.value for attachment_type in AssetAttachment.MetaType } @staticmethod @@ -54,42 +60,66 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.metadata.supports_filtering = False self.metadata.supports_sorting = False + self.attachment.supports_filtering = False + self.attachment.supports_sorting = False - def create_metadata(self, meta_type, meta_value): + def create_attachment(self, attachment_type, attachment_value): """ Attaches asset metadata to a DataRow. - >>> datarow.create_metadata("TEXT", "This is a text message") + >>> datarow.create_attachment("TEXT", "This is a text message") Args: - meta_type (str): Asset metadata type, must be one of: - VIDEO, IMAGE, TEXT, IMAGE_OVERLAY (AssetMetadata.MetaType) - meta_value (str): Asset metadata value. + meta_type (str): Asset attachment type, must be one of: + VIDEO, IMAGE, TEXT, IMAGE_OVERLAY (AssetAttachment.AttachmentType) + meta_value (str): Asset attachment value. Returns: - `AssetMetadata` DB object. + `AssetAttachment` DB object. Raises: - ValueError: meta_type must be one of the supported types. + ValueError: asset_type must be one of the supported types. """ - if meta_type not in self.supported_meta_types: + if attachment_type not in self.supported_attachment_types: raise ValueError( - f"meta_type must be one of {self.supported_meta_types}. Found {meta_type}" + f"meta_type must be one of {self.supported_attachment_types}. Found {attachment_type}" ) - meta_type_param = "metaType" - meta_value_param = "metaValue" + attachment_type_param = "type" + attachment_value_param = "value" data_row_id_param = "dataRowId" - query_str = """mutation CreateAssetMetadataPyApi( + query_str = """mutation CreateDataRowAttachmentPyApi( $%s: AttachmentType!, $%s: String!, $%s: ID!) { - createAssetMetadata(data: { - metaType: $%s metaValue: $%s dataRowId: $%s}) {%s}} """ % ( - meta_type_param, meta_value_param, data_row_id_param, - meta_type_param, meta_value_param, data_row_id_param, + 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, query.results_query_part(Entity.AssetMetadata)) res = self.client.execute( query_str, { - meta_type_param: meta_type, - meta_value_param: meta_value, + attachment_type_param: meta_type, + attachment_value_param: meta_value, data_row_id_param: self.uid }) + return Entity.AssetAttachment(self.client, res["createAssetMetadata"]) + + +createDataRowAttachment(data: DataRowAttachmentCreateInput!): DataRowAttachment! + deleteDataRowAttachment(where: WhereUniqueIdInput!): DataRowAttachment! + updateDataRowAttachment + + + + def create_metadata(self, meta_type, meta_value): + """ + + This function is deprecated. Use create_attachment instead + + Returns: + AssetMetadata + """ + logger.warning( + "`create_metadata` is deprecated. Use `create_attachment` instead." + ) + + attachment = self.create_attachment(meta_type, meta_value) return Entity.AssetMetadata(self.client, res["createAssetMetadata"]) diff --git a/labelbox/schema/organization.py b/labelbox/schema/organization.py index 5ea15ad35..c445c7a1d 100644 --- a/labelbox/schema/organization.py +++ b/labelbox/schema/organization.py @@ -103,10 +103,10 @@ def invite_limit(self) -> InviteLimit: """ Retrieve invite limits for the org This already accounts for users currently in the org Meaining that `used = users + invites, remaining = limit - (users + invites)` - + Returns: InviteLimit - + """ org_id_param = "organizationId" res = self.client.execute("""query InvitesLimitPyApi($%s: ID!) { From 78630822ec72686bc70fa48559c581b17ef4e346 Mon Sep 17 00:00:00 2001 From: Matt Sokoloff Date: Tue, 8 Jun 2021 20:54:04 -0400 Subject: [PATCH 09/16] replace asset metadata with attachments --- examples/basics/data_rows.ipynb | 62 ++++++++++++------------ labelbox/orm/db_object.py | 5 +- labelbox/orm/model.py | 22 +++++---- labelbox/schema/asset_attachment.py | 11 ++--- labelbox/schema/asset_metadata.py | 4 +- labelbox/schema/data_row.py | 49 ++++++++++--------- tests/integration/test_asset_metadata.py | 32 ++++++++++++ 7 files changed, 112 insertions(+), 73 deletions(-) diff --git a/examples/basics/data_rows.ipynb b/examples/basics/data_rows.ipynb index bdcfbe13d..0271dbfcc 100644 --- a/examples/basics/data_rows.ipynb +++ b/examples/basics/data_rows.ipynb @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "posted-nation", "metadata": {}, "outputs": [], @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "id": "beautiful-ready", "metadata": {}, "outputs": [], @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "id": "vertical-stockholm", "metadata": {}, "outputs": [], @@ -78,21 +78,21 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "id": "rural-fellow", "metadata": {}, "outputs": [], "source": [ "# Pick a project that has a dataset attached, data has external ids, and there are some labels\n", "# This will modify the project so just pick a dummy one that you don't care about\n", - "PROJECT_ID = \"ckk4q1viuc0w20704eh69u28h\"\n", + "PROJECT_ID = \"ckpnfquwy0kyg0y8t9rwb99cz\"\n", "# Only update this if you have an on-prem deployment\n", "ENDPOINT = \"https://api.labelbox.com/graphql\"" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "proof-detective", "metadata": {}, "outputs": [], @@ -102,7 +102,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "selective-reconstruction", "metadata": {}, "outputs": [], @@ -123,7 +123,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "extra-paris", "metadata": {}, "outputs": [], @@ -134,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "packed-going", "metadata": {}, "outputs": [ @@ -142,9 +142,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Associated dataset \n", - "Associated label(s)