Skip to content

Commit 96d2e84

Browse files
authored
Merge pull request #802 from superannotateai/fix_categories
add categories arg validation
2 parents bcfd982 + e96f058 commit 96d2e84

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

src/superannotate/lib/app/interface/sdk_interface.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,7 @@ def set_contributors_categories(
867867
self,
868868
project: Union[NotEmptyStr, int],
869869
contributors: List[Union[int, str]],
870-
categories: Union[List[str], Literal["*"]],
870+
categories: Union[List[NotEmptyStr], Literal["*"]],
871871
):
872872
"""
873873
Assign one or more categories to a contributor with an assignable role (Annotator, QA or custom role)
@@ -899,6 +899,9 @@ def set_contributors_categories(
899899
categories="*"
900900
)
901901
"""
902+
if not categories:
903+
AppException("Categories should be a list of strings or '*'.")
904+
902905
project = (
903906
self.controller.get_project_by_id(project).data
904907
if isinstance(project, int)
@@ -917,7 +920,7 @@ def remove_contributors_categories(
917920
self,
918921
project: Union[NotEmptyStr, int],
919922
contributors: List[Union[int, str]],
920-
categories: Union[List[str], Literal["*"]],
923+
categories: Union[List[NotEmptyStr], Literal["*"]],
921924
):
922925
"""
923926
Remove one or more categories for a contributor. "*" in the category list will match all categories defined in the project.
@@ -946,6 +949,9 @@ def remove_contributors_categories(
946949
categories="*"
947950
)
948951
"""
952+
if not categories:
953+
AppException("Categories should be a list of strings or '*'.")
954+
949955
project = (
950956
self.controller.get_project_by_id(project).data
951957
if isinstance(project, int)
@@ -1297,7 +1303,7 @@ def clone_project(
12971303
return data
12981304

12991305
def create_categories(
1300-
self, project: Union[NotEmptyStr, int], categories: List[str]
1306+
self, project: Union[NotEmptyStr, int], categories: List[NotEmptyStr]
13011307
):
13021308
"""
13031309
Create one or more categories in a project.
@@ -1316,6 +1322,9 @@ def create_categories(
13161322
categories=["Shoes", "T-Shirt"]
13171323
)
13181324
"""
1325+
if not categories:
1326+
raise AppException("Categories should be a list of strings.")
1327+
13191328
project = (
13201329
self.controller.get_project_by_id(project).data
13211330
if isinstance(project, int)
@@ -1387,7 +1396,7 @@ def list_categories(self, project: Union[NotEmptyStr, int]):
13871396
def remove_categories(
13881397
self,
13891398
project: Union[NotEmptyStr, int],
1390-
categories: Union[List[str], Literal["*"]],
1399+
categories: Union[List[NotEmptyStr], Literal["*"]],
13911400
):
13921401
"""
13931402
Remove one or more categories in a project. "*" in the category list will match all categories defined in the project.
@@ -1413,14 +1422,16 @@ def remove_categories(
14131422
categories="*"
14141423
)
14151424
"""
1425+
if not categories:
1426+
AppException("Categories should be a list of strings or '*'.")
1427+
14161428
project = (
14171429
self.controller.get_project_by_id(project).data
14181430
if isinstance(project, int)
14191431
else self.controller.get_project(project)
14201432
)
14211433
self.controller.check_multimodal_project_categorization(project)
14221434

1423-
categories_to_remove = None
14241435
query = EmptyQuery()
14251436
if categories == "*":
14261437
query &= Filter("id", [0], OperatorEnum.GT)
@@ -1432,17 +1443,21 @@ def remove_categories(
14321443
categories_to_remove = [
14331444
c for c in all_categories.data if c.name.lower() in categories
14341445
]
1435-
query &= Filter("id", [c.id for c in categories_to_remove], OperatorEnum.IN)
1446+
if categories_to_remove:
1447+
query &= Filter(
1448+
"id", [c.id for c in categories_to_remove], OperatorEnum.IN
1449+
)
14361450
else:
14371451
raise AppException("Categories should be a list of strings or '*'.")
14381452

1439-
if categories_to_remove:
1453+
if query.condition_set:
14401454
response = self.controller.service_provider.work_management.remove_project_categories(
14411455
project_id=project.id, query=query
14421456
)
1443-
logger.info(
1444-
f"{len(response.data)} categories successfully removed from the project."
1445-
)
1457+
if response.data:
1458+
logger.info(
1459+
f"{len(response.data)} categories successfully removed from the project."
1460+
)
14461461

14471462
def create_folder(self, project: NotEmptyStr, folder_name: NotEmptyStr):
14481463
"""
@@ -4497,7 +4512,7 @@ def set_items_category(
44974512
self,
44984513
project: Union[NotEmptyStr, Tuple[int, int], Tuple[str, str]],
44994514
items: List[Union[int, str]],
4500-
category: str,
4515+
category: NotEmptyStr,
45014516
):
45024517
"""
45034518
Add categories to one or more items.

tests/integration/work_management/test_project_categories.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pathlib import Path
55
from unittest import TestCase
66

7+
from lib.core.exceptions import AppException
78
from src.superannotate import SAClient
89

910
sa = SAClient()
@@ -144,3 +145,22 @@ def test_delete_all_categories_with_asterisk(self):
144145
sa.remove_categories(project=self.PROJECT_NAME, categories="*")
145146
categories = sa.list_categories(project=self.PROJECT_NAME)
146147
assert len(categories) == 0
148+
149+
def test_delete_categories_with_empty_list(self):
150+
with self.assertRaisesRegexp(
151+
AppException, "Categories should be a list of strings or '*'"
152+
):
153+
sa.remove_categories(project=self.PROJECT_NAME, categories=[])
154+
155+
def test_delete_invalid_categories(self):
156+
# silent skip
157+
sa.remove_categories(
158+
project=self.PROJECT_NAME,
159+
categories=["invalid_category_1", "invalid_category_2"],
160+
)
161+
162+
def test_create_categories_with_empty_categories(self):
163+
with self.assertRaisesRegexp(
164+
AppException, "Categories should be a list of strings."
165+
):
166+
sa.create_categories(project=self.PROJECT_NAME, categories=[])

0 commit comments

Comments
 (0)