superannotate 4.4.25.dev2__tar.gz → 4.4.26.dev1__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 (140) hide show
  1. {superannotate-4.4.25.dev2/src/superannotate.egg-info → superannotate-4.4.26.dev1}/PKG-INFO +1 -1
  2. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/__init__.py +2 -2
  3. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/sdk_interface.py +62 -27
  4. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/project.py +1 -0
  5. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/enums.py +1 -1
  6. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/service_types.py +5 -1
  7. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/serviceproviders.py +25 -0
  8. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/annotations.py +9 -24
  9. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/images.py +6 -13
  10. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/items.py +149 -1
  11. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/models.py +4 -1
  12. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/controller.py +55 -18
  13. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/serviceprovider.py +18 -2
  14. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/http_client.py +6 -0
  15. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/item.py +58 -0
  16. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/work_management.py +41 -0
  17. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/stream_data_handler.py +25 -11
  18. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1/src/superannotate.egg-info}/PKG-INFO +1 -1
  19. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/LICENSE +0 -0
  20. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/MANIFEST.in +0 -0
  21. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/README.rst +0 -0
  22. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/requirements.txt +0 -0
  23. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/setup.cfg +0 -0
  24. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/setup.py +0 -0
  25. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/__init__.py +0 -0
  26. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/__init__.py +0 -0
  27. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/analytics/__init__.py +0 -0
  28. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/analytics/aggregators.py +0 -0
  29. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/analytics/common.py +0 -0
  30. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/bin/__init__.py +0 -0
  31. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/bin/superannotate.py +0 -0
  32. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/common.py +0 -0
  33. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/exceptions.py +0 -0
  34. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/helpers.py +0 -0
  35. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/__init__.py +0 -0
  36. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/conversion.py +0 -0
  37. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/__init__.py +0 -0
  38. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/baseStrategy.py +0 -0
  39. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/__init__.py +0 -0
  40. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_api.py +0 -0
  41. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_converter.py +0 -0
  42. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_strategies.py +0 -0
  43. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_to_sa_pixel.py +0 -0
  44. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_to_sa_vector.py +0 -0
  45. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/sa_pixel_to_coco.py +0 -0
  46. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/coco_converters/sa_vector_to_coco.py +0 -0
  47. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/converters.py +0 -0
  48. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/__init__.py +0 -0
  49. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_helper.py +0 -0
  50. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_strategies.py +0 -0
  51. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_to_sa_vector.py +0 -0
  52. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/__init__.py +0 -0
  53. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/googlecloud_strategies.py +0 -0
  54. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/googlecloud_to_sa_vector.py +0 -0
  55. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/__init__.py +0 -0
  56. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_helper.py +0 -0
  57. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_strategies.py +0 -0
  58. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_to_sa_pixel.py +0 -0
  59. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_to_sa_vector.py +0 -0
  60. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/sa_json_helper.py +0 -0
  61. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/__init__.py +0 -0
  62. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_strategies.py +0 -0
  63. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_to_sa_pixel.py +0 -0
  64. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_to_sa_vector.py +0 -0
  65. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/__init__.py +0 -0
  66. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_helper.py +0 -0
  67. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_strategies.py +0 -0
  68. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_to_sa_pixel.py +0 -0
  69. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_to_sa_vector.py +0 -0
  70. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vgg_converters/__init__.py +0 -0
  71. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_helper.py +0 -0
  72. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_strategies.py +0 -0
  73. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_to_sa_vector.py +0 -0
  74. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/voc_converters/__init__.py +0 -0
  75. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_helper.py +0 -0
  76. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_strategies.py +0 -0
  77. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_to_sa_pixel.py +0 -0
  78. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_to_sa_vector.py +0 -0
  79. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vott_converters/__init__.py +0 -0
  80. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vott_converters/vott_strategies.py +0 -0
  81. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/vott_converters/vott_to_sa_vector.py +0 -0
  82. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/yolo_converters/__init__.py +0 -0
  83. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/yolo_converters/yolo_strategies.py +0 -0
  84. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/converters/yolo_converters/yolo_to_sa_vector.py +0 -0
  85. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/export_from_sa_conversions.py +0 -0
  86. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/import_to_sa_conversions.py +0 -0
  87. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/input_converters/sa_conversion.py +0 -0
  88. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/__init__.py +0 -0
  89. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/base_interface.py +0 -0
  90. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/cli_interface.py +0 -0
  91. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/sdk/__init__.py +0 -0
  92. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/sdk/folders.py +0 -0
  93. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/sdk/project.py +0 -0
  94. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/interface/types.py +0 -0
  95. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/app/serializers.py +0 -0
  96. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/__init__.py +0 -0
  97. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/base_usecases.py +0 -0
  98. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/conditions.py +0 -0
  99. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/config.py +0 -0
  100. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/__init__.py +0 -0
  101. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/base.py +0 -0
  102. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/classes.py +0 -0
  103. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/folder.py +0 -0
  104. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/integrations.py +0 -0
  105. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/items.py +0 -0
  106. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/entities/project_entities.py +0 -0
  107. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/exceptions.py +0 -0
  108. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/jsx_conditions.py +0 -0
  109. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/plugin.py +0 -0
  110. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/pydantic_v1.py +0 -0
  111. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/reporter.py +0 -0
  112. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/repositories.py +0 -0
  113. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/response.py +0 -0
  114. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/types.py +0 -0
  115. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/__init__.py +0 -0
  116. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/base.py +0 -0
  117. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/classes.py +0 -0
  118. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/custom_fields.py +0 -0
  119. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/folders.py +0 -0
  120. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/integrations.py +0 -0
  121. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/usecases/projects.py +0 -0
  122. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/core/video_convertor.py +0 -0
  123. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/__init__.py +0 -0
  124. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/helpers.py +0 -0
  125. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/repositories.py +0 -0
  126. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/__init__.py +0 -0
  127. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/annotation.py +0 -0
  128. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/annotation_class.py +0 -0
  129. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/explore.py +0 -0
  130. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/folder.py +0 -0
  131. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/integration.py +0 -0
  132. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/item_service.py +0 -0
  133. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/services/project.py +0 -0
  134. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/utils.py +0 -0
  135. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate/lib/infrastructure/validators.py +0 -0
  136. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate.egg-info/SOURCES.txt +0 -0
  137. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate.egg-info/dependency_links.txt +0 -0
  138. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate.egg-info/entry_points.txt +0 -0
  139. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/src/superannotate.egg-info/requires.txt +0 -0
  140. {superannotate-4.4.25.dev2 → superannotate-4.4.26.dev1}/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.4.25.dev2
3
+ Version: 4.4.26.dev1
4
4
  Summary: Python SDK to SuperAnnotate platform
5
5
  Home-page: https://github.com/superannotateai/superannotate-python-sdk
6
6
  Author: SuperAnnotate AI
@@ -3,7 +3,7 @@ import os
3
3
  import sys
4
4
 
5
5
 
6
- __version__ = "4.4.25dev2"
6
+ __version__ = "4.4.26dev1"
7
7
 
8
8
  os.environ.update({"sa_version": __version__})
9
9
  sys.path.append(os.path.split(os.path.realpath(__file__))[0])
@@ -18,7 +18,7 @@ from lib.core.exceptions import AppException
18
18
  from lib.app.input_converters import convert_project_type
19
19
  from lib.app.input_converters import export_annotation
20
20
  from lib.app.input_converters import import_annotation
21
- from lib.app.interface.sdk_interface import SAClient
21
+ from superannotate.lib.app.interface.sdk_interface import SAClient
22
22
 
23
23
 
24
24
  SESSIONS = {}
@@ -79,7 +79,7 @@ PROJECT_TYPE = Literal[
79
79
  "Document",
80
80
  "Tiled",
81
81
  "PointCloud",
82
- "GenAI",
82
+ "Multimodal",
83
83
  ]
84
84
 
85
85
 
@@ -307,7 +307,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
307
307
  :param project_description: the new project's description
308
308
  :type project_description: str
309
309
 
310
- :param project_type: the new project type, Vector, Pixel, Video, Document, Tiled, PointCloud, GenAI.
310
+ :param project_type: the new project type, Vector, Pixel, Video, Document, Tiled, PointCloud, Multimodal.
311
311
  :type project_type: str
312
312
 
313
313
  :param settings: list of settings objects
@@ -711,8 +711,8 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
711
711
  """
712
712
  warnings.warn(
713
713
  DeprecationWarning(
714
- "The “set_project_workflow” function is deprecated."
715
- " Please use the “set_project_steps” function instead."
714
+ "The “get_project_workflow” function is deprecated."
715
+ " Please use the “get_project_steps” function instead."
716
716
  )
717
717
  )
718
718
  return self.get_project_steps(project)
@@ -1215,11 +1215,11 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
1215
1215
  :param only_pinned: enable only pinned output in export. This option disables all other types of output.
1216
1216
  :type only_pinned: bool
1217
1217
 
1218
- :param kwargs:
1219
- Arbitrary kwargs:
1218
+ :param kwargs: Arbitrary keyword arguments:
1220
1219
 
1221
- - integration_name: can be provided which will be used as a storage to store export file
1222
- - format: can be CSV for the Gen AI projects
1220
+ - integration_name: The name of the integration within the platform that is being used.
1221
+ - format: The format in which the data will be exported in multimodal projects.
1222
+ It can be either CSV or JSON. If None, the data will be exported in the default JSON format.
1223
1223
  :return: metadata object of the prepared export
1224
1224
  :rtype: dict
1225
1225
 
@@ -1232,7 +1232,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
1232
1232
  project = "Project Name",
1233
1233
  folder_names = ["Folder 1", "Folder 2"],
1234
1234
  annotation_statuses = ["Completed","QualityCheck"],
1235
- export_type = "CSV"
1235
+ format = "CSV"
1236
1236
  )
1237
1237
 
1238
1238
  client.download_export("Project Name", export, "path_to_download")
@@ -2318,7 +2318,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2318
2318
 
2319
2319
  def get_annotations(
2320
2320
  self,
2321
- project: Union[int, NotEmptyStr],
2321
+ project: Union[NotEmptyStr, int],
2322
2322
  items: Optional[Union[List[NotEmptyStr], List[int]]] = None,
2323
2323
  ):
2324
2324
  """Returns annotations for the given list of items.
@@ -2663,29 +2663,28 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2663
2663
 
2664
2664
  def list_items(
2665
2665
  self,
2666
- project: Union[int, str],
2667
- folder: Optional[Union[int, str]] = None,
2666
+ project: Union[NotEmptyStr, int],
2667
+ folder: Optional[Union[NotEmptyStr, int]] = None,
2668
2668
  *,
2669
- include: List[Literal["assignments", "custom_metadata"]] = None,
2669
+ include: List[Literal["custom_metadata"]] = None,
2670
2670
  **filters,
2671
2671
  ):
2672
2672
  """
2673
2673
  Search items by filtering criteria.
2674
2674
 
2675
- :param project: The project name, project ID, or folder path (e.g., "project1/folder1") to search within.
2675
+ :param project: The project name, project ID, or folder path (e.g., "project1") to search within.
2676
2676
  This can refer to the root of the project or a specific subfolder.
2677
- :type project: Union[int, str]
2677
+ :type project: Union[NotEmptyStr, int]
2678
2678
 
2679
2679
  :param folder: The folder name or ID to search within. If None, the search will be done in the root folder of
2680
2680
  the project. If both “project” and “folder” specify folders, the “project”
2681
2681
  value will take priority.
2682
- :type folder: Union[int, str], optional
2682
+ :type folder: Union[NotEmptyStr, int], optional
2683
2683
 
2684
2684
  :param include: Specifies additional fields to include in the response.
2685
2685
 
2686
2686
  Possible values are
2687
2687
 
2688
- - "assignee": Includes information about the role of the item assignee.
2689
2688
  - "custom_metadata": Includes custom metadata attached to the item.
2690
2689
  :type include: list of str, optional
2691
2690
 
@@ -2695,8 +2694,8 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2695
2694
 
2696
2695
 
2697
2696
  Supported operations:
2698
- - __ne: Value is in the list.
2699
- - __in: Value is not equal.
2697
+ - __ne: Value is not equal.
2698
+ - __in: Value is in the list.
2700
2699
  - __notin: Value is not in the list.
2701
2700
  - __contains: Value has the substring.
2702
2701
  - __starts: Value starts with the prefix.
@@ -2711,6 +2710,9 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2711
2710
  - name__contains: str
2712
2711
  - name__starts: str
2713
2712
  - name__ends: str
2713
+ - annotation_status: str
2714
+ - annotation_status__in: list[str]
2715
+ - annotation_status__ne: list[str]
2714
2716
  - approval_status: Literal["Approved", "Disapproved", None]
2715
2717
  - assignments__user_id: str
2716
2718
  - assignments__user_id__ne: str
@@ -2801,8 +2803,6 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2801
2803
  if include:
2802
2804
  if "custom_metadata" not in include:
2803
2805
  exclude.add("custom_metadata")
2804
- if "assignments" not in include:
2805
- exclude.add("assignments")
2806
2806
  return BaseSerializer.serialize_iterable(res, exclude=exclude)
2807
2807
 
2808
2808
  def attach_items(
@@ -2930,26 +2930,46 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2930
2930
  source: Union[NotEmptyStr, dict],
2931
2931
  destination: Union[NotEmptyStr, dict],
2932
2932
  items: Optional[List[NotEmptyStr]] = None,
2933
- include_annotations: Optional[bool] = True,
2933
+ include_annotations: bool = True,
2934
+ duplicate_strategy: Literal[
2935
+ "skip", "replace", "replace_annotations_only"
2936
+ ] = "skip",
2934
2937
  ):
2935
2938
  """Copy images in bulk between folders in a project
2936
2939
 
2937
- :param source: project name or folder path to select items from (e.g., “project1/folder1”).
2940
+ :param source: project name (root) or folder path to pick items from (e.g., “project1/folder1”).
2938
2941
  :type source: str
2939
2942
 
2940
- :param destination: project name (root) or folder path to place copied items.
2943
+ :param destination: project name (root) or folder path to place copied items (e.g., “project1/folder2”).
2941
2944
  :type destination: str
2942
2945
 
2943
2946
  :param items: names of items to copy. If None, all items from the source directory will be copied.
2944
2947
  :type items: list of str
2945
2948
 
2946
- :param include_annotations: enables annotations copy
2949
+ :param include_annotations: enables the copying of item data, including annotations, status, priority score,
2950
+ approval state, and category. If set to False, only the items will be copied without additional data.
2947
2951
  :type include_annotations: bool
2948
2952
 
2953
+ :param duplicate_strategy: Specifies the strategy for handling duplicate items in the destination.
2954
+ The default value is "skip".
2955
+
2956
+ - "skip": skips duplicate items in the destination and continues with the next item.
2957
+ - "replace": replaces the annotations, status, priority score, approval state, and category of duplicate items.
2958
+ - "replace_annotations_only": replaces only the annotations of duplicate items,
2959
+ leaving other data (status, priority score, approval state, and category) unchanged.
2960
+
2961
+ :type duplicate_strategy: Literal["skip", "replace", "replace_annotations_only"]
2962
+
2949
2963
  :return: list of skipped item names
2950
2964
  :rtype: list of strs
2951
2965
  """
2952
2966
 
2967
+ if not include_annotations and duplicate_strategy != "skip":
2968
+ duplicate_strategy = "skip"
2969
+ logger.warning(
2970
+ "Copy operation continuing without annotations and metadata due to include_annotations=False."
2971
+ )
2972
+
2953
2973
  project_name, source_folder = extract_project_folder(source)
2954
2974
  to_project_name, destination_folder = extract_project_folder(destination)
2955
2975
  if project_name != to_project_name:
@@ -2963,6 +2983,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2963
2983
  to_folder=to_folder,
2964
2984
  item_names=items,
2965
2985
  include_annotations=include_annotations,
2986
+ duplicate_strategy=duplicate_strategy,
2966
2987
  )
2967
2988
  if response.errors:
2968
2989
  raise AppException(response.errors)
@@ -2974,18 +2995,31 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
2974
2995
  source: Union[NotEmptyStr, dict],
2975
2996
  destination: Union[NotEmptyStr, dict],
2976
2997
  items: Optional[List[NotEmptyStr]] = None,
2998
+ duplicate_strategy: Literal[
2999
+ "skip", "replace", "replace_annotations_only"
3000
+ ] = "skip",
2977
3001
  ):
2978
3002
  """Move images in bulk between folders in a project
2979
3003
 
2980
- :param source: project name or folder path to pick items from (e.g., “project1/folder1”).
3004
+ :param source: project name (root) or folder path to pick items from (e.g., “project1/folder1”).
2981
3005
  :type source: str
2982
3006
 
2983
- :param destination: project name (root) or folder path to move items to.
3007
+ :param destination: project name (root) or folder path to move items to (e.g., “project1/folder2”).
2984
3008
  :type destination: str
2985
3009
 
2986
3010
  :param items: names of items to move. If None, all items from the source directory will be moved.
2987
3011
  :type items: list of str
2988
3012
 
3013
+ :param duplicate_strategy: Specifies the strategy for handling duplicate items in the destination.
3014
+ The default value is "skip".
3015
+
3016
+ - "skip": skips duplicate items in the destination and continues with the next item.
3017
+ - "replace": replaces the annotations, status, priority score, approval state, and category of duplicate items.
3018
+ - "replace_annotations_only": replaces only the annotations of duplicate items,
3019
+ leaving other data (status, priority score, approval state, and category) unchanged.
3020
+
3021
+ :type duplicate_strategy: Literal["skip", "replace", "replace_annotations_only"]
3022
+
2989
3023
  :return: list of skipped item names
2990
3024
  :rtype: list of strs
2991
3025
  """
@@ -3003,6 +3037,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
3003
3037
  from_folder=source_folder,
3004
3038
  to_folder=destination_folder,
3005
3039
  item_names=items,
3040
+ duplicate_strategy=duplicate_strategy,
3006
3041
  )
3007
3042
  if response.errors:
3008
3043
  raise AppException(response.errors)
@@ -163,6 +163,7 @@ class TeamEntity(BaseModel):
163
163
  users: Optional[List[UserEntity]]
164
164
  pending_invitations: Optional[List[Any]]
165
165
  creator_id: Optional[str]
166
+ owner_id: Optional[str]
166
167
 
167
168
  class Config:
168
169
  extra = Extra.ignore
@@ -108,7 +108,7 @@ class ProjectType(BaseTitledEnum):
108
108
  TILED = "Tiled", 5
109
109
  OTHER = "Other", 6
110
110
  POINT_CLOUD = "PointCloud", 7
111
- GEN_AI = "GenAI", 8
111
+ MULTIMODAL = "Multimodal", 8
112
112
  UNSUPPORTED_TYPE_1 = "UnsupportedType", 9
113
113
  UNSUPPORTED_TYPE_2 = "UnsupportedType", 10
114
114
 
@@ -222,6 +222,10 @@ class ProjectResponse(ServiceResponse):
222
222
  res_data: entities.ProjectEntity = None
223
223
 
224
224
 
225
+ class WorkflowResponse(ServiceResponse):
226
+ res_data: entities.WorkflowEntity = None
227
+
228
+
225
229
  class WorkflowListResponse(ServiceResponse):
226
230
  res_data: List[entities.WorkflowEntity] = None
227
231
 
@@ -242,5 +246,5 @@ PROJECT_TYPE_RESPONSE_MAP = {
242
246
  ProjectType.PIXEL: ImageResponse,
243
247
  ProjectType.DOCUMENT: DocumentResponse,
244
248
  ProjectType.POINT_CLOUD: PointCloudResponse,
245
- ProjectType.GEN_AI: ImageResponse,
249
+ ProjectType.MULTIMODAL: ImageResponse,
246
250
  }
@@ -5,6 +5,7 @@ from typing import Any
5
5
  from typing import Callable
6
6
  from typing import Dict
7
7
  from typing import List
8
+ from typing import Literal
8
9
 
9
10
  from lib.core import entities
10
11
  from lib.core.conditions import Condition
@@ -70,6 +71,10 @@ class SuperannotateServiceProvider(ABC):
70
71
 
71
72
 
72
73
  class BaseWorkManagementService(SuperannotateServiceProvider):
74
+ @abstractmethod
75
+ def get_workflow(self, pk: int) -> entities.WorkflowEntity:
76
+ raise NotImplementedError
77
+
73
78
  @abstractmethod
74
79
  def list_workflows(self, query: Query) -> WorkflowListResponse:
75
80
  raise NotImplementedError
@@ -283,10 +288,30 @@ class BaseItemService(SuperannotateServiceProvider):
283
288
  ) -> ServiceResponse:
284
289
  raise NotImplementedError
285
290
 
291
+ @abstractmethod
292
+ def copy_move_multiple(
293
+ self,
294
+ project: entities.ProjectEntity,
295
+ from_folder: entities.FolderEntity,
296
+ to_folder: entities.FolderEntity,
297
+ item_names: List[str],
298
+ duplicate_strategy: Literal["skip", "replace", "replace_annotations_only"],
299
+ operation: Literal["copy", "move"],
300
+ include_annotations: bool = True,
301
+ include_pin: bool = False,
302
+ ) -> ServiceResponse:
303
+ raise NotImplementedError
304
+
286
305
  @abstractmethod
287
306
  def await_copy(self, project: entities.ProjectEntity, poll_id: int, items_count):
288
307
  raise NotImplementedError
289
308
 
309
+ @abstractmethod
310
+ def await_copy_move(
311
+ self, project: entities.ProjectEntity, poll_id: int, items_count
312
+ ):
313
+ raise NotImplementedError
314
+
290
315
  @abstractmethod
291
316
  def set_statuses(
292
317
  self,
@@ -36,7 +36,6 @@ from lib.core.entities import FolderEntity
36
36
  from lib.core.entities import ImageEntity
37
37
  from lib.core.entities import ProjectEntity
38
38
  from lib.core.entities import UserEntity
39
- from lib.core.entities import WorkflowEntity
40
39
  from lib.core.exceptions import AppException
41
40
  from lib.core.jsx_conditions import EmptyQuery
42
41
  from lib.core.jsx_conditions import Filter
@@ -477,13 +476,8 @@ class UploadAnnotationsUseCase(BaseReportableUseCase):
477
476
  {i.item.name for i in items_to_upload}
478
477
  - set(self._report.failed_annotations).union(set(skipped))
479
478
  )
480
- response = self._service_provider.work_management.list_workflows(
481
- Filter("id", self._project.workflow_id, OperatorEnum.EQ)
482
- )
483
- if not response.ok:
484
- raise AppException(response.error)
485
- workflow: WorkflowEntity = next(
486
- (i for i in response.data if i.id == self._project.workflow_id), None
479
+ workflow = self._service_provider.work_management.get_workflow(
480
+ self._project.workflow_id
487
481
  )
488
482
  if workflow.is_system():
489
483
  if uploaded_annotations and not self._keep_status:
@@ -842,13 +836,10 @@ class UploadAnnotationsFromFolderUseCase(BaseReportableUseCase):
842
836
  name_path_mappings.keys()
843
837
  - set(self._report.failed_annotations).union(set(missing_annotations))
844
838
  )
845
- response = self._service_provider.work_management.list_workflows(
846
- Filter("id", self._project.id, OperatorEnum.EQ)
839
+ workflow = self._service_provider.work_management.get_workflow(
840
+ self._project.workflow_id
847
841
  )
848
- if response.error:
849
- raise response.error
850
- workflow = response.data[0]
851
- if workflow.is_system and uploaded_annotations and not self._keep_status:
842
+ if workflow.is_system() and uploaded_annotations and not self._keep_status:
852
843
  statuses_changed = set_annotation_statuses_in_progress(
853
844
  service_provider=self._service_provider,
854
845
  project=self._project,
@@ -1084,13 +1075,10 @@ class UploadAnnotationUseCase(BaseReportableUseCase):
1084
1075
  ],
1085
1076
  Body=mask,
1086
1077
  )
1087
- response = self._service_provider.work_management.list_workflows(
1088
- Filter("id", self._project.workflow_id, OperatorEnum.EQ)
1078
+ workflow = self._service_provider.work_management.get_workflow(
1079
+ self._project.workflow_id
1089
1080
  )
1090
- if not response.ok:
1091
- raise AppException(response.error)
1092
- workflow = response.data[0]
1093
- if workflow.is_system and not self._keep_status:
1081
+ if workflow.is_system() and not self._keep_status:
1094
1082
  statuses_changed = set_annotation_statuses_in_progress(
1095
1083
  service_provider=self._service_provider,
1096
1084
  project=self._project,
@@ -1426,11 +1414,8 @@ class ValidateAnnotationUseCase(BaseReportableUseCase):
1426
1414
  schema_response = self._service_provider.annotations.get_schema(
1427
1415
  self._project_type, version
1428
1416
  )
1429
- if not schema_response.ok:
1417
+ if not schema_response.ok or not schema_response.data:
1430
1418
  raise AppException(f"Schema {version} does not exist.")
1431
- if not schema_response.data:
1432
- ValidateAnnotationUseCase.SCHEMAS[key] = lambda x: x
1433
- return ValidateAnnotationUseCase.SCHEMAS[key]
1434
1419
  validator = superannotate_schemas.Draft7Validator(schema_response.data)
1435
1420
  from functools import partial
1436
1421
 
@@ -743,19 +743,15 @@ class UploadImageToProject(BaseUseCase):
743
743
  self._s3_repo = s3_repo
744
744
  self._service_provider = service_provider
745
745
  if annotation_status_value is None:
746
- response = self._service_provider.work_management.list_workflows(
747
- Filter("id", self._project.workflow_id, OperatorEnum.EQ)
746
+ workflow = self._service_provider.work_management.get_workflow(
747
+ self._project.workflow_id
748
748
  )
749
- if response.error:
750
- raise AppException(response.error)
751
- workflow = response.data[0]
752
- if workflow.is_system:
749
+ if workflow.is_system():
753
750
  annotation_status_value = (
754
751
  self._service_provider.get_annotation_status_value(
755
752
  self._project, "NotStarted"
756
753
  )
757
754
  )
758
-
759
755
  self._annotation_status_value = annotation_status_value
760
756
  self._auth_data = None
761
757
 
@@ -1106,13 +1102,10 @@ class UploadImagesToProject(BaseInteractiveUseCase):
1106
1102
  attach_duplications_list = []
1107
1103
 
1108
1104
  if not self._annotation_status_value:
1109
- response = self._service_provider.work_management.list_workflows(
1110
- Filter("id", self._project.workflow_id, OperatorEnum.EQ)
1105
+ workflow = self._service_provider.work_management.get_workflow(
1106
+ self._project.workflow_id
1111
1107
  )
1112
- if response.error:
1113
- raise AppException(response.error)
1114
- workflow = response.data[0]
1115
- if workflow.is_system:
1108
+ if workflow.is_system():
1116
1109
  self._annotation_status_value = (
1117
1110
  self._service_provider.get_annotation_status_value(
1118
1111
  self._project, "NotStarted"
@@ -33,6 +33,7 @@ from lib.core.usecases.base import BaseUseCase
33
33
  from lib.core.usecases.folders import SearchFoldersUseCase
34
34
  from lib.infrastructure.utils import divide_to_chunks
35
35
  from lib.infrastructure.utils import extract_project_folder
36
+ from typing_extensions import Literal
36
37
 
37
38
  logger = logging.getLogger("sa")
38
39
 
@@ -537,6 +538,154 @@ class MoveItems(BaseReportableUseCase):
537
538
  return self._response
538
539
 
539
540
 
541
+ class CopyMoveItems(BaseReportableUseCase):
542
+ """
543
+ Copy/Move items in bulk between folders in a project.
544
+ Return skipped item names.
545
+ """
546
+
547
+ def __init__(
548
+ self,
549
+ reporter: Reporter,
550
+ project: ProjectEntity,
551
+ from_folder: FolderEntity,
552
+ to_folder: FolderEntity,
553
+ item_names: List[str],
554
+ service_provider: BaseServiceProvider,
555
+ include_annotations: bool,
556
+ duplicate_strategy: Literal["skip", "replace", "replace_annotations_only"],
557
+ operation: Literal["copy", "move"],
558
+ chunk_size: int = 1000,
559
+ ):
560
+ super().__init__(reporter)
561
+ self._project = project
562
+ self._from_folder = from_folder
563
+ self._to_folder = to_folder
564
+ self._item_names = item_names
565
+ self._service_provider = service_provider
566
+ self._include_annotations = include_annotations
567
+ self._duplicate_strategy = duplicate_strategy
568
+ self._operation = operation
569
+ self._chunk_size = chunk_size
570
+
571
+ def _validate_limitations(self, items_count):
572
+ response = self._service_provider.get_limitations(
573
+ project=self._project,
574
+ folder=self._to_folder,
575
+ )
576
+ if not response.ok:
577
+ raise AppValidationException(response.error)
578
+ if self._operation == "copy":
579
+ folder_limit_err_msg = constants.COPY_FOLDER_LIMIT_ERROR_MESSAGE
580
+ project_limit_err_msg = constants.COPY_PROJECT_LIMIT_ERROR_MESSAGE
581
+ else:
582
+ folder_limit_err_msg = constants.MOVE_FOLDER_LIMIT_ERROR_MESSAGE
583
+ project_limit_err_msg = constants.MOVE_PROJECT_LIMIT_ERROR_MESSAGE
584
+ if items_count > response.data.folder_limit.remaining_image_count:
585
+ raise AppValidationException(folder_limit_err_msg)
586
+ if items_count > response.data.project_limit.remaining_image_count:
587
+ raise AppValidationException(project_limit_err_msg)
588
+
589
+ def validate_item_names(self):
590
+ if self._item_names:
591
+ self._item_names = list(set(self._item_names))
592
+
593
+ def execute(self):
594
+ if self.is_valid():
595
+ if self._item_names:
596
+ items = self._item_names
597
+ else:
598
+ res = self._service_provider.item_service.list(
599
+ self._project.id, self._from_folder.id, EmptyQuery()
600
+ )
601
+ if res.error:
602
+ raise AppException(res.error)
603
+ items = [i.name for i in res.data]
604
+ try:
605
+ self._validate_limitations(len(items))
606
+ except AppValidationException as e:
607
+ self._response.errors = e
608
+ return self._response
609
+ skipped_items = []
610
+ if self._duplicate_strategy == "skip":
611
+ existing_items = []
612
+ for i in range(0, len(items), self._chunk_size):
613
+ query = Filter(
614
+ "name", items[i : i + self._chunk_size], OperatorEnum.IN
615
+ ) # noqa
616
+ res = self._service_provider.item_service.list(
617
+ self._project.id, self._to_folder.id, query
618
+ )
619
+ if res.error:
620
+ raise AppException(res.error)
621
+ if not res.data:
622
+ continue
623
+ existing_items += res.data
624
+ duplications = [item.name for item in existing_items]
625
+ items_to_processing = list(set(items) - set(duplications))
626
+ skipped_items.extend(duplications)
627
+ else:
628
+ items_to_processing = items
629
+ if items_to_processing:
630
+ for i in range(0, len(items_to_processing), self._chunk_size):
631
+ chunk_to_process = items_to_processing[
632
+ i : i + self._chunk_size
633
+ ] # noqa: E203
634
+ response = self._service_provider.items.copy_move_multiple(
635
+ project=self._project,
636
+ from_folder=self._from_folder,
637
+ to_folder=self._to_folder,
638
+ item_names=chunk_to_process,
639
+ include_annotations=self._include_annotations,
640
+ duplicate_strategy=self._duplicate_strategy,
641
+ operation=self._operation,
642
+ )
643
+ if not response.ok or not response.data.get("poll_id"):
644
+ skipped_items.extend(chunk_to_process)
645
+ continue
646
+ try:
647
+ self._service_provider.items.await_copy_move(
648
+ project=self._project,
649
+ poll_id=response.data["poll_id"],
650
+ items_count=len(chunk_to_process),
651
+ )
652
+ except BackendError as e:
653
+ self._response.errors = AppException(e)
654
+ return self._response
655
+ existing_items = []
656
+ for i in range(0, len(items_to_processing), self._chunk_size):
657
+ res = self._service_provider.item_service.list(
658
+ self._project.id,
659
+ self._to_folder.id,
660
+ Filter(
661
+ "name",
662
+ items_to_processing[i : i + self._chunk_size],
663
+ OperatorEnum.IN,
664
+ ), # noqa
665
+ )
666
+ if res.error:
667
+ raise AppException(res.error)
668
+
669
+ existing_items += res.data
670
+
671
+ existing_item_names_set = {item.name for item in existing_items}
672
+ items_to_processing_names_set = set(items_to_processing)
673
+ processed_items = existing_item_names_set.intersection(
674
+ items_to_processing_names_set
675
+ )
676
+ skipped_items.extend(
677
+ list(items_to_processing_names_set - processed_items)
678
+ )
679
+ operation_processing_map = {"copy": "Copied", "move": "Moved"}
680
+ self.reporter.log_info(
681
+ f"{operation_processing_map[self._operation]} {len(processed_items)}/{len(items_to_processing)} item(s) from "
682
+ f"{self._project.name}{'' if self._from_folder.is_root else f'/{self._from_folder.name}'} to "
683
+ f"{self._project.name}{'' if self._to_folder.is_root else f'/{self._to_folder.name}'}"
684
+ )
685
+ self._response.data = list(set(skipped_items))
686
+ return self._response
687
+
688
+
540
689
  class SetAnnotationStatues(BaseReportableUseCase):
541
690
  CHUNK_SIZE = 500
542
691
  ERROR_MESSAGE = "Failed to change status"
@@ -926,7 +1075,6 @@ class AddItemsToSubsetUseCase(BaseUseCase):
926
1075
  self,
927
1076
  ):
928
1077
  if self.is_valid():
929
-
930
1078
  futures = []
931
1079
  with ThreadPoolExecutor(max_workers=4) as executor:
932
1080
  for path, items in self.path_separated.items():
@@ -82,7 +82,10 @@ class PrepareExportUseCase(BaseUseCase):
82
82
  raise AppValidationException(
83
83
  "COCO format is not supported for this project."
84
84
  )
85
- elif self._export_type == 3 and self._project.type != ProjectType.GEN_AI.value:
85
+ elif (
86
+ self._export_type == 3
87
+ and self._project.type != ProjectType.MULTIMODAL.value
88
+ ):
86
89
  raise AppValidationException(
87
90
  "CSV format is not supported for this project."
88
91
  )