6060from lib .core .types import MLModel
6161from lib .core .types import PriorityScoreEntity
6262
63- from lib .core .pydantic_v1 import ValidationError
6463from lib .core .pydantic_v1 import constr
6564from lib .core .pydantic_v1 import conlist
6665from lib .core .pydantic_v1 import parse_obj_as
6766from lib .infrastructure .utils import extract_project_folder
68- from lib .infrastructure .validators import wrap_error
6967
7068from superannotate_core .core .entities import BaseItemEntity
7169from superannotate_core .app import Project , Folder
@@ -743,7 +741,9 @@ def get_project_workflow(self, project: Union[str, dict]):
743741 return workflow .data
744742
745743 def search_annotation_classes (
746- self , project : Union [NotEmptyStr , dict ], name_contains : Optional [str ] = None
744+ self ,
745+ project : Union [NotEmptyStr , dict , Project ],
746+ name_contains : Optional [str ] = None ,
747747 ):
748748 """Searches annotation classes by name_prefix (case-insensitive)
749749
@@ -757,17 +757,20 @@ def search_annotation_classes(
757757 :return: annotation classes of the project
758758 :rtype: list of dicts
759759 """
760- project_name , folder_name = extract_project_folder (project )
760+ if isinstance (project , Project ):
761+ project = project .dict ()
762+
763+ project_name , _ = extract_project_folder (project )
761764 project = self .controller .get_project (project_name )
762- condition = Condition ( "project_id" , project . id , EQ )
763- if name_contains :
764- condition &= Condition ( "name" , name_contains , EQ ) & Condition (
765- "pattern" , True , EQ
766- )
767- response = self . controller . annotation_classes . list ( condition )
768- if response . errors :
769- raise AppException ( response . errors )
770- return response . data
765+ condition = (
766+ Condition ( "name" , name_contains , EQ ) & Condition ( "pattern" , True , EQ )
767+ if name_contains
768+ else None
769+ )
770+ return [
771+ annotation_class . dict ()
772+ for annotation_class in project . list_annotation_classes ( condition )
773+ ]
771774
772775 def set_project_status (self , project : NotEmptyStr , status : PROJECT_STATUS ):
773776 """Set project status
@@ -1353,8 +1356,7 @@ def upload_video_to_project(
13531356
13541357 def create_annotation_class (
13551358 self ,
1356- # todo project: Union[Project, NotEmptyStr],
1357- project : Union [NotEmptyStr ],
1359+ project : Union [NotEmptyStr , dict , Project ],
13581360 name : NotEmptyStr ,
13591361 color : NotEmptyStr ,
13601362 attribute_groups : Optional [List [AttributeGroupSchema ]] = None ,
@@ -1447,38 +1449,41 @@ def create_annotation_class(
14471449 )
14481450
14491451 """
1450- # todo if isinstance(project, Project):
1451- # if isinstance(project, Project):
1452- # project = project.dict()
1453- _class_type = ClassTypeEnum (class_type )
1454- # try:
1455- # annotation_class = AnnotationClass(
1456- # {
1457- # "name": name,
1458- # "color": color,
1459- # "type": ClassTypeEnum(class_type),
1460- # "attribute_groups": attribute_groups,
1461- # }
1462- # )
1463- # except ValidationError as e:
1464- # raise AppException(wrap_error(e))
1465- project = self .controller .get_project (project )
1452+ if isinstance (project , Project ):
1453+ project = project .dict ()
1454+
1455+ project_name , _ = extract_project_folder (project )
1456+ project = self .controller .get_project (project_name )
1457+
1458+ if project .type == ProjectType .Pixel .value and any (
1459+ "default_value" in attr_group .keys () for attr_group in attribute_groups
1460+ ):
1461+ raise AppException (
1462+ 'The "default_value" key is not supported for project type Pixel.'
1463+ )
1464+
1465+ _class_type = ClassTypeEnum .get_value (class_type )
14661466 if (
14671467 project .type != ProjectType .Document
1468- and _class_type == ClassTypeEnum .RELATIONSHIP
1468+ and _class_type == ClassTypeEnum .relationship
14691469 ):
14701470 raise AppException (
14711471 f"{ class_type } class type is not supported in { project .type .name } project."
14721472 )
1473- project .create_annotation_class (
1473+ annotation_class = project .create_annotation_class (
14741474 name = name ,
14751475 color = color ,
14761476 class_type = _class_type ,
14771477 attribute_groups = attribute_groups ,
14781478 )
1479+ if annotation_class :
1480+ return annotation_class .dict ()
1481+ raise AppException ("Failed to create annotation class" )
14791482
14801483 def delete_annotation_class (
1481- self , project : NotEmptyStr , annotation_class : Union [dict , NotEmptyStr ]
1484+ self ,
1485+ project : Union [NotEmptyStr , dict , Project ],
1486+ annotation_class : Union [dict , NotEmptyStr ],
14821487 ):
14831488 """Deletes annotation class from project
14841489
@@ -1489,24 +1494,32 @@ def delete_annotation_class(
14891494 :type annotation_class: str or dict
14901495 """
14911496
1492- if isinstance (annotation_class , str ):
1493- try :
1494- annotation_class = AnnotationClassEntity (
1495- name = annotation_class ,
1496- color = "#ffffff" , # noqa Random, just need to serialize
1497- )
1498- except ValidationError as e :
1499- raise AppException (wrap_error (e ))
1497+ if isinstance (annotation_class , dict ) and "name" in annotation_class .keys ():
1498+ class_name = annotation_class ["name" ]
1499+ elif isinstance (annotation_class , str ):
1500+ class_name = annotation_class
15001501 else :
1501- annotation_class = AnnotationClassEntity (** annotation_class )
1502- project = self .controller .projects .get_by_name (project ).data
1502+ raise AppException ("Invalid value provided for annotation_class." )
15031503
1504- self .controller .annotation_classes .delete (
1505- project = project , annotation_class = annotation_class
1506- )
1504+ if isinstance (project , Project ):
1505+ project = project .dict ()
1506+
1507+ project_name , _ = extract_project_folder (project )
1508+ project = self .controller .get_project (project_name )
1509+
1510+ condition = Condition ("name" , class_name , EQ ) & Condition ("pattern" , True , EQ )
1511+ annotation_classes = project .list_annotation_classes (condition = condition )
1512+ if annotation_classes :
1513+ class_to_delete = annotation_classes [0 ]
1514+ logger .info (
1515+ "Deleting annotation class from project %s with name %s" ,
1516+ project .name ,
1517+ class_to_delete .name ,
1518+ )
1519+ project .delete_annotation_class (class_id = class_to_delete .id )
15071520
15081521 def download_annotation_classes_json (
1509- self , project : NotEmptyStr , folder : Union [str , Path ]
1522+ self , project : Union [ NotEmptyStr , dict , Project ] , folder : Union [str , Path ]
15101523 ):
15111524 """Downloads project classes.json to folder
15121525
@@ -1519,20 +1532,28 @@ def download_annotation_classes_json(
15191532 :return: path of the download file
15201533 :rtype: str
15211534 """
1535+ if isinstance (project , Project ):
1536+ project = project .dict ()
15221537
1523- project = self .controller .projects .get_by_name (project ).data
1524- response = self .controller .annotation_classes .download (
1525- project = project , download_path = folder
1538+ project_name , _ = extract_project_folder (project )
1539+ project = self .controller .get_project (project_name )
1540+ logger .info (
1541+ f"Downloading classes.json from project { project .name } to folder { str (folder )} ."
15261542 )
1527- if response .errors :
1528- raise AppException (response .errors )
1529- return response .data
1543+ annotation_classes : List [dict ] = [
1544+ annotation_class .dict ()
1545+ for annotation_class in project .list_annotation_classes ()
1546+ ]
1547+ json_path = f"{ folder } /classes.json"
1548+ with open (json_path , "w" ) as f :
1549+ json .dump (annotation_classes , f , indent = 4 )
1550+ return json_path
15301551
15311552 def create_annotation_classes_from_classes_json (
15321553 self ,
1533- project : Union [NotEmptyStr , dict ],
1554+ project : Union [NotEmptyStr , dict , Project ],
15341555 classes_json : Union [List [AnnotationClassEntity ], str , Path ],
1535- from_s3_bucket = False ,
1556+ from_s3_bucket : str = None ,
15361557 ):
15371558 """Creates annotation classes in project from a SuperAnnotate format
15381559 annotation classes.json.
@@ -1549,7 +1570,7 @@ def create_annotation_classes_from_classes_json(
15491570 :return: list of created annotation class metadatas
15501571 :rtype: list of dicts
15511572 """
1552- if isinstance (classes_json , str ) or isinstance ( classes_json , Path ):
1573+ if isinstance (classes_json , ( str , Path ) ):
15531574 if from_s3_bucket :
15541575 from_session = boto3 .Session ()
15551576 from_s3 = from_session .resource ("s3" )
@@ -1561,12 +1582,12 @@ def create_annotation_classes_from_classes_json(
15611582 else :
15621583 data = open (classes_json , encoding = "utf-8" )
15631584 classes_json = json .load (data )
1564- # try:
1565- # # annotation_classes = parse_obj_as(List[AnnotationClassEntity], classes_json)
1566- # annotation_classes = [AnnotationClassEntity.from_json(i) for i in classes_json]
1567- # except ValidationError as _:
1568- # raise AppException("Couldn't validate annotation classes." )
1569- project = self .controller .get_project (project )
1585+
1586+ if isinstance ( project , Project ):
1587+ project = project . dict ()
1588+
1589+ project_name , _ = extract_project_folder ( project )
1590+ project = self .controller .get_project (project_name )
15701591 annotation_classes = project .create_annotation_classes (classes_json )
15711592 return [i .dict () for i in annotation_classes ]
15721593
@@ -1684,7 +1705,10 @@ def download_image(
16841705 return response .data
16851706
16861707 def upload_annotations (
1687- self , project : NotEmptyStr , annotations : List [dict ], keep_status : bool = False
1708+ self ,
1709+ project : Union [NotEmptyStr , dict ],
1710+ annotations : List [dict ],
1711+ keep_status : bool = False ,
16881712 ):
16891713 """Uploads a list of annotation dicts as annotations to the SuperAnnotate directory.
16901714
0 commit comments