5555from lib .core .entities .integrations import IntegrationEntity
5656from lib .core .entities .integrations import IntegrationTypeEnum
5757from lib .core .enums import ImageQuality
58+ from lib .core .enums import CustomFieldEntityEnum
5859from lib .core .enums import ProjectType
5960from lib .core .enums import ClassTypeEnum
6061from lib .core .exceptions import AppException
@@ -279,6 +280,79 @@ def get_team_metadata(self):
279280 response = self .controller .get_team ()
280281 return TeamSerializer (response .data ).serialize ()
281282
283+ def get_user_metadata (
284+ self , pk : Union [int , str ], include : List [Literal ["custom_fields" ]] = None
285+ ):
286+ """
287+ Returns user metadata
288+
289+ :param pk: The email address or ID of the team contributor.
290+ :type pk: str or int
291+
292+ :param include: Specifies additional fields to include in the response.
293+
294+ Possible values are
295+
296+ - "custom_fields": whether to include custom fields that have been created for the team user.
297+
298+ :type include: list of str, optional
299+
300+ :return: metadata of team contributor
301+ :rtype: dict
302+ """
303+ user = self .controller .work_management .get_user_metadata (pk = pk , include = include )
304+ return BaseSerializer (user ).serialize (by_alias = False )
305+
306+ def set_user_custom_field (
307+ self , pk : Union [int , str ], custom_field_name : str , value : Any
308+ ):
309+ """
310+ Set the custom field for team contributors.
311+
312+ :param pk: The email address or ID of the team contributor.
313+ :type pk: str or int
314+
315+ :param custom_field_name: the name of the custom field created for the team contributor,
316+ used to set or update its value.
317+
318+ :type custom_field_name: str
319+
320+ :param value: The value
321+ :type value: Any
322+
323+ Request Example:
324+ ::
325+ from superannotate import SAClient
326+
327+
328+ sa = SAClient()
329+
330+ client.set_user_custom_field(
331+ "example@email.com",
332+ custom_field_name="Due date",
333+ value="Dec 20, 2024"
334+ )
335+ """
336+ user_id = self .controller .work_management .get_user_metadata (pk = pk ).id
337+ self .controller .work_management .set_custom_field_value (
338+ entity_id = user_id ,
339+ field_name = custom_field_name ,
340+ value = value ,
341+ entity = CustomFieldEntityEnum .CONTRIBUTOR ,
342+ parent_entity = CustomFieldEntityEnum .TEAM ,
343+ )
344+
345+ def list_users (self , * , include : List [Literal ["custom_fields" ]] = None , ** filters ):
346+ """
347+
348+ @param include:
349+ @param filters:
350+ @return:
351+ """
352+ return BaseSerializer .serialize_iterable (
353+ self .controller .work_management .list_users (include = include , ** filters )
354+ )
355+
282356 def get_component_config (self , project : Union [NotEmptyStr , int ], component_id : str ):
283357 """
284358 Retrieves the configuration for a given project and component ID.
@@ -2903,7 +2977,7 @@ def list_items(
29032977 project : Union [NotEmptyStr , int ],
29042978 folder : Optional [Union [NotEmptyStr , int ]] = None ,
29052979 * ,
2906- include : List [Literal ["custom_metadata" , "category " ]] = None ,
2980+ include : List [Literal ["custom_metadata" , "categories " ]] = None ,
29072981 ** filters ,
29082982 ):
29092983 """
@@ -2923,6 +2997,7 @@ def list_items(
29232997 Possible values are
29242998
29252999 - "custom_metadata": Includes custom metadata attached to the item.
3000+ - "categories": Includes categories attached to the item.
29263001 :type include: list of str, optional
29273002
29283003 :param filters: Specifies filtering criteria (e.g., name, ID, annotation status),
@@ -2993,6 +3068,40 @@ def list_items(
29933068 }
29943069 ]
29953070
3071+ Request Example with include categories:
3072+ ::
3073+
3074+ client.list_items(
3075+ project="My Multimodal",
3076+ folder="folder1",
3077+ include=["categories"]
3078+ )
3079+
3080+ Response Example:
3081+ ::
3082+
3083+ [
3084+ {
3085+ "id": 48909383,
3086+ "name": "scan_123.jpeg",
3087+ "path": "Medical Annotations/folder1",
3088+ "url": "https://sa-public-files.s3.../scan_123.jpeg",
3089+ "annotation_status": "InProgress",
3090+ "createdAt": "2022-02-10T14:32:21.000Z",
3091+ "updatedAt": "2022-02-15T20:46:44.000Z",
3092+ "entropy_value": None,
3093+ "assignments": [],
3094+ "categories": [
3095+ {
3096+ "createdAt": "2025-01-29T13:51:39.000Z",
3097+ "updatedAt": "2025-01-29T13:51:39.000Z",
3098+ "id": 328577,
3099+ "name": "my_category",
3100+ },
3101+ ],
3102+ }
3103+ ]
3104+
29963105 Additional Filter Examples:
29973106 ::
29983107
@@ -3014,6 +3123,14 @@ def list_items(
30143123 if isinstance (project , int )
30153124 else self .controller .get_project (project )
30163125 )
3126+ if (
3127+ include
3128+ and "categories" in include
3129+ and project .type != ProjectType .MULTIMODAL .value
3130+ ):
3131+ raise AppException (
3132+ "The 'categories' option in the 'include' field is only supported for Multimodal projects."
3133+ )
30173134 if folder is None :
30183135 folder = self .controller .get_folder (project , "root" )
30193136 else :
@@ -3088,6 +3205,7 @@ def list_projects(
30883205 - status__in: List[Literal[“NotStarted”, “InProgress”, “Completed”, “OnHold”]]
30893206 - status__notin: List[Literal[“NotStarted”, “InProgress”, “Completed”, “OnHold”]]
30903207 - custom_field: Optional[dict] – Specifies custom fields attributes to filter projects by.
3208+
30913209 Custom fields can be accessed using the `custom_field__` prefix followed by the attribute name.
30923210
30933211 :type filters: ProjectFilters
0 commit comments