Skip to content

Commit 1b7a1e1

Browse files
authored
Merge pull request #784 from superannotateai/develop
Develop
2 parents adbb635 + 1bffede commit 1b7a1e1

22 files changed

+334
-166
lines changed

CHANGELOG.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ History
66

77
All release highlights of this project will be documented in this file.
88

9+
4.4.34 - April 11, 2025
10+
______________________
11+
12+
**Added**
13+
14+
- ``SAClient.get_integrations`` Added id, createdAt, updatedAt, and creator_id in integration metadata.
15+
- ``SAClient.list_workflows`` Retrieves all workflows for your team along with their metadata.
16+
17+
**Updated**
18+
- ``SAClient.get_project_metadata``
19+
20+
**Removed**
21+
- ``SAClient.get_project_workflow``
22+
- ``SAClient.set_project_workflow``
23+
924
4.4.33 - April 1, 2025
1025
______________________
1126

docs/source/api_reference/api_project.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,4 @@ Projects
2626
.. automethod:: superannotate.SAClient.set_project_default_image_quality_in_editor
2727
.. automethod:: superannotate.SAClient.set_project_steps
2828
.. automethod:: superannotate.SAClient.get_project_steps
29-
.. automethod:: superannotate.SAClient.set_project_workflow
30-
.. automethod:: superannotate.SAClient.get_project_workflow
3129
.. automethod:: superannotate.SAClient.get_component_config

docs/source/api_reference/api_team.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Team
44

55

66
.. automethod:: superannotate.SAClient.get_team_metadata
7+
.. automethod:: superannotate.SAClient.list_workflows
78
.. automethod:: superannotate.SAClient.get_integrations
89
.. automethod:: superannotate.SAClient.invite_contributors_to_team
910
.. automethod:: superannotate.SAClient.search_team_contributors

pytest.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ minversion = 3.7
33
log_cli=true
44
python_files = test_*.py
55
;pytest_plugins = ['pytest_profiling']
6-
addopts = -n 6 --dist loadscope
6+
;addopts = -n 6 --dist loadscope

src/superannotate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import sys
44

55

6-
__version__ = "4.4.33"
6+
__version__ = "4.4.34"
77

88

99
os.environ.update({"sa_version": __version__})

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

Lines changed: 106 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
from lib.infrastructure.validators import wrap_error
7373
from lib.app.serializers import WMProjectSerializer
7474
from lib.core.entities.work_managament import WMUserTypeEnum
75+
from lib.core.jsx_conditions import EmptyQuery
76+
7577

7678
logger = logging.getLogger("sa")
7779

@@ -211,7 +213,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
211213
return True
212214

213215
def save(self):
214-
if len(json.dumps(self.annotation).encode("utf-8")) > 16 * 1024 * 1024:
216+
if len(json.dumps(self.annotation).encode("utf-8")) > 15 * 1024 * 1024:
215217
self._set_large_annotation_adapter(self.annotation)
216218
else:
217219
self._set_small_annotation_adapter(self.annotation)
@@ -1354,7 +1356,7 @@ def get_project_metadata(
13541356
the key "settings"
13551357
:type include_settings: bool
13561358
1357-
:param include_workflow: Deprecated
1359+
:param include_workflow: Returns workflow metadata
13581360
:type include_workflow: bool
13591361
13601362
:param include_contributors: enables project contributors output under
@@ -1377,6 +1379,7 @@ def get_project_metadata(
13771379
13781380
client.get_project_metadata(
13791381
project="Medical Annotations",
1382+
include_workflow=True,
13801383
include_custom_fields=True
13811384
)
13821385
@@ -1385,50 +1388,53 @@ def get_project_metadata(
13851388
::
13861389
13871390
{
1388-
"classes": [],
1389-
"completed_items_count": None,
1390-
"contributors": [],
13911391
"createdAt": "2025-02-04T12:04:01+00:00",
1392+
"updatedAt": "2024-02-04T12:04:01+00:00",
1393+
"id": 902174,
1394+
"team_id": 233435,
1395+
"name": "Medical Annotations",
1396+
"type": "Vector",
1397+
"description": "DESCRIPTION",
1398+
"instructions_link": None,
13921399
"creator_id": "ecample@email.com",
1400+
"entropy_status": 1,
1401+
"sharing_status": None,
1402+
"status": "NotStarted",
1403+
"folder_id": 1191383,
1404+
"workflow_id": 1,
1405+
"workflow": {
1406+
"createdAt": "2024-09-03T12:48:09+00:00",
1407+
"updatedAt": "2024-09-03T12:48:09+00:00",
1408+
"id": 1,
1409+
"name": "System workflow",
1410+
"type": "system",
1411+
"description": "This workflow is generated by the system, and prevents annotators from completing items.",
1412+
"raw_config": {"roles": ["Annotator", "QA"], ...}
1413+
},
1414+
"upload_state": "INITIAL",
1415+
"users": [],
1416+
"contributors": [],
1417+
"settings": [],
1418+
"classes": [],
1419+
"item_count": None,
1420+
"completed_items_count": None,
1421+
"root_folder_completed_items_count": None,
13931422
"custom_fields": {
13941423
"Notes": "Something",
13951424
"Ann Quality threshold": 80,
13961425
"Tag": ["Tag1", "Tag2", "Tag3"],
13971426
"Due date": 1738281600.0,
13981427
"Other_Custom_Field": None,
1399-
},
1400-
"description": "DESCRIPTION",
1401-
"entropy_status": 1,
1402-
"folder_id": 1191383,
1403-
"id": 902174,
1404-
"instructions_link": None,
1405-
"item_count": None,
1406-
"name": "Medical Annotations",
1407-
"root_folder_completed_items_count": None,
1408-
"settings": [],
1409-
"sharing_status": None,
1410-
"status": "NotStarted",
1411-
"team_id": 233435,
1412-
"type": "Vector",
1413-
"updatedAt": "2024-02-04T12:04:01+00:00",
1414-
"upload_state": "INITIAL",
1415-
"users": [],
1416-
"workflow_id": 1,
1428+
}
14171429
}
14181430
"""
14191431
project_name, _ = extract_project_folder(project)
14201432
project = self.controller.get_project(project_name)
1421-
if include_workflow:
1422-
warnings.warn(
1423-
DeprecationWarning(
1424-
"The “include_workflow” parameter is deprecated."
1425-
" Please use the “get_project_steps” function instead."
1426-
)
1427-
)
14281433
response = self.controller.projects.get_metadata(
14291434
project,
14301435
include_annotation_classes,
14311436
include_settings,
1437+
include_workflow,
14321438
include_contributors,
14331439
include_complete_item_count,
14341440
include_custom_fields,
@@ -1464,18 +1470,6 @@ def get_project_settings(self, project: Union[NotEmptyStr, dict]):
14641470
]
14651471
return settings
14661472

1467-
def get_project_workflow(self, project: Union[str, dict]):
1468-
"""
1469-
Deprecated
1470-
"""
1471-
warnings.warn(
1472-
DeprecationWarning(
1473-
"The “get_project_workflow” function is deprecated."
1474-
" Please use the “get_project_steps” function instead."
1475-
)
1476-
)
1477-
return self.get_project_steps(project)
1478-
14791473
def get_project_steps(self, project: Union[str, dict]):
14801474
"""Gets project's steps.
14811475
@@ -1509,10 +1503,10 @@ def get_project_steps(self, project: Union[str, dict]):
15091503
"""
15101504
project_name, _ = extract_project_folder(project)
15111505
project = self.controller.get_project(project_name)
1512-
workflow = self.controller.projects.list_workflow(project)
1513-
if workflow.errors:
1514-
raise AppException(workflow.errors)
1515-
return workflow.data
1506+
steps = self.controller.projects.list_steps(project)
1507+
if steps.errors:
1508+
raise AppException(steps.errors)
1509+
return steps.data
15161510

15171511
def search_annotation_classes(
15181512
self, project: Union[NotEmptyStr, dict], name_contains: Optional[str] = None
@@ -2502,19 +2496,6 @@ def download_export(
25022496
if response.errors:
25032497
raise AppException(response.errors)
25042498

2505-
def set_project_workflow(
2506-
self, project: Union[NotEmptyStr, dict], new_workflow: List[dict]
2507-
):
2508-
"""
2509-
Deprecated
2510-
"""
2511-
warnings.warn(
2512-
DeprecationWarning(
2513-
"The “set_project_workflow” function is deprecated. Please use the “set_project_steps” function instead."
2514-
)
2515-
)
2516-
return self.set_project_steps(project, new_workflow)
2517-
25182499
def set_project_steps(self, project: Union[NotEmptyStr, dict], steps: List[dict]):
25192500
"""Sets project's steps.
25202501
@@ -2548,7 +2529,7 @@ def set_project_steps(self, project: Union[NotEmptyStr, dict], steps: List[dict]
25482529
"""
25492530
project_name, _ = extract_project_folder(project)
25502531
project = self.controller.get_project(project_name)
2551-
response = self.controller.projects.set_workflows(project, steps=steps)
2532+
response = self.controller.projects.set_steps(project, steps=steps)
25522533
if response.errors:
25532534
raise AppException(response.errors)
25542535

@@ -3273,14 +3254,33 @@ def get_integrations(self):
32733254
32743255
:return: metadata objects of all integrations of the team.
32753256
:rtype: list of dicts
3257+
3258+
Request Example:
3259+
::
3260+
3261+
client.get_integrations()
3262+
3263+
3264+
Response Example:
3265+
::
3266+
3267+
[
3268+
{
3269+
"createdAt": "2023-11-27T11:16:02.000Z",
3270+
"id": 5072,
3271+
"name": "My S3 Bucket",
3272+
"root": "test-openseadragon-1212",
3273+
"type": "aws",
3274+
"updatedAt": "2023-12-27T11:16:02.000Z",
3275+
"creator_id": "example@superannotate.com"
3276+
}
3277+
]
32763278
"""
32773279
response = self.controller.integrations.list()
32783280
if response.errors:
32793281
raise AppException(response.errors)
32803282
integrations = response.data
3281-
return BaseSerializer.serialize_iterable(
3282-
integrations, ("name", "type", "root") # noqa
3283-
)
3283+
return BaseSerializer.serialize_iterable(integrations)
32843284

32853285
def attach_items_from_integrated_storage(
32863286
self,
@@ -4783,3 +4783,46 @@ def item_context(
47834783
item=_item,
47844784
overwrite=overwrite,
47854785
)
4786+
4787+
def list_workflows(self):
4788+
"""
4789+
Lists team’s all workflows and their metadata
4790+
4791+
:return: metadata of workflows
4792+
:rtype: list of dicts
4793+
4794+
4795+
Request Example:
4796+
::
4797+
4798+
client.list_workflows()
4799+
4800+
4801+
Response Example:
4802+
::
4803+
4804+
[
4805+
{
4806+
"createdAt": "2024-09-03T12:48:09+00:00",
4807+
"updatedAt": "2024-09-04T12:48:09+00:00",
4808+
"id": 1,
4809+
"name": "System workflow",
4810+
"type": "system",
4811+
"description": "This workflow is generated by the system, and prevents annotators from completing items.",
4812+
"raw_config": {"roles": ["Annotator", "QA"], ...}
4813+
},
4814+
{
4815+
"createdAt": "2025-01-03T12:48:09+00:00",
4816+
"updatedAt": "2025-01-05T12:48:09+00:00",
4817+
"id": 58758,
4818+
"name": "Custom workflow",
4819+
"type": "user",
4820+
"description": "This workflow custom build.",
4821+
"raw_config": {"roles": ["Custom Annotator", "Custom QA"], ...}
4822+
}
4823+
]
4824+
"""
4825+
workflows = self.controller.service_provider.work_management.list_workflows(
4826+
EmptyQuery()
4827+
)
4828+
return BaseSerializer.serialize_iterable(workflows.data)

src/superannotate/lib/core/entities/integrations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
class IntegrationEntity(TimedBaseModel):
1313
id: int = None
14-
user_id: str = None
14+
creator_id: str = None
1515
name: str
1616
type: IntegrationTypeEnum = Field(None, alias="source")
1717
root: str = Field(None, alias="bucket_name")

src/superannotate/lib/core/entities/project.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,20 @@ class Config:
8888
extra = Extra.ignore
8989

9090

91+
class WorkflowEntity(TimedBaseModel):
92+
id: Optional[int]
93+
name: Optional[str]
94+
type: Optional[str]
95+
description: Optional[str]
96+
raw_config: Optional[dict]
97+
98+
def is_system(self):
99+
return self.type == "system"
100+
101+
class Config:
102+
extra = Extra.ignore
103+
104+
91105
class ProjectEntity(TimedBaseModel):
92106
id: Optional[int]
93107
team_id: Optional[int]
@@ -101,6 +115,7 @@ class ProjectEntity(TimedBaseModel):
101115
status: Optional[ProjectStatus]
102116
folder_id: Optional[int]
103117
workflow_id: Optional[int]
118+
workflow: Optional[WorkflowEntity]
104119
sync_status: Optional[int]
105120
upload_state: Optional[int]
106121
users: Optional[List[ContributorEntity]] = []
@@ -175,15 +190,3 @@ class CustomFieldEntity(BaseModel):
175190

176191
class Config:
177192
extra = Extra.allow
178-
179-
180-
class WorkflowEntity(BaseModel):
181-
id: Optional[int]
182-
name: Optional[str]
183-
type: Optional[str]
184-
185-
def is_system(self):
186-
return self.type == "system"
187-
188-
class Config:
189-
extra = Extra.ignore

src/superannotate/lib/core/serviceproviders.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,15 @@ def set_settings(
261261
raise NotImplementedError
262262

263263
@abstractmethod
264-
def list_workflows(self, project: entities.ProjectEntity):
264+
def list_steps(self, project: entities.ProjectEntity):
265265
raise NotImplementedError
266266

267267
@abstractmethod
268-
def set_workflow(
269-
self, project: entities.ProjectEntity, workflow: entities.WorkflowEntity
270-
):
268+
def set_step(self, project: entities.ProjectEntity, step: entities.StepEntity):
271269
raise NotImplementedError
272270

273271
@abstractmethod
274-
def set_workflows(self, project: entities.ProjectEntity, steps: list):
272+
def set_steps(self, project: entities.ProjectEntity, steps: list):
275273
raise NotImplementedError
276274

277275
@abstractmethod
@@ -283,7 +281,7 @@ def un_share(self, project: entities.ProjectEntity, user_id) -> ServiceResponse:
283281
raise NotImplementedError
284282

285283
@abstractmethod
286-
def set_project_workflow_attributes(
284+
def set_project_step_attributes(
287285
self, project: entities.ProjectEntity, attributes: list
288286
):
289287
raise NotImplementedError

0 commit comments

Comments
 (0)