Skip to content

Commit 31276e6

Browse files
committed
PLT-1016 - Add methods for External Workforce management
1 parent fa6deb5 commit 31276e6

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

docs/labelbox/external-workforce.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ExternalWorkforce
2+
===============================================================================================
3+
4+
.. automodule:: labelbox.schema.external_workforce
5+
:members:
6+
:show-inheritance:
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from labelbox.pydantic_compat import BaseModel
2+
3+
class ExternalWorkforce(BaseModel):
4+
"""
5+
Represents an external workforce used in the Labelbox system.
6+
7+
Attributes:
8+
id (str): The unique identifier of the external workforce.
9+
name (str): The name of the external workforce.
10+
"""
11+
id: str
12+
name: str

libs/labelbox/src/labelbox/schema/project.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from labelbox.schema.task_queue import TaskQueue
4343
from labelbox.schema.ontology_kind import (EditorTaskType, OntologyKind)
4444
from labelbox.schema.project_overview import ProjectOverview
45+
from labelbox.schema.external_workforce import ExternalWorkforce
4546

4647
if TYPE_CHECKING:
4748
from labelbox import BulkImportRequest
@@ -1826,6 +1827,114 @@ def clone(self) -> "Project":
18261827
"""
18271828
result = self.client.execute(mutation, {"projectId": self.uid})
18281829
return self.client.get_project(result["cloneProject"]["id"])
1830+
1831+
def add_external_workforce(self, workforce_id: Union[str, ExternalWorkforce]) -> List[ExternalWorkforce]:
1832+
1833+
"""
1834+
Add an external workforce (organization) to a project.
1835+
1836+
Args:
1837+
workforce_id (Union[str, ExternalWorkforce]): Organization id of the external workforce.
1838+
1839+
Returns:
1840+
List[ExternalWorkforce]: The remaining external workforces or an empty list if no external workforces are left.
1841+
1842+
Raises:
1843+
LabelboxError: If the external workforce with the given ID cannot be found.
1844+
1845+
Note:
1846+
This method adds an external workforce (organization) to the current project.
1847+
The `workforce_id` parameter can be either a string representing the organization ID or an instance of the `ExternalWorkforce` class.
1848+
"""
1849+
workforce_id = workforce_id.uid if isinstance(workforce_id, ExternalWorkforce) else workforce_id
1850+
1851+
mutation = """
1852+
mutation ShareProjectWithExternalOrganizationPyApi($projectId: ID!, $organizationId: ID!) {
1853+
shareProjectWithExternalOrganization(
1854+
data: { projectId: $projectId, organizationId: $organizationId }
1855+
) {
1856+
id
1857+
sharedWithOrganizations {
1858+
id
1859+
name
1860+
}
1861+
}
1862+
}
1863+
"""
1864+
1865+
result = self.client.execute(mutation, {"projectId": self.uid, "organizationId": workforce_id})
1866+
1867+
if not result:
1868+
raise LabelboxError(f"Can't find External Workforce {workforce_id}")
1869+
1870+
return [ExternalWorkforce(**workforce_dic)
1871+
for workforce_dic
1872+
in result["shareProjectWithExternalOrganization"]["sharedWithOrganizations"]]
1873+
1874+
1875+
def remove_external_workforce(self, workforce_id: Union[str, ExternalWorkforce]) -> List[ExternalWorkforce]:
1876+
"""Remove an external workforce (organization) from a project.
1877+
1878+
Args:
1879+
workforce_id (Union[str, ExternalWorkforce]): Organization id of the external workforce
1880+
or an instance of the ExternalWorkforce class.
1881+
1882+
Returns:
1883+
List[ExternalWorkforce]: The remaining external workforces or an empty list if no external workforces are left.
1884+
1885+
Raises:
1886+
LabelboxError: If the external workforce cannot be found.
1887+
"""
1888+
1889+
mutation = """
1890+
mutation UnshareProjectWithExternalOrganizationPyApi($projectId: ID!, $organizationId: ID!) {
1891+
unshareProjectWithExternalOrganization(
1892+
data: { projectId: $projectId, organizationId: $organizationId }
1893+
) {
1894+
id
1895+
sharedWithOrganizations {
1896+
id
1897+
name
1898+
}
1899+
}
1900+
}
1901+
"""
1902+
1903+
result = self.client.execute(mutation, {"projectId": self.uid, "organizationId": workforce_id})
1904+
1905+
if not result:
1906+
raise LabelboxError(f"Can't find External Workforce {workforce_id}")
1907+
1908+
return [ExternalWorkforce(**workforce_dic)
1909+
for workforce_dic
1910+
in result["unshareProjectWithExternalOrganization"]["sharedWithOrganizations"]]
1911+
1912+
1913+
def get_external_workforces(self) -> List[ExternalWorkforce]:
1914+
"""List the external workforces (organizations) attached to a project
1915+
1916+
Args:
1917+
project_id: Id of the project to check Project to check
1918+
1919+
Returns:
1920+
list of dictionaries with id and name for each external workforce (aka organization)
1921+
or empty list if no external workforces were found
1922+
"""
1923+
1924+
query = """
1925+
query GetProjectExternalOganizationsPyApi($projectId: ID!) {
1926+
project(where: { id: $projectId }) {
1927+
id
1928+
sharedWithOrganizations {
1929+
id
1930+
name
1931+
}
1932+
}
1933+
}
1934+
"""
1935+
1936+
result = self.client.execute(query, {"projectId": self.uid})["project"]["sharedWithOrganizations"]
1937+
return [ExternalWorkforce(**workforce_dic) for workforce_dic in result]
18291938

18301939

18311940
class ProjectMember(DbObject):
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from labelbox import Project, ExternalWorkforce
2+
import os
3+
4+
5+
def test_add_external_workforce(project: Project):
6+
# org id from https://labelbox.atlassian.net/wiki/spaces/PLT/pages/2110816271/How+to+labelbox-python+SDK+CI+Tests
7+
workforce_id = "clum46jsb00jp07z338dh1gvb" if os.environ['LABELBOX_TEST_ENVIRON'] == "staging" else "ckcz6bubudyfi0855o1dt1g9s"
8+
9+
external_workforces = project.add_external_workforce(workforce_id)
10+
assert len(external_workforces) == 1
11+
assert isinstance(external_workforces[0], ExternalWorkforce)
12+
13+
14+
def test_get_external_workforces(project: Project):
15+
external_workforces = project.external_workforces()
16+
assert len(external_workforces) == 1
17+
assert isinstance(external_workforces[0], ExternalWorkforce)
18+
19+
20+
def test_remove_external_workforce(project: Project):
21+
# org id from https://labelbox.atlassian.net/wiki/spaces/PLT/pages/2110816271/How+to+labelbox-python+SDK+CI+Tests
22+
workforce_id = "clum46jsb00jp07z338dh1gvb" if os.environ['LABELBOX_TEST_ENVIRON'] == "staging" else "ckcz6bubudyfi0855o1dt1g9s"
23+
24+
external_workforces = project.remove_external_workforce(workforce_id)
25+
assert len(external_workforces) == 0
26+
27+

0 commit comments

Comments
 (0)