@@ -1973,6 +1973,118 @@ def search_annotation_classes(
19731973 raise AppException (response .errors )
19741974 return BaseSerializer .serialize_iterable (response .data )
19751975
1976+ def update_annotation_class (
1977+ self ,
1978+ project : Union [NotEmptyStr , int ],
1979+ name : NotEmptyStr ,
1980+ attribute_groups : List [dict ],
1981+ ):
1982+ """Updates an existing annotation class by submitting a full, updated attribute_groups payload.
1983+ You can add new attribute groups, add new attribute values, rename attribute groups, rename attribute values,
1984+ delete attribute groups, delete attribute values, update attribute group types, update default attributes,
1985+ and update the required state.
1986+
1987+ .. warning::
1988+ This operation replaces the entire attribute group structure of the annotation class.
1989+ Any attribute groups or attribute values omitted from the payload will be permanently removed.
1990+ Existing annotations that reference removed attribute groups or attributes will lose their associated values.
1991+
1992+ :param project: The name or ID of the project.
1993+ :type project: Union[str, int]
1994+
1995+ :param name: The name of the annotation class to update.
1996+ :type name: str
1997+
1998+ :param attribute_groups: The full list of attribute groups for the class.
1999+ Each attribute group may contain:
2000+
2001+ - id (optional, required for existing groups)
2002+ - group_type (required): "radio", "checklist", "text", "numeric", or "ocr"
2003+ - name (required)
2004+ - isRequired (optional)
2005+ - default_value (optional)
2006+ - attributes (required, list)
2007+
2008+ Each attribute may contain:
2009+
2010+ - id (optional, required for existing attributes)
2011+ - name (required)
2012+
2013+ :type attribute_groups: list of dicts
2014+
2015+ Request Example:
2016+ ::
2017+
2018+ # Retrieve existing annotation class
2019+ classes = client.search_annotation_classes(project="Medical Project", name="Organ")
2020+ existing_class = classes[0]
2021+
2022+ # Modify attribute groups
2023+ updated_groups = existing_class["attribute_groups"]
2024+
2025+ # Add a new attribute to an existing group
2026+ updated_groups[0]["attributes"].append({"name": "Kidney"})
2027+
2028+ # Add a new attribute group
2029+ updated_groups.append({
2030+ "group_type": "radio",
2031+ "name": "Severity",
2032+ "attributes": [
2033+ {"name": "Mild"},
2034+ {"name": "Moderate"},
2035+ {"name": "Severe"}
2036+ ],
2037+ "default_value": "Mild"
2038+ })
2039+
2040+ # Update the annotation class
2041+ client.update_annotation_class(
2042+ project="Medical Project",
2043+ name="Organ",
2044+ attribute_groups=updated_groups
2045+ )
2046+ """
2047+ project = self .controller .get_project (project )
2048+
2049+ # Find the annotation class by nam
2050+ annotation_classes = self .controller .annotation_classes .list (
2051+ condition = Condition ("project_id" , project .id , EQ )
2052+ ).data
2053+
2054+ annotation_class = next (
2055+ (c for c in annotation_classes if c ["name" ] == name ), None
2056+ )
2057+
2058+ if not annotation_class :
2059+ raise AppException ("Annotation class not found in project." )
2060+
2061+ # Parse and validate attribute groups
2062+ annotation_class ["attributeGroups" ] = attribute_groups
2063+ for group in annotation_class ["attributeGroups" ]:
2064+ if "isRequired" in group :
2065+ group ["is_required" ] = group .pop ("isRequired" )
2066+
2067+ from lib .core .entities import WMAnnotationClassEntity
2068+
2069+ try :
2070+ # validate annotation class
2071+ annotation_class = WMAnnotationClassEntity .parse_obj (
2072+ BaseSerializer (annotation_class ).serialize ()
2073+ )
2074+ except ValidationError as e :
2075+ raise AppException (wrap_error (e ))
2076+
2077+ # Update the annotation class with new attribute groups
2078+
2079+ response = self .controller .annotation_classes .update (
2080+ project = project , annotation_class = annotation_class
2081+ )
2082+
2083+ if response .errors :
2084+ raise AppException (response .errors )
2085+
2086+ return BaseSerializer (response .data ).serialize (by_alias = True )
2087+
19762088 def set_project_status (self , project : NotEmptyStr , status : PROJECT_STATUS ):
19772089 """Set project status
19782090
@@ -2845,7 +2957,9 @@ def create_annotation_class(
28452957 )
28462958 if response .errors :
28472959 raise AppException (response .errors )
2848- return BaseSerializer (response .data ).serialize (exclude_unset = True )
2960+ return BaseSerializer (response .data ).serialize (
2961+ exclude_unset = True , by_alias = False
2962+ )
28492963
28502964 def delete_annotation_class (
28512965 self , project : NotEmptyStr , annotation_class : Union [dict , NotEmptyStr ]
0 commit comments