Skip to content

Commit bacd372

Browse files
authored
Merge pull request #430 from Labelbox/mani/resource-tags
get_resource_tags and create_project_resource_tags
2 parents 8b2088d + 8ea84d0 commit bacd372

File tree

6 files changed

+146
-2
lines changed

6 files changed

+146
-2
lines changed

labelbox/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@
2323
from labelbox.schema.model_run import ModelRun
2424
from labelbox.schema.benchmark import Benchmark
2525
from labelbox.schema.iam_integration import IAMIntegration
26+
from labelbox.schema.resource_tag import ResourceTag
27+
from labelbox.schema.project_resource_tag import ProjectResourceTag

labelbox/schema/organization.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import json
12
from typing import TYPE_CHECKING, List, Optional
23

34
from labelbox.exceptions import LabelboxError
45
from labelbox import utils
56
from labelbox.orm.db_object import DbObject, query, Entity
67
from labelbox.orm.model import Field, Relationship
78
from labelbox.schema.invite import InviteLimit
9+
from labelbox.schema.resource_tag import ResourceTag
810

911
if TYPE_CHECKING:
1012
from labelbox import Role, User, ProjectRole, Invite, InviteLimit, IAMIntegration
@@ -42,6 +44,7 @@ def __init__(self, *args, **kwargs):
4244
users = Relationship.ToMany("User", False)
4345
projects = Relationship.ToMany("Project", True)
4446
webhooks = Relationship.ToMany("Webhook", False)
47+
resource_tags = Relationship.ToMany("ResourceTags", False)
4548

4649
def invite_user(
4750
self,
@@ -126,6 +129,43 @@ def remove_user(self, user: "User") -> None:
126129
updateUser(where: {id: $%s}, data: {deleted: true}) { id deleted }
127130
}""" % (user_id_param, user_id_param), {user_id_param: user.uid})
128131

132+
def create_resource_tag(self, tag=None) -> ResourceTag:
133+
"""
134+
Creates a resource tag.
135+
>>> tag = {'text': 'tag-1', 'color': 'ffffff'}
136+
137+
Args:
138+
tag (dict): A resource tag {'text': 'tag-1', 'color': 'fffff'}
139+
Returns:
140+
The created resource tag.
141+
"""
142+
tag_text_param = "text"
143+
tag_color_param = "color"
144+
145+
query_str = """mutation CreateResourceTagPyApi($text:String!,$color:String!) {
146+
createResourceTag(input:{text:$%s,color:$%s}) {%s}}
147+
""" % (tag_text_param, tag_color_param,
148+
query.results_query_part(ResourceTag))
149+
150+
params = {
151+
tag_text_param: tag.get("text", ""),
152+
tag_color_param: tag.get("color", "")
153+
}
154+
res = self.client.execute(query_str, params)
155+
return ResourceTag(self.client, res['createResourceTag'])
156+
157+
def get_resource_tags(self) -> List[ResourceTag]:
158+
"""
159+
Returns all resource tags for an organization
160+
"""
161+
query_str = """query GetOrganizationResourceTagsPyApi{organization{resourceTag{%s}}}""" % (
162+
query.results_query_part(ResourceTag))
163+
164+
return [
165+
ResourceTag(self.client, tag) for tag in self.client.execute(
166+
query_str)['organization']['resourceTag']
167+
]
168+
129169
def get_iam_integrations(self) -> List["IAMIntegration"]:
130170
"""
131171
Returns all IAM Integrations for an organization

labelbox/schema/project.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from labelbox.orm.db_object import DbObject, Updateable, Deletable
1919
from labelbox.orm.model import Entity, Field, Relationship
2020
from labelbox.pagination import PaginatedCollection
21+
from labelbox.schema.resource_tag import ResourceTag
2122

2223
if TYPE_CHECKING:
2324
from labelbox import BulkImportRequest
@@ -121,6 +122,33 @@ def members(self) -> PaginatedCollection:
121122
{id_param: str(self.uid)},
122123
["project", "members"], ProjectMember)
123124

125+
def update_project_resource_tags(
126+
self, resource_tag_ids: List[str]) -> List[ResourceTag]:
127+
""" Creates project resource tags
128+
129+
Args:
130+
resource_tag_ids
131+
Returns:
132+
a list of ResourceTag ids that was created.
133+
"""
134+
project_id_param = "projectId"
135+
tag_ids_param = "resourceTagIds"
136+
137+
query_str = """mutation UpdateProjectResourceTagsPyApi($%s:ID!,$%s:[String!]) {
138+
project(where:{id:$%s}){updateProjectResourceTags(input:{%s:$%s}){%s}}}""" % (
139+
project_id_param, tag_ids_param, project_id_param, tag_ids_param,
140+
tag_ids_param, query.results_query_part(ResourceTag))
141+
142+
res = self.client.execute(query_str, {
143+
project_id_param: self.uid,
144+
tag_ids_param: resource_tag_ids
145+
})
146+
147+
return [
148+
ResourceTag(self.client, tag)
149+
for tag in res["project"]["updateProjectResourceTags"]
150+
]
151+
124152
def labels(self, datasets=None, order_by=None) -> PaginatedCollection:
125153
""" Custom relationship expansion method to support limited filtering.
126154
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from labelbox.orm.db_object import DbObject, Updateable
2+
from labelbox.orm.model import Field, Relationship
3+
4+
5+
class ProjectResourceTag(DbObject, Updateable):
6+
""" Project resource tag to associate ProjectResourceTag to Project.
7+
8+
Attributes:
9+
resourceTagId (str)
10+
projectId (str)
11+
12+
resource_tag (Relationship): `ToOne` relationship to ResourceTag
13+
"""
14+
15+
resource_tag_id = Field.ID("resource_tag_id")
16+
project_id = Field.ID("project_id")

labelbox/schema/resource_tag.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from labelbox.orm.db_object import DbObject, Updateable
2+
from labelbox.orm.model import Field, Relationship
3+
4+
5+
class ResourceTag(DbObject, Updateable):
6+
""" Resource tag to label and identify your labelbox resources easier.
7+
8+
Attributes:
9+
text (str)
10+
color (str)
11+
12+
project_resource_tag (Relationship): `ToMany` relationship to ProjectResourceTag
13+
"""
14+
15+
text = Field.String("text")
16+
color = Field.String("color")

tests/integration/test_project.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,50 @@ def test_project(client, rand_gen):
4242
assert project not in final
4343
assert set(final) == set(before)
4444

45-
# TODO this should raise ResourceNotFoundError, but it doesn't
46-
project = client.get_project(project.uid)
45+
46+
def test_update_project_resource_tags(client, rand_gen):
47+
before = list(client.get_projects())
48+
for o in before:
49+
assert isinstance(o, Project)
50+
51+
org = client.get_organization()
52+
assert org.uid is not None
53+
54+
project_name = rand_gen(str)
55+
p1 = client.create_project(name=project_name)
56+
assert p1.uid is not None
57+
58+
colorA = "#ffffff"
59+
textA = rand_gen(str)
60+
tag = {"text": textA, "color": colorA}
61+
62+
colorB = colorA
63+
textB = rand_gen(str)
64+
tagB = {"text": textB, "color": colorB}
65+
66+
tagA = client.get_organization().create_resource_tag(tag)
67+
assert tagA.text == textA
68+
assert '#' + tagA.color == colorA
69+
assert tagA.uid is not None
70+
71+
tags = org.get_resource_tags()
72+
lenA = len(tags)
73+
assert lenA > 0
74+
75+
tagB = client.get_organization().create_resource_tag(tagB)
76+
assert tagB.text == textB
77+
assert '#' + tagB.color == colorB
78+
assert tagB.uid is not None
79+
80+
tags = client.get_organization().get_resource_tags()
81+
lenB = len(tags)
82+
assert lenB > 0
83+
assert lenB > lenA
84+
85+
project_resource_tag = client.get_project(
86+
p1.uid).update_project_resource_tags([str(tagA.uid)])
87+
assert len(project_resource_tag) == 1
88+
assert project_resource_tag[0].uid == tagA.uid
4789

4890

4991
def test_project_filtering(client, rand_gen):

0 commit comments

Comments
 (0)