diff --git a/docs/labelbox/labeling-service.rst b/docs/labelbox/labeling-service.rst new file mode 100644 index 000000000..03afb31e9 --- /dev/null +++ b/docs/labelbox/labeling-service.rst @@ -0,0 +1,6 @@ +Project Labeling Service +=============================================================================================== + +.. automodule:: labelbox.schema.labeling_service + :members: + :show-inheritance: diff --git a/libs/labelbox/src/labelbox/schema/labeling_service.py b/libs/labelbox/src/labelbox/schema/labeling_service.py new file mode 100644 index 000000000..e052c64c1 --- /dev/null +++ b/libs/labelbox/src/labelbox/schema/labeling_service.py @@ -0,0 +1,29 @@ +from datetime import datetime +from enum import Enum + +from labelbox.data.annotation_types.types import Cuid +from labelbox.orm.db_object import experimental +from labelbox.pydantic_compat import BaseModel +from labelbox.utils import _CamelCaseMixin + + +class LabelingServiceStatus(Enum): + Accepted = 'ACCEPTED', + Calibration = 'CALIBRATION', + Complete = 'COMPLETE', + Production = 'PRODUCTION', + Requested = 'REQUESTED', + SetUp = 'SET_UP' + + +@experimental +class LabelingService(_CamelCaseMixin, BaseModel): + id: Cuid + project_id: Cuid + created_at: datetime + updated_at: datetime + created_by_id: Cuid + status: LabelingServiceStatus + + def status_as_string(self): + return self.status.value diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index 1fd87c7e5..33888ef99 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, TypeVar, Union, overload from urllib.parse import urlparse +from labelbox.schema.labeling_service import LabelingService import requests from labelbox import parser @@ -1904,6 +1905,35 @@ def clone(self) -> "Project": result = self.client.execute(mutation, {"projectId": self.uid}) return self.client.get_project(result["cloneProject"]["id"]) + @experimental + def get_labeling_service(self) -> LabelingService: + """ + Returns the labeling service associated with the project. + + Returns: + LabelingService: The labeling service associated with the project. + + Raises: + ResourceNotFoundError: If the project does not have a labeling service. + """ + query = """ + query GetProjectBoostWorkforcePyApi($projectId: ID!) { + projectBoostWorkforce(data: { projectId: $projectId }) { + id + projectId + createdAt + updatedAt + createdById + status + } + } + """ + result = self.client.execute(query, {"projectId": self.uid}) + if result["projectBoostWorkforce"] is None: + raise ResourceNotFoundError( + message="The project does not have a labeling service.") + return LabelingService(**result["projectBoostWorkforce"]) + class ProjectMember(DbObject): user = Relationship.ToOne("User", cache=True) diff --git a/libs/labelbox/tests/integration/test_labeling_service.py b/libs/labelbox/tests/integration/test_labeling_service.py new file mode 100644 index 000000000..0cb11eb25 --- /dev/null +++ b/libs/labelbox/tests/integration/test_labeling_service.py @@ -0,0 +1,7 @@ +from labelbox.exceptions import ResourceNotFoundError +import pytest + + +def test_get_labeling_service_throws_exception(project): + with pytest.raises(ResourceNotFoundError): # No labeling service by default + project.get_labeling_service()