From c295f32cb5b9616f6035d1d507116c3b4b36e7f8 Mon Sep 17 00:00:00 2001 From: Val Brodsky Date: Tue, 18 Jun 2024 15:59:02 -0700 Subject: [PATCH 1/6] Add Project set_project_model_setup_complete --- libs/labelbox/src/labelbox/schema/project.py | 47 +++++++++++++------ .../test_chat_evaluation_ontology_project.py | 2 + 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index a2142ebc5..f64843ed2 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -13,13 +13,9 @@ from labelbox import parser from labelbox import utils -from labelbox.exceptions import ( - InvalidQueryError, - LabelboxError, - ProcessingWaitTimeout, - ResourceConflict, - ResourceNotFoundError -) +from labelbox.exceptions import (InvalidQueryError, LabelboxError, + ProcessingWaitTimeout, ResourceConflict, + ResourceNotFoundError) from labelbox.orm import query from labelbox.orm.db_object import DbObject, Deletable, Updateable, experimental from labelbox.orm.model import Entity, Field, Relationship @@ -122,6 +118,7 @@ class Project(DbObject, Updateable, Deletable): media_type = Field.Enum(MediaType, "media_type", "allowedMediaType") editor_task_type = Field.Enum(EditorTaskType, "editor_task_type") data_row_count = Field.Int("data_row_count") + model_setup_complete: Field = Field.Boolean("model_setup_complete") # Relationships created_by = Relationship.ToOne("User", False, "created_by") @@ -1299,6 +1296,24 @@ def delete_project_model_config(self, project_model_config_id: str) -> bool: raise ResourceNotFoundError(ProjectModelConfig, params) return result["deleteProjectModelConfig"]["success"] + def set_project_model_setup_complete(self) -> bool: + """ Checks if the model setup is complete for this project. + + Returns: + bool, indicates if the model setup is complete. + """ + query = """query ModelSetupCompletePyApi($projectId: ID!) { + project(where: {id: $projectId}, data: {modelSetupComplete: true}) { + modelSetupComplete + } + }""" + + result = self.client.execute(query, {"projectId": self.uid}) + + self.update( + model_setup_complete=result["project"]["modelSetupComplete"]) + return result["project"]["modelSetupComplete"] + def set_labeling_parameter_overrides( self, data: List[LabelingParameterOverrideInput]) -> bool: """ Adds labeling parameter overrides to this project. @@ -1752,7 +1767,9 @@ def __check_data_rows_have_been_processed( return response["queryAllDataRowsHaveBeenProcessed"][ "allDataRowsHaveBeenProcessed"] - def get_overview(self, details=False) -> Union[ProjectOverview, ProjectOverviewDetailed]: + def get_overview( + self, + details=False) -> Union[ProjectOverview, ProjectOverviewDetailed]: """Return the overview of a project. This method returns the number of data rows per task queue and issues of a project, @@ -1792,7 +1809,7 @@ def get_overview(self, details=False) -> Union[ProjectOverview, ProjectOverviewD # Must use experimental to access "issues" result = self.client.execute(query, {"projectId": self.uid}, - experimental=True)["project"] + experimental=True)["project"] # Reformat category names overview = { @@ -1805,7 +1822,7 @@ def get_overview(self, details=False) -> Union[ProjectOverview, ProjectOverviewD # Rename categories overview["to_label"] = overview.pop("unlabeled") - overview["total_data_rows"] = overview.pop("all") + overview["total_data_rows"] = overview.pop("all") if not details: return ProjectOverview(**overview) @@ -1813,18 +1830,20 @@ def get_overview(self, details=False) -> Union[ProjectOverview, ProjectOverviewD # Build dictionary for queue details for review and rework queues for category in ["rework", "review"]: queues = [ - {tq["name"]: tq.get("dataRowCount")} + { + tq["name"]: tq.get("dataRowCount") + } for tq in result.get("taskQueues") if tq.get("queueType") == f"MANUAL_{category.upper()}_QUEUE" ] - overview[f"in_{category}"] = { + overview[f"in_{category}"] = { "data": queues, "total": overview[f"in_{category}"] } - + return ProjectOverviewDetailed(**overview) - + def clone(self) -> "Project": """ Clones the current project. diff --git a/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py b/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py index 6a41a7a09..ba36bbaf6 100644 --- a/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py +++ b/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py @@ -24,6 +24,8 @@ def test_create_chat_evaluation_ontology_project( assert classification.feature_schema_id project = chat_evaluation_project_create_dataset + assert project.model_setup_complete is None + project.setup_editor(ontology) assert project.labeling_frontend().name == "Editor" From 1cecdc27c32c0e2d53a1d22a6ec0b2b726d55836 Mon Sep 17 00:00:00 2001 From: Val Brodsky Date: Wed, 19 Jun 2024 16:14:43 -0700 Subject: [PATCH 2/6] Handle out of band exceptions for Project add_model_config in order to deal with a model_setup_complete scenario --- libs/labelbox/src/labelbox/schema/project.py | 31 ++++++++++---- libs/labelbox/tests/integration/conftest.py | 2 +- .../test_chat_evaluation_ontology_project.py | 4 +- .../test_project_set_model_setup_complete.py | 41 +++++++++++++++++++ 4 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 libs/labelbox/tests/integration/test_project_set_model_setup_complete.py diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index f64843ed2..2679ee6b8 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -1,3 +1,4 @@ +import re import json import logging from string import Template @@ -1268,7 +1269,22 @@ def add_model_config(self, model_config_id: str) -> str: "projectId": self.uid, "modelConfigId": model_config_id, } - result = self.client.execute(query, params) + try: + result = self.client.execute(query, params) + except LabelboxError as e: + # unfortunately, this is the type of errors our client does not deal with and so the error message is not in the same format as the other errors + # needs custom parsing + error_string = e.message + # Regex to find the message content + pattern = r"'message': '([^']+)'" + # Search for the pattern in the error string + match = re.search(pattern, error_string) + if match: + error_content = match.group(1) + else: + error_content = "Unknown error" + raise LabelboxError(message=error_content) from e + if not result: raise ResourceNotFoundError(ModelConfig, params) return result["createProjectModelConfig"]["projectModelConfigId"] @@ -1301,18 +1317,19 @@ def set_project_model_setup_complete(self) -> bool: Returns: bool, indicates if the model setup is complete. + + NOTE: This method should only be used for live model evaluation projects. """ - query = """query ModelSetupCompletePyApi($projectId: ID!) { - project(where: {id: $projectId}, data: {modelSetupComplete: true}) { + query = """mutation SetProjectModelSetupCompletePyApi($projectId: ID!) { + setProjectModelSetupComplete(where: {id: $projectId}, data: {modelSetupComplete: true}) { modelSetupComplete } }""" result = self.client.execute(query, {"projectId": self.uid}) - - self.update( - model_setup_complete=result["project"]["modelSetupComplete"]) - return result["project"]["modelSetupComplete"] + self.model_setup_complete = result["setProjectModelSetupComplete"][ + "modelSetupComplete"] + return result["setProjectModelSetupComplete"]["modelSetupComplete"] def set_labeling_parameter_overrides( self, data: List[LabelingParameterOverrideInput]) -> bool: diff --git a/libs/labelbox/tests/integration/conftest.py b/libs/labelbox/tests/integration/conftest.py index 612d98122..b639b20df 100644 --- a/libs/labelbox/tests/integration/conftest.py +++ b/libs/labelbox/tests/integration/conftest.py @@ -407,7 +407,7 @@ def chat_evaluation_ontology(client, rand_gen): @pytest.fixture -def chat_evaluation_project_create_dataset(client, rand_gen): +def live_chat_evaluation_project_with_new_dataset(client, rand_gen): project_name = f"test-model-evaluation-project-{rand_gen(str)}" dataset_name = f"test-model-evaluation-dataset-{rand_gen(str)}" project = client.create_model_evaluation_project(name=project_name, diff --git a/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py b/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py index ba36bbaf6..f0b58f1d3 100644 --- a/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py +++ b/libs/labelbox/tests/integration/test_chat_evaluation_ontology_project.py @@ -6,7 +6,7 @@ def test_create_chat_evaluation_ontology_project( client, chat_evaluation_ontology, - chat_evaluation_project_create_dataset, conversation_data_row, + live_chat_evaluation_project_with_new_dataset, conversation_data_row, rand_gen): ontology = chat_evaluation_ontology @@ -23,7 +23,7 @@ def test_create_chat_evaluation_ontology_project( assert classification.schema_id assert classification.feature_schema_id - project = chat_evaluation_project_create_dataset + project = live_chat_evaluation_project_with_new_dataset assert project.model_setup_complete is None project.setup_editor(ontology) diff --git a/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py b/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py new file mode 100644 index 000000000..53e1686fe --- /dev/null +++ b/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py @@ -0,0 +1,41 @@ +import pytest + +from labelbox.exceptions import LabelboxError, OperationNotAllowedException + + +def test_live_chat_evaluation_project( + live_chat_evaluation_project_with_new_dataset, model_config): + + project = live_chat_evaluation_project_with_new_dataset + + project.set_project_model_setup_complete() + assert bool(project.model_setup_complete) is True + + with pytest.raises( + expected_exception=LabelboxError, + match= + "Cannot create model config for project because model setup is complete" + ): + project.add_model_config(model_config.uid) + + +def test_offline_chat_evaluation_project(offline_chat_evaluation_project, + model_config): + + project = offline_chat_evaluation_project + + with pytest.raises( + expected_exception=OperationNotAllowedException, + match= + "Only live model chat evaluation projects can complete model setup" + ): + project.set_project_model_setup_complete() + + +def test_any_other_project(project, model_config): + with pytest.raises( + expected_exception=OperationNotAllowedException, + match= + "Only live model chat evaluation projects can complete model setup" + ): + project.set_project_model_setup_complete() From 5e2af6f1b1cb87ad94e36df5d71c9bd08bcd33cd Mon Sep 17 00:00:00 2001 From: Val Brodsky Date: Wed, 19 Jun 2024 20:55:23 -0700 Subject: [PATCH 3/6] Handle model setup complete on model project config deletion --- libs/labelbox/src/labelbox/exceptions.py | 16 ++++++++++++ libs/labelbox/src/labelbox/schema/project.py | 12 ++------- .../labelbox/schema/project_model_config.py | 11 ++++++-- .../test_project_set_model_setup_complete.py | 25 +++++++++++++++++++ 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/libs/labelbox/src/labelbox/exceptions.py b/libs/labelbox/src/labelbox/exceptions.py index 678196f5d..dd3a2be4c 100644 --- a/libs/labelbox/src/labelbox/exceptions.py +++ b/libs/labelbox/src/labelbox/exceptions.py @@ -1,3 +1,6 @@ +import re + + class LabelboxError(Exception): """Base class for exceptions.""" @@ -147,3 +150,16 @@ class CustomMetricsNotSupportedException(Exception): class ProcessingWaitTimeout(Exception): """Raised when waiting for the data rows to be processed takes longer than allowed""" + + +def _error_message_for_unparsed_graphql_error(error_string: str) -> str: + # Regex to find the message content + pattern = r"'message': '([^']+)'" + # Search for the pattern in the error string + match = re.search(pattern, error_string) + if match: + error_content = match.group(1) + else: + error_content = "Unknown error" + + return error_content diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index 2679ee6b8..496a95cef 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -1,4 +1,3 @@ -import re import json import logging from string import Template @@ -14,6 +13,7 @@ from labelbox import parser from labelbox import utils +from labelbox.exceptions import _error_message_for_unparsed_graphql_error from labelbox.exceptions import (InvalidQueryError, LabelboxError, ProcessingWaitTimeout, ResourceConflict, ResourceNotFoundError) @@ -1274,15 +1274,7 @@ def add_model_config(self, model_config_id: str) -> str: except LabelboxError as e: # unfortunately, this is the type of errors our client does not deal with and so the error message is not in the same format as the other errors # needs custom parsing - error_string = e.message - # Regex to find the message content - pattern = r"'message': '([^']+)'" - # Search for the pattern in the error string - match = re.search(pattern, error_string) - if match: - error_content = match.group(1) - else: - error_content = "Unknown error" + error_content = _error_message_for_unparsed_graphql_error(e.message) raise LabelboxError(message=error_content) from e if not result: diff --git a/libs/labelbox/src/labelbox/schema/project_model_config.py b/libs/labelbox/src/labelbox/schema/project_model_config.py index 8248a6a7a..353ce7890 100644 --- a/libs/labelbox/src/labelbox/schema/project_model_config.py +++ b/libs/labelbox/src/labelbox/schema/project_model_config.py @@ -1,5 +1,6 @@ -from labelbox.orm.db_object import DbObject, Deletable +from labelbox.orm.db_object import DbObject from labelbox.orm.model import Field, Relationship +from labelbox.exceptions import LabelboxError, _error_message_for_unparsed_graphql_error class ProjectModelConfig(DbObject): @@ -30,5 +31,11 @@ def delete(self) -> bool: params = { "id": self.uid, } - result = self.client.execute(query, params) + + try: + result = self.client.execute(query, params) + except LabelboxError as e: + error_content = _error_message_for_unparsed_graphql_error(e.message) + raise LabelboxError(message=error_content) from e + return result["deleteProjectModelConfig"]["success"] diff --git a/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py b/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py index 53e1686fe..d48514024 100644 --- a/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py +++ b/libs/labelbox/tests/integration/test_project_set_model_setup_complete.py @@ -19,6 +19,31 @@ def test_live_chat_evaluation_project( project.add_model_config(model_config.uid) +def test_live_chat_evaluation_project_delete_cofig( + live_chat_evaluation_project_with_new_dataset, model_config): + + project = live_chat_evaluation_project_with_new_dataset + project_model_config_id = project.add_model_config(model_config.uid) + assert project_model_config_id + + project_model_config = None + for pmg in project.project_model_configs(): + if pmg.uid == project_model_config_id: + project_model_config = pmg + break + assert project_model_config + + project.set_project_model_setup_complete() + assert bool(project.model_setup_complete) is True + + with pytest.raises( + expected_exception=LabelboxError, + match= + "Cannot create model config for project because model setup is complete" + ): + project_model_config.delete() + + def test_offline_chat_evaluation_project(offline_chat_evaluation_project, model_config): From 7ceab1e7f6a341403eee95a1f25b20400f1ea0a8 Mon Sep 17 00:00:00 2001 From: Val Brodsky Date: Wed, 19 Jun 2024 16:36:53 -0700 Subject: [PATCH 4/6] Use _create_project(), not create_project() for create_offline_model_evaluation_project Fixing a typo --- libs/labelbox/src/labelbox/client.py | 2 +- libs/labelbox/src/labelbox/exceptions.py | 5 +++++ libs/labelbox/src/labelbox/schema/project.py | 8 +++++--- libs/labelbox/tests/unit/test_exceptions.py | 13 +++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 libs/labelbox/tests/unit/test_exceptions.py diff --git a/libs/labelbox/src/labelbox/client.py b/libs/labelbox/src/labelbox/client.py index 019285350..3154c29f9 100644 --- a/libs/labelbox/src/labelbox/client.py +++ b/libs/labelbox/src/labelbox/client.py @@ -840,7 +840,7 @@ def create_offline_model_evaluation_project(self, **kwargs) -> Project: kwargs.pop("append_to_existing_dataset", None) kwargs.pop("data_row_count", None) - return self.create_project(**kwargs) + return self._create_project(**kwargs) def _create_project(self, **kwargs) -> Project: auto_audit_percentage = kwargs.get("auto_audit_percentage") diff --git a/libs/labelbox/src/labelbox/exceptions.py b/libs/labelbox/src/labelbox/exceptions.py index dd3a2be4c..081b71b3a 100644 --- a/libs/labelbox/src/labelbox/exceptions.py +++ b/libs/labelbox/src/labelbox/exceptions.py @@ -153,6 +153,11 @@ class ProcessingWaitTimeout(Exception): def _error_message_for_unparsed_graphql_error(error_string: str) -> str: + """ + Since our client only parses certain graphql errors, this function is used to + extract the error message from the error string when the error is not + parsed by the client. + """ # Regex to find the message content pattern = r"'message': '([^']+)'" # Search for the pattern in the error string diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index 496a95cef..4818e8c1e 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -1272,8 +1272,6 @@ def add_model_config(self, model_config_id: str) -> str: try: result = self.client.execute(query, params) except LabelboxError as e: - # unfortunately, this is the type of errors our client does not deal with and so the error message is not in the same format as the other errors - # needs custom parsing error_content = _error_message_for_unparsed_graphql_error(e.message) raise LabelboxError(message=error_content) from e @@ -1305,12 +1303,16 @@ def delete_project_model_config(self, project_model_config_id: str) -> bool: return result["deleteProjectModelConfig"]["success"] def set_project_model_setup_complete(self) -> bool: - """ Checks if the model setup is complete for this project. + """ + Sets the model setup is complete for this project. + Once the project is marked as "setup complete", a user can not add / modify delete existing project model configs. Returns: bool, indicates if the model setup is complete. NOTE: This method should only be used for live model evaluation projects. + It will throw exception for all other types of projects. + User Project is_chat_evaluation() method to check if the project is a live model evaluation project. """ query = """mutation SetProjectModelSetupCompletePyApi($projectId: ID!) { setProjectModelSetupComplete(where: {id: $projectId}, data: {modelSetupComplete: true}) { diff --git a/libs/labelbox/tests/unit/test_exceptions.py b/libs/labelbox/tests/unit/test_exceptions.py new file mode 100644 index 000000000..ea96bff18 --- /dev/null +++ b/libs/labelbox/tests/unit/test_exceptions.py @@ -0,0 +1,13 @@ +import pytest + +from labelbox.exceptions import _error_message_for_unparsed_graphql_error + + +@pytest.mark.parametrize('exception_message, expected_result', [ + ("Unparsed errors on query execution: [{'message': 'Cannot create model config for project because model setup is complete'", + "Cannot create model config for project because model setup is complete"), + ("blah blah blah", "Unknown error"), +]) +def test_client_unparsed_exception_messages(exception_message, expected_result): + assert _error_message_for_unparsed_graphql_error( + exception_message) == expected_result From ffd40a4b6791712dd2e192aeb1ab07fcc981a553 Mon Sep 17 00:00:00 2001 From: Val Brodsky Date: Thu, 20 Jun 2024 11:00:57 -0700 Subject: [PATCH 5/6] A more full-proof way to handle unknown exceptions for model setup complete --- libs/labelbox/src/labelbox/schema/project.py | 8 +++++++- libs/labelbox/src/labelbox/schema/project_model_config.py | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index 4818e8c1e..7e8648d69 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -1272,7 +1272,13 @@ def add_model_config(self, model_config_id: str) -> str: try: result = self.client.execute(query, params) except LabelboxError as e: - error_content = _error_message_for_unparsed_graphql_error(e.message) + if e.message.startswith( + "Unknown error: " + ): # unfortunate hack to handle unparsed graphql errors + error_content = _error_message_for_unparsed_graphql_error( + e.message) + else: + error_content = e.message raise LabelboxError(message=error_content) from e if not result: diff --git a/libs/labelbox/src/labelbox/schema/project_model_config.py b/libs/labelbox/src/labelbox/schema/project_model_config.py index 353ce7890..c6ee796f2 100644 --- a/libs/labelbox/src/labelbox/schema/project_model_config.py +++ b/libs/labelbox/src/labelbox/schema/project_model_config.py @@ -35,7 +35,13 @@ def delete(self) -> bool: try: result = self.client.execute(query, params) except LabelboxError as e: - error_content = _error_message_for_unparsed_graphql_error(e.message) + if e.message.startswith( + "Unknown error: " + ): # unfortunate hack to handle unparsed graphql errors + error_content = _error_message_for_unparsed_graphql_error( + e.message) + else: + error_content = e.message raise LabelboxError(message=error_content) from e return result["deleteProjectModelConfig"]["success"] From 63090c40b1721a4f09fd4552b9638533caeb8e9e Mon Sep 17 00:00:00 2001 From: Val Brodsky Date: Fri, 21 Jun 2024 10:44:37 -0700 Subject: [PATCH 6/6] PR feedback + fix tests --- libs/labelbox/src/labelbox/exceptions.py | 2 +- libs/labelbox/src/labelbox/schema/project.py | 4 ++-- .../src/labelbox/schema/project_model_config.py | 4 ++-- .../tests/integration/test_project_model_config.py | 12 ++++++------ libs/labelbox/tests/unit/test_exceptions.py | 6 +++--- libs/labelbox/tests/unit/test_project.py | 1 + 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libs/labelbox/src/labelbox/exceptions.py b/libs/labelbox/src/labelbox/exceptions.py index 081b71b3a..612e7ef58 100644 --- a/libs/labelbox/src/labelbox/exceptions.py +++ b/libs/labelbox/src/labelbox/exceptions.py @@ -152,7 +152,7 @@ class ProcessingWaitTimeout(Exception): """Raised when waiting for the data rows to be processed takes longer than allowed""" -def _error_message_for_unparsed_graphql_error(error_string: str) -> str: +def error_message_for_unparsed_graphql_error(error_string: str) -> str: """ Since our client only parses certain graphql errors, this function is used to extract the error message from the error string when the error is not diff --git a/libs/labelbox/src/labelbox/schema/project.py b/libs/labelbox/src/labelbox/schema/project.py index 7e8648d69..d96485ccf 100644 --- a/libs/labelbox/src/labelbox/schema/project.py +++ b/libs/labelbox/src/labelbox/schema/project.py @@ -13,7 +13,7 @@ from labelbox import parser from labelbox import utils -from labelbox.exceptions import _error_message_for_unparsed_graphql_error +from labelbox.exceptions import error_message_for_unparsed_graphql_error from labelbox.exceptions import (InvalidQueryError, LabelboxError, ProcessingWaitTimeout, ResourceConflict, ResourceNotFoundError) @@ -1275,7 +1275,7 @@ def add_model_config(self, model_config_id: str) -> str: if e.message.startswith( "Unknown error: " ): # unfortunate hack to handle unparsed graphql errors - error_content = _error_message_for_unparsed_graphql_error( + error_content = error_message_for_unparsed_graphql_error( e.message) else: error_content = e.message diff --git a/libs/labelbox/src/labelbox/schema/project_model_config.py b/libs/labelbox/src/labelbox/schema/project_model_config.py index c6ee796f2..9cf6dcbfa 100644 --- a/libs/labelbox/src/labelbox/schema/project_model_config.py +++ b/libs/labelbox/src/labelbox/schema/project_model_config.py @@ -1,6 +1,6 @@ from labelbox.orm.db_object import DbObject from labelbox.orm.model import Field, Relationship -from labelbox.exceptions import LabelboxError, _error_message_for_unparsed_graphql_error +from labelbox.exceptions import LabelboxError, error_message_for_unparsed_graphql_error class ProjectModelConfig(DbObject): @@ -38,7 +38,7 @@ def delete(self) -> bool: if e.message.startswith( "Unknown error: " ): # unfortunate hack to handle unparsed graphql errors - error_content = _error_message_for_unparsed_graphql_error( + error_content = error_message_for_unparsed_graphql_error( e.message) else: error_content = e.message diff --git a/libs/labelbox/tests/integration/test_project_model_config.py b/libs/labelbox/tests/integration/test_project_model_config.py index 1ff5041ef..220995e27 100644 --- a/libs/labelbox/tests/integration/test_project_model_config.py +++ b/libs/labelbox/tests/integration/test_project_model_config.py @@ -3,9 +3,9 @@ from labelbox.exceptions import ResourceNotFoundError -def test_add_single_model_config(chat_evaluation_project_create_dataset, +def test_add_single_model_config(live_chat_evaluation_project_with_new_dataset, model_config): - configured_project = chat_evaluation_project_create_dataset + configured_project = live_chat_evaluation_project_with_new_dataset project_model_config_id = configured_project.add_model_config( model_config.uid) @@ -18,9 +18,9 @@ def test_add_single_model_config(chat_evaluation_project_create_dataset, def test_add_multiple_model_config(client, rand_gen, - chat_evaluation_project_create_dataset, + live_chat_evaluation_project_with_new_dataset, model_config, valid_model_id): - configured_project = chat_evaluation_project_create_dataset + configured_project = live_chat_evaluation_project_with_new_dataset second_model_config = client.create_model_config(rand_gen(str), valid_model_id, {"param": "value"}) @@ -40,9 +40,9 @@ def test_add_multiple_model_config(client, rand_gen, project_model_config_id) -def test_delete_project_model_config(chat_evaluation_project_create_dataset, +def test_delete_project_model_config(live_chat_evaluation_project_with_new_dataset, model_config): - configured_project = chat_evaluation_project_create_dataset + configured_project = live_chat_evaluation_project_with_new_dataset assert configured_project.delete_project_model_config( configured_project.add_model_config(model_config.uid)) assert not len(configured_project.project_model_configs()) diff --git a/libs/labelbox/tests/unit/test_exceptions.py b/libs/labelbox/tests/unit/test_exceptions.py index ea96bff18..69bcfbd77 100644 --- a/libs/labelbox/tests/unit/test_exceptions.py +++ b/libs/labelbox/tests/unit/test_exceptions.py @@ -1,13 +1,13 @@ import pytest -from labelbox.exceptions import _error_message_for_unparsed_graphql_error +from labelbox.exceptions import error_message_for_unparsed_graphql_error @pytest.mark.parametrize('exception_message, expected_result', [ - ("Unparsed errors on query execution: [{'message': 'Cannot create model config for project because model setup is complete'", + ("Unparsed errors on query execution: [{'message': 'Cannot create model config for project because model setup is complete'}]", "Cannot create model config for project because model setup is complete"), ("blah blah blah", "Unknown error"), ]) def test_client_unparsed_exception_messages(exception_message, expected_result): - assert _error_message_for_unparsed_graphql_error( + assert error_message_for_unparsed_graphql_error( exception_message) == expected_result diff --git a/libs/labelbox/tests/unit/test_project.py b/libs/labelbox/tests/unit/test_project.py index 9d522e7c0..c2c818291 100644 --- a/libs/labelbox/tests/unit/test_project.py +++ b/libs/labelbox/tests/unit/test_project.py @@ -31,6 +31,7 @@ def test_project_editor_task_type(api_editor_task_type, "allowedMediaType": "IMAGE", "queueMode": "BATCH", "setupComplete": "2021-06-01T00:00:00.000Z", + "modelSetupComplete": None, }) assert project.editor_task_type == expected_editor_task_type