superannotate 4.5.9__tar.gz → 4.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. {superannotate-4.5.9/src/superannotate.egg-info → superannotate-4.6.0}/PKG-INFO +7 -34
  2. {superannotate-4.5.9 → superannotate-4.6.0}/README.rst +4 -31
  3. {superannotate-4.5.9 → superannotate-4.6.0}/requirements.txt +2 -2
  4. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/__init__.py +1 -1
  5. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_converter.py +1 -1
  6. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/base_interface.py +7 -3
  7. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/cli_interface.py +3 -3
  8. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/sdk_interface.py +189 -169
  9. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/__init__.py +34 -0
  10. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/base.py +13 -1
  11. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/serviceproviders.py +69 -39
  12. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/__init__.py +1 -0
  13. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/annotations.py +21 -15
  14. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/projects.py +0 -18
  15. superannotate-4.6.0/src/superannotate/lib/core/usecases/work_management.py +397 -0
  16. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/controller.py +73 -29
  17. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/serviceprovider.py +20 -8
  18. superannotate-4.6.0/src/superannotate/lib/infrastructure/services/auth.py +139 -0
  19. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/http_client.py +11 -7
  20. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/work_management.py +40 -5
  21. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/utils.py +56 -14
  22. {superannotate-4.5.9 → superannotate-4.6.0/src/superannotate.egg-info}/PKG-INFO +7 -34
  23. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate.egg-info/SOURCES.txt +2 -0
  24. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate.egg-info/requires.txt +2 -2
  25. {superannotate-4.5.9 → superannotate-4.6.0}/LICENSE +0 -0
  26. {superannotate-4.5.9 → superannotate-4.6.0}/MANIFEST.in +0 -0
  27. {superannotate-4.5.9 → superannotate-4.6.0}/setup.cfg +0 -0
  28. {superannotate-4.5.9 → superannotate-4.6.0}/setup.py +0 -0
  29. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/__init__.py +0 -0
  30. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/__init__.py +0 -0
  31. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/analytics/__init__.py +0 -0
  32. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/analytics/aggregators.py +0 -0
  33. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/analytics/common.py +0 -0
  34. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/bin/__init__.py +0 -0
  35. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/bin/superannotate.py +0 -0
  36. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/common.py +0 -0
  37. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/exceptions.py +0 -0
  38. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/helpers.py +0 -0
  39. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/__init__.py +0 -0
  40. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/conversion.py +0 -0
  41. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/__init__.py +0 -0
  42. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/baseStrategy.py +0 -0
  43. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/coco_converters/__init__.py +0 -0
  44. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_api.py +0 -0
  45. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_strategies.py +0 -0
  46. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_to_sa_vector.py +0 -0
  47. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/coco_converters/sa_vector_to_coco.py +0 -0
  48. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/converters.py +0 -0
  49. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/__init__.py +0 -0
  50. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_helper.py +0 -0
  51. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_strategies.py +0 -0
  52. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_to_sa_vector.py +0 -0
  53. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/__init__.py +0 -0
  54. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/googlecloud_strategies.py +0 -0
  55. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/googlecloud_to_sa_vector.py +0 -0
  56. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/__init__.py +0 -0
  57. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_helper.py +0 -0
  58. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_to_sa_vector.py +0 -0
  59. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/sa_json_helper.py +0 -0
  60. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/__init__.py +0 -0
  61. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_strategies.py +0 -0
  62. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_to_sa_vector.py +0 -0
  63. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/__init__.py +0 -0
  64. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_helper.py +0 -0
  65. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_strategies.py +0 -0
  66. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_to_sa_vector.py +0 -0
  67. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vgg_converters/__init__.py +0 -0
  68. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_helper.py +0 -0
  69. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_strategies.py +0 -0
  70. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_to_sa_vector.py +0 -0
  71. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/voc_converters/__init__.py +0 -0
  72. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_helper.py +0 -0
  73. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_strategies.py +0 -0
  74. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_to_sa_pixel.py +0 -0
  75. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_to_sa_vector.py +0 -0
  76. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vott_converters/__init__.py +0 -0
  77. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vott_converters/vott_strategies.py +0 -0
  78. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/vott_converters/vott_to_sa_vector.py +0 -0
  79. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/yolo_converters/__init__.py +0 -0
  80. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/yolo_converters/yolo_strategies.py +0 -0
  81. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/converters/yolo_converters/yolo_to_sa_vector.py +0 -0
  82. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/export_from_sa_conversions.py +0 -0
  83. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/input_converters/import_to_sa_conversions.py +0 -0
  84. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/__init__.py +0 -0
  85. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/responses.py +0 -0
  86. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/sdk/__init__.py +0 -0
  87. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/sdk/folders.py +0 -0
  88. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/sdk/project.py +0 -0
  89. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/interface/types.py +0 -0
  90. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/app/serializers.py +0 -0
  91. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/base_usecases.py +0 -0
  92. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/conditions.py +0 -0
  93. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/config.py +0 -0
  94. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/__init__.py +0 -0
  95. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/classes.py +0 -0
  96. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/filters.py +0 -0
  97. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/folder.py +0 -0
  98. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/integrations.py +0 -0
  99. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/items.py +0 -0
  100. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/multimodal_form.py +0 -0
  101. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/project.py +0 -0
  102. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/project_entities.py +0 -0
  103. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/entities/work_managament.py +0 -0
  104. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/enums.py +0 -0
  105. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/exceptions.py +0 -0
  106. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/jsx_conditions.py +0 -0
  107. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/plugin.py +0 -0
  108. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/reporter.py +0 -0
  109. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/repositories.py +0 -0
  110. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/response.py +0 -0
  111. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/service_types.py +0 -0
  112. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/types.py +0 -0
  113. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/base.py +0 -0
  114. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/classes.py +0 -0
  115. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/custom_fields.py +0 -0
  116. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/folders.py +0 -0
  117. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/images.py +0 -0
  118. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/integrations.py +0 -0
  119. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/items.py +0 -0
  120. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/usecases/models.py +0 -0
  121. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/utils.py +0 -0
  122. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/core/video_convertor.py +0 -0
  123. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/__init__.py +0 -0
  124. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/annotation_adapter.py +0 -0
  125. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/custom_entities.py +0 -0
  126. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/helpers.py +0 -0
  127. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/query_builder.py +0 -0
  128. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/repositories.py +0 -0
  129. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/__init__.py +0 -0
  130. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/annotation.py +0 -0
  131. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/annotation_class.py +0 -0
  132. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/explore.py +0 -0
  133. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/folder.py +0 -0
  134. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/integration.py +0 -0
  135. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/item.py +0 -0
  136. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/item_service.py +0 -0
  137. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/project.py +0 -0
  138. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/services/telemetry_scoring.py +0 -0
  139. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/stream_data_handler.py +0 -0
  140. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate/lib/infrastructure/validators.py +0 -0
  141. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate.egg-info/dependency_links.txt +0 -0
  142. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate.egg-info/entry_points.txt +0 -0
  143. {superannotate-4.5.9 → superannotate-4.6.0}/src/superannotate.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: superannotate
3
- Version: 4.5.9
3
+ Version: 4.6.0
4
4
  Summary: Python SDK to SuperAnnotate platform
5
5
  Home-page: https://github.com/superannotateai/superannotate-python-sdk
6
6
  Author: SuperAnnotate AI
@@ -19,12 +19,12 @@ Description-Content-Type: text/x-rst
19
19
  License-File: LICENSE
20
20
  Requires-Dist: pydantic~=2.5
21
21
  Requires-Dist: pydantic-extra-types~=2.11
22
- Requires-Dist: aiohttp~=3.8
22
+ Requires-Dist: aiohttp~=3.14
23
23
  Requires-Dist: boto3~=1.42
24
24
  Requires-Dist: opencv-python-headless~=4.7
25
25
  Requires-Dist: plotly~=6.5
26
26
  Requires-Dist: pandas~=2.0
27
- Requires-Dist: pillow~=12.1
27
+ Requires-Dist: pillow~=12.3
28
28
  Requires-Dist: tqdm~=4.66
29
29
  Requires-Dist: requests~=2.33
30
30
  Requires-Dist: aiofiles~=25.1
@@ -66,7 +66,7 @@ Authentication
66
66
  # by environment variable SA_TOKEN
67
67
  sa_client = SAClient()
68
68
  # by token
69
- sa_client = SAClient(token='<team token>')
69
+ sa_client = SAClient(token='<API key>')
70
70
  # by config file
71
71
  # default path is ~/.superannotate/config.ini
72
72
  sa_client = SAClient(config_path='~/.superannotate/dev_config.ini')
@@ -77,8 +77,9 @@ config.ini example
77
77
  .. code-block:: python
78
78
 
79
79
  [DEFAULT]
80
- SA_TOKEN = <Token>
80
+ SA_TOKEN = <API key>
81
81
  LOGGING_LEVEL = INFO
82
+ LOGGING_PATH = /Users/username/data/superannotate_logs
82
83
 
83
84
 
84
85
  Using superannotate
@@ -89,7 +90,7 @@ Using superannotate
89
90
  from superannotate import SAClient
90
91
 
91
92
 
92
- sa_client =SAClient()
93
+ sa_client = SAClient()
93
94
 
94
95
  project = 'Dogs'
95
96
 
@@ -145,34 +146,6 @@ Windows (`Anaconda <https://www.anaconda.com/products/individual#windows>`__
145
146
  ) platforms.
146
147
 
147
148
 
148
- Supported Features
149
- ------------------
150
-
151
- - search/get/create/clone/update/delete projects
152
- - search/get/create/delete folders
153
- - assign folders to project contributors
154
- - upload items to a project from a local or AWS S3 folder
155
- - attach items by URL or from an integrated storage, meanwhile keeping them secure in your cloud provider
156
- - get integrated cloud storages
157
- - upload annotations (also from local or AWS S3 folder)
158
- - delete annotations
159
- - set items annotations statuses
160
- - get/download/export annotations from a project (also to a local or AWS S3 folder)
161
- - invite/search team contributors or add contributors to a specific project
162
- - search/get/copy/move items in a project
163
- - query items using SA Query Language
164
- - define custom metadata for items and upload custom values (query based on your custom metadata)
165
- - upload priority scores
166
- - get available subsets (sets of segregated items), query items in a subset or add items to a subset
167
- - assign or anassign items to project contributors
168
- - download an image that has been uploaded to project
169
- - search/create/download/delete project annotation classes
170
- - search/download models
171
- - run predictions
172
- - convert annotations from/to COCO format
173
- - convert annotation from VOC, SuperVisely, LabelBox, DataLoop, VGG, VoTT, SageMaker, GoogleCloud, YOLO formats
174
- - CLI commands for simple tasks
175
-
176
149
  Questions and Issues
177
150
  --------------------
178
151
 
@@ -31,7 +31,7 @@ Authentication
31
31
  # by environment variable SA_TOKEN
32
32
  sa_client = SAClient()
33
33
  # by token
34
- sa_client = SAClient(token='<team token>')
34
+ sa_client = SAClient(token='<API key>')
35
35
  # by config file
36
36
  # default path is ~/.superannotate/config.ini
37
37
  sa_client = SAClient(config_path='~/.superannotate/dev_config.ini')
@@ -42,8 +42,9 @@ config.ini example
42
42
  .. code-block:: python
43
43
 
44
44
  [DEFAULT]
45
- SA_TOKEN = <Token>
45
+ SA_TOKEN = <API key>
46
46
  LOGGING_LEVEL = INFO
47
+ LOGGING_PATH = /Users/username/data/superannotate_logs
47
48
 
48
49
 
49
50
  Using superannotate
@@ -54,7 +55,7 @@ Using superannotate
54
55
  from superannotate import SAClient
55
56
 
56
57
 
57
- sa_client =SAClient()
58
+ sa_client = SAClient()
58
59
 
59
60
  project = 'Dogs'
60
61
 
@@ -110,34 +111,6 @@ Windows (`Anaconda <https://www.anaconda.com/products/individual#windows>`__
110
111
  ) platforms.
111
112
 
112
113
 
113
- Supported Features
114
- ------------------
115
-
116
- - search/get/create/clone/update/delete projects
117
- - search/get/create/delete folders
118
- - assign folders to project contributors
119
- - upload items to a project from a local or AWS S3 folder
120
- - attach items by URL or from an integrated storage, meanwhile keeping them secure in your cloud provider
121
- - get integrated cloud storages
122
- - upload annotations (also from local or AWS S3 folder)
123
- - delete annotations
124
- - set items annotations statuses
125
- - get/download/export annotations from a project (also to a local or AWS S3 folder)
126
- - invite/search team contributors or add contributors to a specific project
127
- - search/get/copy/move items in a project
128
- - query items using SA Query Language
129
- - define custom metadata for items and upload custom values (query based on your custom metadata)
130
- - upload priority scores
131
- - get available subsets (sets of segregated items), query items in a subset or add items to a subset
132
- - assign or anassign items to project contributors
133
- - download an image that has been uploaded to project
134
- - search/create/download/delete project annotation classes
135
- - search/download models
136
- - run predictions
137
- - convert annotations from/to COCO format
138
- - convert annotation from VOC, SuperVisely, LabelBox, DataLoop, VGG, VoTT, SageMaker, GoogleCloud, YOLO formats
139
- - CLI commands for simple tasks
140
-
141
114
  Questions and Issues
142
115
  --------------------
143
116
 
@@ -1,11 +1,11 @@
1
1
  pydantic~=2.5
2
2
  pydantic-extra-types~=2.11
3
- aiohttp~=3.8
3
+ aiohttp~=3.14
4
4
  boto3~=1.42
5
5
  opencv-python-headless~=4.7
6
6
  plotly~=6.5
7
7
  pandas~=2.0
8
- pillow~=12.1
8
+ pillow~=12.3
9
9
  tqdm~=4.66
10
10
  requests~=2.33
11
11
  aiofiles~=25.1
@@ -2,7 +2,7 @@ import logging
2
2
  import os
3
3
  import sys
4
4
 
5
- __version__ = "4.5.9"
5
+ __version__ = "4.6.0"
6
6
 
7
7
 
8
8
  os.environ.update({"sa_version": __version__})
@@ -199,7 +199,7 @@ class CocoBaseStrategy(baseStrategy):
199
199
  else:
200
200
  try:
201
201
  img = Image.open(image_path)
202
- img_width, img_height = img.size()
202
+ img_width, img_height = img.size
203
203
  except Exception as e:
204
204
  raise
205
205
 
@@ -124,11 +124,14 @@ class Tracker:
124
124
 
125
125
  @staticmethod
126
126
  @lru_cache
127
- def get_default_payload(team_name, user_email):
127
+ def get_default_payload(team_name, user_email, auth_type):
128
128
  return {
129
129
  "SDK": True,
130
130
  "Team": team_name,
131
131
  "User Email": user_email,
132
+ # How the client authenticated: "sdk" for a legacy team token,
133
+ # "api_key" for a scoped API key.
134
+ "Auth Type": auth_type,
132
135
  "Version": os.environ["sa_version"],
133
136
  "Python version": platform.python_version(),
134
137
  "Python interpreter type": platform.python_implementation(),
@@ -205,11 +208,12 @@ class Tracker:
205
208
  arguments = self.extract_arguments(self.function, *args, **kwargs)
206
209
  event_name, properties = self.default_parser(function_name, arguments)
207
210
  user_email = client.controller.current_user.email
208
- team_name = client.controller.team_data.name
211
+ team_name = client.controller.team_name
212
+ auth_type = client.controller.token_context.auth_type
209
213
 
210
214
  properties["Success"] = success
211
215
  default = self.get_default_payload(
212
- team_name=team_name, user_email=user_email
216
+ team_name=team_name, user_email=user_email, auth_type=auth_type
213
217
  )
214
218
  self._track(
215
219
  user_email,
@@ -33,10 +33,10 @@ class CLIFacade:
33
33
  logging_path: str = constances.LOG_FILE_LOCATION,
34
34
  ):
35
35
  """
36
- To initialize CLI (and SDK) with team token
37
- Input the team SDK token from https://app.superannotate.com/team
36
+ To initialize CLI (and SDK) with API key.
37
+ The API key is available on the team setup page, for more details please visit our documentation at https://doc.superannotate.com/docs/api-keys.
38
38
 
39
- :param token: the team token
39
+ :param token: the API key
40
40
  :type token: str
41
41
 
42
42
  :param logging_level: logging level, default is "INFO"
@@ -295,7 +295,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
295
295
  In case of no argument has been provided, SA_TOKEN environmental variable
296
296
  will be checked or $HOME/.superannotate/config.json will be used.
297
297
 
298
- :param token: team token
298
+ :param token: API key
299
299
  :type token: str
300
300
 
301
301
  :param config_path: path to config file
@@ -303,11 +303,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
303
303
 
304
304
  """
305
305
 
306
- def __init__(
307
- self,
308
- token: str | None = None,
309
- config_path: str | None = None,
310
- ):
306
+ def __init__(self, token: str | None = None, config_path: str | None = None):
311
307
  super().__init__(token, config_path)
312
308
 
313
309
  def get_project_by_id(self, project_id: int):
@@ -1223,6 +1219,161 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
1223
1219
  operation="revoke",
1224
1220
  )
1225
1221
 
1222
+ def grant_team_user_permissions(
1223
+ self,
1224
+ permissions: list[NotEmptyStr] | Literal["*"],
1225
+ user: int | str,
1226
+ ) -> None:
1227
+ """
1228
+ Grants permissions for a team user. Accepts "*" to indicate all available
1229
+ team-level permissions based on the user's role.
1230
+
1231
+ :param permissions: Specifies which permissions to grant.
1232
+ Accepts "*" to indicate all available team user permissions.
1233
+
1234
+ Possible values are
1235
+
1236
+ - "Access team API keys": Only for Team Admins. Allows Team Admins to
1237
+ create, rotate, and revoke team API keys which have full Team Admin
1238
+ permissions. If this permission is set, it will automatically grant
1239
+ access to all the other admin permissions.
1240
+ - "Access Orchestrate": Only for Team Admins. Allows Team Admins to create and
1241
+ monitor Orchestrate pipelines, as well as access Secrets and Proxies.
1242
+ - "Revoke members' personal API keys": Only for Team Admins. Allows Team
1243
+ Admins to revoke personal API keys generated by other members.
1244
+ - "Manage Contributors' permissions": Only for Team Contributors. Grants
1245
+ all contributor permissions and the ability to manage other
1246
+ contributors' permissions. If this permission is set, it will
1247
+ automatically grant access to all the other contributor permissions.
1248
+ - "Invite Contributors to team": Only for Team Contributors. Allows
1249
+ inviting contributors to the team.
1250
+ - "Remove Contributors from team": Only for Team Contributors. Allows
1251
+ removing contributors from the team.
1252
+ - "View Contributors' scores": Only for Team Contributors. Allows viewing
1253
+ contributors' scores.
1254
+ - "View Contributors' custom field values": Only for Team Contributors.
1255
+ Allows viewing contributors' custom field values.
1256
+ - "Edit Contributors' custom field values": Only for Team Contributors.
1257
+ Allows editing contributors' custom field values. If this permission is
1258
+ set, it will automatically grant access to "View Contributors' custom
1259
+ field values" permission.
1260
+ - "Access Workload management": Only for Team Contributors. Allows
1261
+ accessing Workload management.
1262
+ :type permissions: Union[List[str], Literal["*"]]
1263
+
1264
+ :param user: Team user ID or email to grant permissions to.
1265
+ :type user: Union[int, str]
1266
+
1267
+ :rtype: None
1268
+
1269
+ :raises AppException: If permissions are empty or the user is not found.
1270
+
1271
+ Request Example:
1272
+ ::
1273
+
1274
+ # To grant a specific permission by email:
1275
+ sa_client.grant_team_user_permissions(
1276
+ permissions=["Access team API keys"],
1277
+ user="test@superannotate.com"
1278
+ )
1279
+
1280
+ # To grant all permissions by team user ID:
1281
+ sa_client.grant_team_user_permissions(
1282
+ permissions="*",
1283
+ user=124341
1284
+ )
1285
+
1286
+ # Example when granting "Edit Contributors' custom field values" permission
1287
+ sa_client.grant_team_user_permissions(
1288
+ permissions=["Edit Contributors' custom field values"],
1289
+ user="test@superannotate.com"
1290
+ )
1291
+
1292
+ # Example when granting "Manage Contributors' permissions" permission
1293
+ sa_client.grant_team_user_permissions(
1294
+ permissions=["Manage Contributors' permissions"],
1295
+ user="test@superannotate.com"
1296
+ )
1297
+ """
1298
+ if not permissions:
1299
+ raise AppException("Permission(s) cannot be empty.")
1300
+ self.controller.work_management.edit_team_user_permissions(
1301
+ user=user,
1302
+ permissions=permissions,
1303
+ operation="grant",
1304
+ )
1305
+
1306
+ def revoke_team_user_permissions(
1307
+ self,
1308
+ permissions: list[NotEmptyStr] | Literal["*"],
1309
+ user: int | str,
1310
+ ) -> None:
1311
+ """
1312
+ Revokes permissions for a team user. Accepts "*" to indicate all available
1313
+ team-level permissions based on the user's role.
1314
+
1315
+ :param permissions: Specifies which permissions to revoke.
1316
+ Accepts "*" to indicate all available team user permissions. Possible
1317
+ values are the same as for
1318
+ :func:`grant_team_user_permissions`.
1319
+
1320
+ The following rules apply when revoking:
1321
+
1322
+ - "Access team API keys" grants every other Team Admin permission, so
1323
+ no Team Admin permission can be revoked while it is still granted;
1324
+ revoke "Access team API keys" first.
1325
+ - "Manage Contributors' permissions" grants every other Team
1326
+ Contributor permission, so no Team Contributor permission can be
1327
+ revoked while it is still granted; revoke "Manage Contributors'
1328
+ permissions" first.
1329
+ - Revoking either of the above revokes only that permission; the
1330
+ permissions it implied stay granted.
1331
+ - Revoking "View Contributors' custom field values" will also revoke
1332
+ "Edit Contributors' custom field values".
1333
+ :type permissions: Union[List[str], Literal["*"]]
1334
+
1335
+ :param user: Team user ID or email to revoke permissions from.
1336
+ :type user: Union[int, str]
1337
+
1338
+ :rtype: None
1339
+
1340
+ :raises AppException: If permissions are empty or the user is not found.
1341
+
1342
+ Request Example:
1343
+ ::
1344
+
1345
+ # To revoke a specific permission by email:
1346
+ sa_client.revoke_team_user_permissions(
1347
+ permissions=["Remove Contributors from team"],
1348
+ user="contributor@superannotate.com"
1349
+ )
1350
+
1351
+ # To revoke all permissions by team user ID:
1352
+ sa_client.revoke_team_user_permissions(
1353
+ permissions="*",
1354
+ user=124341
1355
+ )
1356
+
1357
+ # Example when revoking "View Contributors' custom field values" permission
1358
+ sa_client.revoke_team_user_permissions(
1359
+ permissions=["View Contributors' custom field values"],
1360
+ user="test@superannotate.com"
1361
+ )
1362
+
1363
+ # Example when revoking "Manage Contributors' permissions" permission
1364
+ sa_client.revoke_team_user_permissions(
1365
+ permissions=["Manage Contributors' permissions"],
1366
+ user="test@superannotate.com"
1367
+ )
1368
+ """
1369
+ if not permissions:
1370
+ raise AppException("Permission(s) cannot be empty.")
1371
+ self.controller.work_management.edit_team_user_permissions(
1372
+ user=user,
1373
+ permissions=permissions,
1374
+ operation="revoke",
1375
+ )
1376
+
1226
1377
  def get_component_config(self, project: NotEmptyStr | int, component_id: str):
1227
1378
  """
1228
1379
  Retrieves the configuration for a given project and component ID.
@@ -1279,44 +1430,6 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
1279
1430
  raise AppException("No component context found for project.")
1280
1431
  return _context
1281
1432
 
1282
- def search_team_contributors(
1283
- self,
1284
- email: EmailStr | None = None,
1285
- first_name: NotEmptyStr | None = None,
1286
- last_name: NotEmptyStr | None = None,
1287
- return_metadata: bool = True,
1288
- ):
1289
- """Search for contributors in the team
1290
-
1291
- :param email: filter by email
1292
- :type email: str
1293
-
1294
- :param first_name: filter by first name
1295
- :type first_name: str
1296
-
1297
- :param last_name: filter by last name
1298
- :type last_name: str
1299
-
1300
- :param return_metadata: return metadata of contributors instead of names
1301
- :type return_metadata: bool
1302
-
1303
- :return: metadata of found users
1304
- :rtype: list of dicts
1305
- """
1306
- warnings.warn(
1307
- "This function search_team_contributors() will be deprecated and removed in version 4.6.0\n"
1308
- "Recommended replacement: get_user_metadata() or list_users()",
1309
- DeprecationWarning,
1310
- stacklevel=2,
1311
- )
1312
- contributors = self.controller.search_team_contributors(
1313
- email=email, first_name=first_name, last_name=last_name
1314
- ).data
1315
-
1316
- if not return_metadata:
1317
- return [contributor["email"] for contributor in contributors]
1318
- return contributors
1319
-
1320
1433
  def search_projects(
1321
1434
  self,
1322
1435
  name: NotEmptyStr | None = None,
@@ -1345,7 +1458,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
1345
1458
  :rtype: list of strs or dicts
1346
1459
  """
1347
1460
  warnings.warn(
1348
- "This function search_projects() will be deprecated and removed in version 4.6.0\n"
1461
+ "This function search_projects() will be deprecated and removed in version 4.7.0\n"
1349
1462
  "Recommended replacement: get_project_metadata() or list_projects()",
1350
1463
  DeprecationWarning,
1351
1464
  stacklevel=2,
@@ -1951,7 +2064,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
1951
2064
  """
1952
2065
  warnings.warn(
1953
2066
  DeprecationWarning(
1954
- "This function search_folders() will be deprecated and removed in version 4.6.0 \n"
2067
+ "This function search_folders() will be deprecated and removed in version 4.7.0 \n"
1955
2068
  "Recommended replacement:list_folders()"
1956
2069
  )
1957
2070
  )
@@ -3702,6 +3815,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
3702
3815
  keep_status: bool | None = None,
3703
3816
  *,
3704
3817
  data_spec: Literal["default", "multimodal"] = "default",
3818
+ integration: str | None = None,
3705
3819
  ):
3706
3820
  """Uploads a list of annotation dictionaries to the specified SuperAnnotate project or folder.
3707
3821
 
@@ -3723,6 +3837,10 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
3723
3837
  compact and modality-specific data representation.
3724
3838
  :type data_spec: str, optional
3725
3839
 
3840
+ :param integration: The name of an existing integration on the SuperAnnotate platform, used to access external URLs in the annotations. Only supported for
3841
+ Multimodal projects and data_spec="multimodal" and only applies to items being newly created — it has no effect on existing items.
3842
+ :type integration: str, optional
3843
+
3726
3844
  :return: A dictionary containing the results of the upload, categorized into successfully uploaded,
3727
3845
  failed, and skipped annotations.
3728
3846
  :rtype: dict
@@ -3759,6 +3877,17 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
3759
3877
  keep_status=True,
3760
3878
  data_spec='multimodal'
3761
3879
  )
3880
+
3881
+ Example Usage with private URLs signed via an integration::
3882
+
3883
+ # Upload annotations with private URLs using integration
3884
+ sa_client.upload_annotations(
3885
+ project="project1/folder1",
3886
+ annotations=annotations,
3887
+ keep_status=True,
3888
+ data_spec="multimodal",
3889
+ integration="AWS Main Bucket"
3890
+ )
3762
3891
  """
3763
3892
  if keep_status is not None:
3764
3893
  warnings.warn(
@@ -3768,6 +3897,18 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
3768
3897
  )
3769
3898
  )
3770
3899
  project, folder = self.controller.get_project_folder(project)
3900
+ integration_entity = None
3901
+ if integration:
3902
+ if data_spec != "multimodal" or project.type != ProjectType.MULTIMODAL:
3903
+ raise AppException(
3904
+ "Integration is only supported for Multimodal projects"
3905
+ )
3906
+ for i in self.controller.integrations.list().data:
3907
+ if i.name == integration:
3908
+ integration_entity = i
3909
+ break
3910
+ else:
3911
+ raise AppException("Integration not found")
3771
3912
  response = self.controller.annotations.upload_multiple(
3772
3913
  project=project,
3773
3914
  folder=folder,
@@ -3775,6 +3916,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
3775
3916
  keep_status=keep_status,
3776
3917
  user=self.controller.current_user,
3777
3918
  output_format=data_spec,
3919
+ integration=integration_entity,
3778
3920
  )
3779
3921
  if response.errors:
3780
3922
  raise AppException(response.errors)
@@ -4598,128 +4740,6 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
4598
4740
 
4599
4741
  return BaseSerializer(item).serialize(exclude=exclude)
4600
4742
 
4601
- def search_items(
4602
- self,
4603
- project: NotEmptyStr | int | tuple[int, int] | tuple[str, str],
4604
- name_contains: NotEmptyStr | None = None,
4605
- annotation_status: str | None = None,
4606
- annotator_email: NotEmptyStr | None = None,
4607
- qa_email: NotEmptyStr | None = None,
4608
- recursive: bool = False,
4609
- include_custom_metadata: bool = False,
4610
- ):
4611
- """Search items by filtering criteria.
4612
-
4613
- :param project: Accepts a project as a string ("project" or "project/folder") or as a tuple (project_id, folder_id), where the folder is optional.”
4614
- :type project: Union[str, int, Tuple[int, int], Tuple[str, str]]
4615
-
4616
- :param name_contains: returns those items, where the given string is found anywhere within an item’s name.
4617
- If None, all items returned, in accordance with the recursive=False parameter.
4618
- :type name_contains: str
4619
-
4620
- :param annotation_status: returns items with the specified annotation status, which must match a predefined
4621
- status in the project workflow. If None, all items are returned.
4622
-
4623
- :type annotation_status: str
4624
-
4625
- :param annotator_email: returns those items’ names that are assigned to the specified annotator.
4626
- If None, all items are returned. Strict equal.
4627
- :type annotator_email: str
4628
-
4629
- :param qa_email: returns those items’ names that are assigned to the specified QA.
4630
- If None, all items are returned. Strict equal.
4631
- :type qa_email: str
4632
-
4633
- :param recursive: search in the project’s root and all of its folders.
4634
- If False search only in the project’s root or given directory.
4635
- :type recursive: bool
4636
-
4637
- :param include_custom_metadata: include custom metadata that has been attached to an asset.
4638
- :type include_custom_metadata: bool
4639
-
4640
- :return: metadata of item
4641
- :rtype: list of dicts
4642
-
4643
- Request Example:
4644
- ::
4645
-
4646
- sa_client.search_items(
4647
- project="Medical Annotations",
4648
- name_contains="image_1",
4649
- include_custom_metadata=True
4650
- )
4651
-
4652
- Response Example:
4653
- ::
4654
-
4655
- [
4656
- {
4657
- "name": "image_1.jpeg",
4658
- "path": "Medical Annotations/Study",
4659
- "url": "https://sa-public-files.s3.../image_1.png",
4660
- "annotation_status": "NotStarted",
4661
- "annotator_email": None,
4662
- "qa_email": None,
4663
- "entropy_value": None,
4664
- "createdAt": "2022-02-15T20:46:44.000Z",
4665
- "updatedAt": "2022-02-15T20:46:44.000Z",
4666
- "custom_metadata": {
4667
- "study_date": "2021-12-31",
4668
- "patient_id": "62078f8a756ddb2ca9fc9660",
4669
- "patient_sex": "female",
4670
- "medical_specialist": "robertboxer@ms.com",
4671
- }
4672
- }
4673
- ]
4674
- """
4675
- warnings.warn(
4676
- "This function search_items() will be deprecated and removed in version 4.6.0\n"
4677
- "Recommended replacement: get_item_metadata() or list_items()",
4678
- DeprecationWarning,
4679
- stacklevel=2,
4680
- )
4681
- project, folder = self.controller.get_project_folder(project)
4682
- query_kwargs = {"include": ["assignments"]}
4683
- if name_contains:
4684
- query_kwargs["name__contains"] = name_contains
4685
- if annotation_status:
4686
- query_kwargs["annotation_status"] = annotation_status
4687
- if qa_email:
4688
- query_kwargs["assignments__user_id"] = qa_email
4689
- query_kwargs["assignments__user_role"] = "QA"
4690
- if annotator_email:
4691
- query_kwargs["assignments__user_id"] = annotator_email
4692
- query_kwargs["assignments__user_role"] = "Annotator"
4693
- if folder.is_root and recursive:
4694
- items = []
4695
- for folder in self.controller.folders.list(project=project).data:
4696
- path = (
4697
- f"{project.name}{f'/{folder.name}' if not folder.is_root else ''}"
4698
- )
4699
- _items = self.controller.items.list_items(
4700
- project,
4701
- folder,
4702
- **query_kwargs,
4703
- )
4704
- for i in _items:
4705
- i.path = path
4706
- items.extend(_items)
4707
- else:
4708
- path = f"{project.name}{f'/{folder.name}' if not folder.is_root else ''}"
4709
- items = self.controller.items.list_items(project, folder, **query_kwargs)
4710
- for i in items:
4711
- i.path = path
4712
- exclude = {"meta"}
4713
- if include_custom_metadata:
4714
- item_custom_fields = self.controller.custom_fields.list_fields(
4715
- project=project, item_ids=[i.id for i in items]
4716
- )
4717
- for i in items:
4718
- i.custom_metadata = item_custom_fields[i.id]
4719
- else:
4720
- exclude.add("custom_metadata")
4721
- return BaseSerializer.serialize_iterable(items, exclude=exclude)
4722
-
4723
4743
  def list_items(
4724
4744
  self,
4725
4745
  project: NotEmptyStr | int,
@@ -5683,7 +5703,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
5683
5703
  ):
5684
5704
  """
5685
5705
  Attach custom metadata to items.
5686
- SAClient.get_item_metadata(), SAClient.search_items(), SAClient.query() methods
5706
+ SAClient.get_item_metadata(), SAClient.list_items(), SAClient.query() methods
5687
5707
  will return the item metadata and custom metadata.
5688
5708
 
5689
5709
  :param project: Accepts a project as a string ("project" or "project/folder") or as a tuple (project_id, folder_id), where the folder is optional.”