superannotate 4.4.31.dev1__tar.gz → 4.4.32__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.
- {superannotate-4.4.31.dev1/src/superannotate.egg-info → superannotate-4.4.32}/PKG-INFO +1 -1
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/__init__.py +1 -1
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/sdk_interface.py +80 -12
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/serviceproviders.py +10 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/annotations.py +1 -1
- superannotate-4.4.32/src/superannotate/lib/core/usecases/integrations.py +179 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/items.py +46 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/annotation_adapter.py +1 -1
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/controller.py +23 -1
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/annotation.py +32 -14
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/explore.py +23 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/integration.py +5 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/stream_data_handler.py +77 -41
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/utils.py +72 -2
- {superannotate-4.4.31.dev1 → superannotate-4.4.32/src/superannotate.egg-info}/PKG-INFO +1 -1
- superannotate-4.4.31.dev1/src/superannotate/lib/core/usecases/integrations.py +0 -78
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/LICENSE +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/MANIFEST.in +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/README.rst +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/requirements.txt +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/setup.cfg +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/setup.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/analytics/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/analytics/aggregators.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/analytics/common.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/bin/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/bin/superannotate.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/common.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/exceptions.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/helpers.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/conversion.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/baseStrategy.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_api.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_converter.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_to_sa_pixel.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/coco_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/sa_pixel_to_coco.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/coco_converters/sa_vector_to_coco.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/converters.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_helper.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/dataloop_converters/dataloop_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/googlecloud_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/googlecloud_converters/googlecloud_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_helper.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_to_sa_pixel.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/labelbox_converters/labelbox_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/sa_json_helper.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_to_sa_pixel.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/sagemaker_converters/sagemaker_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_helper.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_to_sa_pixel.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/supervisely_converters/supervisely_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vgg_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_helper.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vgg_converters/vgg_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/voc_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_helper.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_to_sa_pixel.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/voc_converters/voc_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vott_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vott_converters/vott_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/vott_converters/vott_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/yolo_converters/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/yolo_converters/yolo_strategies.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/converters/yolo_converters/yolo_to_sa_vector.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/export_from_sa_conversions.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/import_to_sa_conversions.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/input_converters/sa_conversion.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/base_interface.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/cli_interface.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/sdk/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/sdk/folders.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/sdk/project.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/interface/types.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/app/serializers.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/base_usecases.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/conditions.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/config.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/base.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/classes.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/filters.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/folder.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/integrations.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/items.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/project.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/project_entities.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/entities/work_managament.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/enums.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/exceptions.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/jsx_conditions.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/plugin.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/pydantic_v1.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/reporter.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/repositories.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/response.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/service_types.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/types.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/base.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/classes.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/custom_fields.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/folders.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/images.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/models.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/projects.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/utils.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/video_convertor.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/custom_entities.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/helpers.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/query_builder.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/repositories.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/serviceprovider.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/__init__.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/annotation_class.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/folder.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/http_client.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/item.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/item_service.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/project.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/services/work_management.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/infrastructure/validators.py +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate.egg-info/SOURCES.txt +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate.egg-info/dependency_links.txt +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate.egg-info/entry_points.txt +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate.egg-info/requires.txt +0 -0
- {superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate.egg-info/top_level.txt +0 -0
|
@@ -461,6 +461,16 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
461
461
|
def pause_user_activity(
|
|
462
462
|
self, pk: Union[int, str], projects: Union[List[int], List[str], Literal["*"]]
|
|
463
463
|
):
|
|
464
|
+
"""
|
|
465
|
+
Block the team contributor from requesting items from the projects.
|
|
466
|
+
|
|
467
|
+
:param pk: The email address or user ID of the team contributor.
|
|
468
|
+
:type pk: str or int
|
|
469
|
+
|
|
470
|
+
:param projects: A list of project names or IDs from which the user should be blocked.
|
|
471
|
+
The special value "*" means block access to all projects
|
|
472
|
+
:type projects: Union[List[int], List[str], Literal["*"]]
|
|
473
|
+
"""
|
|
464
474
|
user = self.controller.work_management.get_user_metadata(pk=pk)
|
|
465
475
|
if user.role is not WMUserTypeEnum.Contributor:
|
|
466
476
|
raise AppException("User must have a contributor role to pause activity.")
|
|
@@ -474,6 +484,16 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
474
484
|
def resume_user_activity(
|
|
475
485
|
self, pk: Union[int, str], projects: Union[List[int], List[str], Literal["*"]]
|
|
476
486
|
):
|
|
487
|
+
"""
|
|
488
|
+
Resume the team contributor from requesting items from the projects.
|
|
489
|
+
|
|
490
|
+
:param pk: The email address or user ID of the team contributor.
|
|
491
|
+
:type pk: str or int
|
|
492
|
+
|
|
493
|
+
:param projects: A list of project names or IDs from which the user should be resumed.
|
|
494
|
+
The special value "*" means resume access to all projects
|
|
495
|
+
:type projects: Union[List[int], List[str], Literal["*"]]
|
|
496
|
+
"""
|
|
477
497
|
user = self.controller.work_management.get_user_metadata(pk=pk)
|
|
478
498
|
if user.role is not WMUserTypeEnum.Contributor:
|
|
479
499
|
raise AppException("User must have a contributor role to resume activity.")
|
|
@@ -501,7 +521,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
501
521
|
"""
|
|
502
522
|
|
|
503
523
|
def retrieve_context(
|
|
504
|
-
|
|
524
|
+
component_data: List[dict], component_pk: str
|
|
505
525
|
) -> Tuple[bool, typing.Any]:
|
|
506
526
|
try:
|
|
507
527
|
for component in component_data:
|
|
@@ -512,9 +532,9 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
512
532
|
if found:
|
|
513
533
|
return found, val
|
|
514
534
|
if (
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
535
|
+
"id" in component
|
|
536
|
+
and component["id"] == component_pk
|
|
537
|
+
and component["type"] == "webComponent"
|
|
518
538
|
):
|
|
519
539
|
return True, json.loads(component.get("context"))
|
|
520
540
|
|
|
@@ -2919,32 +2939,80 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
2919
2939
|
project: NotEmptyStr,
|
|
2920
2940
|
integration: Union[NotEmptyStr, IntegrationEntity],
|
|
2921
2941
|
folder_path: Optional[NotEmptyStr] = None,
|
|
2942
|
+
*,
|
|
2943
|
+
query: Optional[NotEmptyStr] = None,
|
|
2944
|
+
item_name_column: Optional[NotEmptyStr] = None,
|
|
2945
|
+
custom_item_name: Optional[NotEmptyStr] = None,
|
|
2946
|
+
component_mapping: Optional[Dict[str, str]] = None,
|
|
2922
2947
|
):
|
|
2923
|
-
"""Link images from integrated external storage to SuperAnnotate.
|
|
2948
|
+
"""Link images from integrated external storage to SuperAnnotate from AWS, GCP, Azure, Databricks.
|
|
2924
2949
|
|
|
2925
2950
|
:param project: project name or folder path where items should be attached (e.g., “project1/folder1”).
|
|
2926
2951
|
:type project: str
|
|
2927
2952
|
|
|
2928
|
-
:param integration:
|
|
2929
|
-
|
|
2953
|
+
:param integration: The existing integration name or metadata dict to pull items from.
|
|
2954
|
+
Mandatory keys in integration metadata’s dict is “name”.
|
|
2930
2955
|
:type integration: str or dict
|
|
2931
2956
|
|
|
2932
2957
|
:param folder_path: Points to an exact folder/directory within given storage.
|
|
2933
|
-
|
|
2958
|
+
If None, items are fetched from the root directory.
|
|
2934
2959
|
:type folder_path: str
|
|
2960
|
+
|
|
2961
|
+
:param query: (Only for Databricks). The SQL query to retrieve specific columns from Databricks.
|
|
2962
|
+
If provided, the function will execute the query and use the results for mapping and uploading.
|
|
2963
|
+
:type query: Optional[str]
|
|
2964
|
+
|
|
2965
|
+
:param item_name_column: (Only for Databricks). The column name from the SQL query whose values
|
|
2966
|
+
will be used as item names. If this is provided, custom_item_name cannot be used.
|
|
2967
|
+
The column must exist in the query result.
|
|
2968
|
+
:type item_name_column: Optional[str]
|
|
2969
|
+
|
|
2970
|
+
:param custom_item_name: (Only for Databricks). A manually defined prefix for item names.
|
|
2971
|
+
A random 10-character suffix will be appended to ensure uniqueness.
|
|
2972
|
+
If this is provided, item_name_column cannot be used.
|
|
2973
|
+
:type custom_item_name: Optional[str]
|
|
2974
|
+
|
|
2975
|
+
:param component_mapping: (Only for Databricks). A dictionary mapping Databricks
|
|
2976
|
+
columns to SuperAnnotate component IDs.
|
|
2977
|
+
:type component_mapping: Optional[dict]
|
|
2978
|
+
|
|
2979
|
+
|
|
2980
|
+
Request Example:
|
|
2981
|
+
::
|
|
2982
|
+
|
|
2983
|
+
client.attach_items_from_integrated_storage(
|
|
2984
|
+
project="project_name",
|
|
2985
|
+
integration="databricks_integration",
|
|
2986
|
+
query="SELECT * FROM integration_data LIMIT 10",
|
|
2987
|
+
item_name_column="prompt",
|
|
2988
|
+
component_mapping={
|
|
2989
|
+
"category": "_item_category",
|
|
2990
|
+
"prompt_id": "id",
|
|
2991
|
+
"prompt": "prompt"
|
|
2992
|
+
}
|
|
2993
|
+
)
|
|
2994
|
+
|
|
2935
2995
|
"""
|
|
2936
2996
|
project, folder = self.controller.get_project_folder_by_path(project)
|
|
2937
2997
|
_integration = None
|
|
2938
2998
|
if isinstance(integration, str):
|
|
2939
2999
|
integration = IntegrationEntity(name=integration)
|
|
2940
3000
|
for i in self.controller.integrations.list().data:
|
|
2941
|
-
if integration.name == i.name:
|
|
3001
|
+
if integration.name.lower() == i.name.lower():
|
|
2942
3002
|
_integration = i
|
|
2943
3003
|
break
|
|
2944
3004
|
else:
|
|
2945
3005
|
raise AppException("Integration not found.")
|
|
3006
|
+
|
|
2946
3007
|
response = self.controller.integrations.attach_items(
|
|
2947
|
-
project,
|
|
3008
|
+
project=project,
|
|
3009
|
+
folder=folder,
|
|
3010
|
+
integration=_integration,
|
|
3011
|
+
folder_path=folder_path,
|
|
3012
|
+
query=query,
|
|
3013
|
+
item_name_column=item_name_column,
|
|
3014
|
+
custom_item_name=custom_item_name,
|
|
3015
|
+
component_mapping=component_mapping,
|
|
2948
3016
|
)
|
|
2949
3017
|
if response.errors:
|
|
2950
3018
|
raise AppException(response.errors)
|
|
@@ -3593,7 +3661,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
3593
3661
|
"skip", "replace", "replace_annotations_only"
|
|
3594
3662
|
] = "skip",
|
|
3595
3663
|
):
|
|
3596
|
-
"""Copy
|
|
3664
|
+
"""Copy items in bulk between folders in a project
|
|
3597
3665
|
|
|
3598
3666
|
:param source: project name (root) or folder path to pick items from (e.g., “project1/folder1”).
|
|
3599
3667
|
:type source: str
|
|
@@ -3657,7 +3725,7 @@ class SAClient(BaseInterfaceFacade, metaclass=TrackableMeta):
|
|
|
3657
3725
|
"skip", "replace", "replace_annotations_only"
|
|
3658
3726
|
] = "skip",
|
|
3659
3727
|
):
|
|
3660
|
-
"""Move
|
|
3728
|
+
"""Move items in bulk between folders in a project
|
|
3661
3729
|
|
|
3662
3730
|
:param source: project name (root) or folder path to pick items from (e.g., “project1/folder1”).
|
|
3663
3731
|
:type source: str
|
{superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/serviceproviders.py
RENAMED
|
@@ -490,6 +490,7 @@ class BaseAnnotationService(SuperannotateServiceProvider):
|
|
|
490
490
|
self,
|
|
491
491
|
project: entities.ProjectEntity,
|
|
492
492
|
item_ids: List[int],
|
|
493
|
+
chunk_size: int = 1000,
|
|
493
494
|
) -> Dict[str, List]:
|
|
494
495
|
raise NotImplementedError
|
|
495
496
|
|
|
@@ -592,6 +593,7 @@ class BaseIntegrationService(SuperannotateServiceProvider):
|
|
|
592
593
|
folder: entities.FolderEntity,
|
|
593
594
|
integration: entities.IntegrationEntity,
|
|
594
595
|
folder_name: str = None,
|
|
596
|
+
options: Dict[str, str] = None,
|
|
595
597
|
) -> ServiceResponse:
|
|
596
598
|
raise NotImplementedError
|
|
597
599
|
|
|
@@ -670,6 +672,14 @@ class BaseExploreService(SuperannotateServiceProvider):
|
|
|
670
672
|
) -> ServiceResponse:
|
|
671
673
|
raise NotImplementedError
|
|
672
674
|
|
|
675
|
+
@abstractmethod
|
|
676
|
+
def query_item_count(
|
|
677
|
+
self,
|
|
678
|
+
project: entities.ProjectEntity,
|
|
679
|
+
query: str = None,
|
|
680
|
+
) -> ServiceResponse:
|
|
681
|
+
raise NotImplementedError
|
|
682
|
+
|
|
673
683
|
|
|
674
684
|
class BaseServiceProvider:
|
|
675
685
|
projects: BaseProjectService
|
|
@@ -2046,7 +2046,7 @@ class UploadMultiModalAnnotationsUseCase(BaseReportableUseCase):
|
|
|
2046
2046
|
f"annotations to the project {self._project.name}."
|
|
2047
2047
|
)
|
|
2048
2048
|
if not self._root_folder.is_root:
|
|
2049
|
-
if len(distributed_items) > 1 or
|
|
2049
|
+
if len(distributed_items) > 1 or "" not in distributed_items:
|
|
2050
2050
|
raise AppException(
|
|
2051
2051
|
"You can't include a folder when uploading from within a folder."
|
|
2052
2052
|
)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from lib.core.conditions import Condition
|
|
5
|
+
from lib.core.conditions import CONDITION_EQ as EQ
|
|
6
|
+
from lib.core.entities import FolderEntity
|
|
7
|
+
from lib.core.entities import IntegrationEntity
|
|
8
|
+
from lib.core.entities import ProjectEntity
|
|
9
|
+
from lib.core.entities.integrations import IntegrationTypeEnum
|
|
10
|
+
from lib.core.enums import ProjectType
|
|
11
|
+
from lib.core.exceptions import AppException
|
|
12
|
+
from lib.core.reporter import Reporter
|
|
13
|
+
from lib.core.response import Response
|
|
14
|
+
from lib.core.serviceproviders import BaseServiceProvider
|
|
15
|
+
from lib.core.usecases import BaseReportableUseCase
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GetIntegrations(BaseReportableUseCase):
|
|
19
|
+
def __init__(self, reporter: Reporter, service_provider: BaseServiceProvider):
|
|
20
|
+
|
|
21
|
+
super().__init__(reporter)
|
|
22
|
+
self._service_provider = service_provider
|
|
23
|
+
|
|
24
|
+
def execute(self) -> Response:
|
|
25
|
+
integrations = self._service_provider.integrations.list().data.integrations
|
|
26
|
+
integrations = list(sorted(integrations, key=lambda x: x.createdAt))
|
|
27
|
+
integrations.reverse()
|
|
28
|
+
self._response.data = integrations
|
|
29
|
+
return self._response
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AttachIntegrations(BaseReportableUseCase):
|
|
33
|
+
MULTIMODAL_INTEGRATIONS = [
|
|
34
|
+
IntegrationTypeEnum.DATABRICKS,
|
|
35
|
+
IntegrationTypeEnum.SNOWFLAKE,
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
reporter: Reporter,
|
|
41
|
+
project: ProjectEntity,
|
|
42
|
+
folder: FolderEntity,
|
|
43
|
+
service_provider: BaseServiceProvider,
|
|
44
|
+
integration: IntegrationEntity,
|
|
45
|
+
folder_path: str = None,
|
|
46
|
+
query: Optional[str] = None,
|
|
47
|
+
item_name_column: Optional[str] = None,
|
|
48
|
+
custom_item_name: Optional[str] = None,
|
|
49
|
+
component_mapping: Optional[Dict[str, str]] = None,
|
|
50
|
+
):
|
|
51
|
+
super().__init__(reporter)
|
|
52
|
+
self._project = project
|
|
53
|
+
self._folder = folder
|
|
54
|
+
self._integration = integration
|
|
55
|
+
self._service_provider = service_provider
|
|
56
|
+
self._folder_path = folder_path
|
|
57
|
+
self._query = query
|
|
58
|
+
self._item_name_column = item_name_column
|
|
59
|
+
self._custom_item_name = custom_item_name
|
|
60
|
+
self._component_mapping = component_mapping
|
|
61
|
+
self._options = {} # using only for Databricks and Snowflake
|
|
62
|
+
self._item_category_column = None
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def _upload_path(self):
|
|
66
|
+
return f"{self._project.name}{f'/{self._folder.name}' if self._folder.name != 'root' else ''}"
|
|
67
|
+
|
|
68
|
+
def validate_integration(self):
|
|
69
|
+
# TODO add support in next iterations
|
|
70
|
+
if self._integration.type == IntegrationTypeEnum.SNOWFLAKE:
|
|
71
|
+
raise AppException(
|
|
72
|
+
"Attaching items is not supported with Snowflake integration."
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if self._integration.type in self.MULTIMODAL_INTEGRATIONS:
|
|
76
|
+
if self._project.type != ProjectType.MULTIMODAL:
|
|
77
|
+
raise AppException(
|
|
78
|
+
f"{self._integration.name} integration is supported only for Multimodal projects."
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def validate_options_for_multimodal_integration(self):
|
|
82
|
+
if self._integration.type in self.MULTIMODAL_INTEGRATIONS:
|
|
83
|
+
if self._item_name_column and self._custom_item_name:
|
|
84
|
+
raise AppException(
|
|
85
|
+
"‘item_name_column and custom_item_name cannot be used simultaneously."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if not self._item_name_column and not self._custom_item_name:
|
|
89
|
+
raise AppException(
|
|
90
|
+
"Either item_name_column or custom_item_name is required."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if not all((self._query, self._component_mapping)):
|
|
94
|
+
raise AppException(
|
|
95
|
+
f"{self._integration.name} integration requires both a query and component_mapping."
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
category_setting: bool = bool(
|
|
99
|
+
next(
|
|
100
|
+
(
|
|
101
|
+
setting.value
|
|
102
|
+
for setting in self._service_provider.projects.list_settings(
|
|
103
|
+
self._project
|
|
104
|
+
).data
|
|
105
|
+
if setting.attribute == "CategorizeItems"
|
|
106
|
+
),
|
|
107
|
+
None,
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
if (
|
|
111
|
+
not category_setting
|
|
112
|
+
and "_item_category" in self._component_mapping.values()
|
|
113
|
+
):
|
|
114
|
+
raise AppException(
|
|
115
|
+
"Item Category must be enabled for a project to use _item_category"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
self._item_category_column = next(
|
|
119
|
+
(
|
|
120
|
+
k
|
|
121
|
+
for k, v in self._component_mapping.items()
|
|
122
|
+
if v == "_item_category"
|
|
123
|
+
),
|
|
124
|
+
None,
|
|
125
|
+
)
|
|
126
|
+
if self._item_category_column:
|
|
127
|
+
del self._component_mapping[self._item_category_column]
|
|
128
|
+
|
|
129
|
+
sa_components = [
|
|
130
|
+
c.name.lower()
|
|
131
|
+
for c in self._service_provider.annotation_classes.list(
|
|
132
|
+
condition=Condition("project_id", self._project.id, EQ)
|
|
133
|
+
).data
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
for i in self._component_mapping.values():
|
|
137
|
+
if i.lower() not in sa_components:
|
|
138
|
+
raise AppException(
|
|
139
|
+
f"Component mapping contains invalid component ID: `{i}`"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def generate_options_for_multimodal_integration(self):
|
|
143
|
+
self._options["query"] = self._query
|
|
144
|
+
self._options["item_name"] = (
|
|
145
|
+
self._custom_item_name if self._custom_item_name else self._item_name_column
|
|
146
|
+
)
|
|
147
|
+
self._options["prefix"] = True if self._custom_item_name else False
|
|
148
|
+
self._options["column_class_map"] = self._component_mapping
|
|
149
|
+
if self._item_category_column:
|
|
150
|
+
self._options["item_category"] = self._item_category_column
|
|
151
|
+
|
|
152
|
+
def execute(self) -> Response:
|
|
153
|
+
if self.is_valid():
|
|
154
|
+
if self._integration.type in self.MULTIMODAL_INTEGRATIONS:
|
|
155
|
+
self.generate_options_for_multimodal_integration()
|
|
156
|
+
|
|
157
|
+
self.reporter.log_info(
|
|
158
|
+
"Attaching file(s) from "
|
|
159
|
+
f"{self._integration.root}{f'/{self._folder_path}' if self._folder_path else ''} "
|
|
160
|
+
f"to {self._upload_path}. This may take some time."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
attache_response = self._service_provider.integrations.attach_items(
|
|
164
|
+
project=self._project,
|
|
165
|
+
folder=self._folder,
|
|
166
|
+
integration=self._integration,
|
|
167
|
+
folder_name=self._folder_path
|
|
168
|
+
if self._integration.type not in self.MULTIMODAL_INTEGRATIONS
|
|
169
|
+
else None,
|
|
170
|
+
options=self._options if self._options else None,
|
|
171
|
+
)
|
|
172
|
+
if not attache_response.ok:
|
|
173
|
+
self._response.errors = AppException(
|
|
174
|
+
f"An error occurred for {self._integration.name}. Please make sure: "
|
|
175
|
+
"\n - The bucket exists."
|
|
176
|
+
"\n - The connection is valid."
|
|
177
|
+
"\n - The path to a specified directory is correct."
|
|
178
|
+
)
|
|
179
|
+
return self._response
|
{superannotate-4.4.31.dev1 → superannotate-4.4.32}/src/superannotate/lib/core/usecases/items.py
RENAMED
|
@@ -163,6 +163,52 @@ class QueryEntitiesUseCase(BaseReportableUseCase):
|
|
|
163
163
|
return self._response
|
|
164
164
|
|
|
165
165
|
|
|
166
|
+
class QueryEntitiesCountUseCase(BaseReportableUseCase):
|
|
167
|
+
def __init__(
|
|
168
|
+
self,
|
|
169
|
+
reporter: Reporter,
|
|
170
|
+
project: ProjectEntity,
|
|
171
|
+
service_provider: BaseServiceProvider,
|
|
172
|
+
query: str,
|
|
173
|
+
):
|
|
174
|
+
super().__init__(reporter)
|
|
175
|
+
self._project = project
|
|
176
|
+
self._service_provider = service_provider
|
|
177
|
+
self._query = query
|
|
178
|
+
|
|
179
|
+
def validate_arguments(self):
|
|
180
|
+
if self._query:
|
|
181
|
+
response = self._service_provider.explore.validate_saqul_query(
|
|
182
|
+
project=self._project, query=self._query
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
if not response.ok:
|
|
186
|
+
raise AppException(response.error)
|
|
187
|
+
if response.data["isValidQuery"]:
|
|
188
|
+
self._query = response.data["parsedQuery"]
|
|
189
|
+
else:
|
|
190
|
+
raise AppException("Incorrect query.")
|
|
191
|
+
else:
|
|
192
|
+
response = self._service_provider.explore.validate_saqul_query(
|
|
193
|
+
self._project, "-"
|
|
194
|
+
)
|
|
195
|
+
if not response.ok:
|
|
196
|
+
raise AppException(response.error)
|
|
197
|
+
|
|
198
|
+
def execute(self) -> Response:
|
|
199
|
+
if self.is_valid():
|
|
200
|
+
query_kwargs = {"query": self._query}
|
|
201
|
+
service_response = self._service_provider.explore.query_item_count(
|
|
202
|
+
self._project,
|
|
203
|
+
**query_kwargs,
|
|
204
|
+
)
|
|
205
|
+
if service_response.ok:
|
|
206
|
+
self._response.data = service_response.data
|
|
207
|
+
else:
|
|
208
|
+
self._response.errors = service_response.data
|
|
209
|
+
return self._response
|
|
210
|
+
|
|
211
|
+
|
|
166
212
|
class AssignItemsUseCase(BaseUseCase):
|
|
167
213
|
CHUNK_SIZE = 500
|
|
168
214
|
|
|
@@ -44,7 +44,7 @@ class BaseMultimodalAnnotationAdapter(ABC):
|
|
|
44
44
|
return None
|
|
45
45
|
|
|
46
46
|
def set_component_value(self, component_id: str, value: Any):
|
|
47
|
-
self.annotation
|
|
47
|
+
self.annotation.setdefault("data", {}).setdefault(component_id, {})["value"] = value
|
|
48
48
|
return self
|
|
49
49
|
|
|
50
50
|
|
|
@@ -1138,7 +1138,11 @@ class IntegrationManager(BaseManager):
|
|
|
1138
1138
|
project: ProjectEntity,
|
|
1139
1139
|
folder: FolderEntity,
|
|
1140
1140
|
integration: IntegrationEntity,
|
|
1141
|
-
folder_path: str,
|
|
1141
|
+
folder_path: str = None,
|
|
1142
|
+
query: Optional[str] = None,
|
|
1143
|
+
item_name_column: Optional[str] = None,
|
|
1144
|
+
custom_item_name: Optional[str] = None,
|
|
1145
|
+
component_mapping: Optional[Dict[str, str]] = None,
|
|
1142
1146
|
):
|
|
1143
1147
|
use_case = usecases.AttachIntegrations(
|
|
1144
1148
|
reporter=Reporter(),
|
|
@@ -1147,6 +1151,10 @@ class IntegrationManager(BaseManager):
|
|
|
1147
1151
|
folder=folder,
|
|
1148
1152
|
integration=integration,
|
|
1149
1153
|
folder_path=folder_path,
|
|
1154
|
+
query=query,
|
|
1155
|
+
item_name_column=item_name_column,
|
|
1156
|
+
custom_item_name=custom_item_name,
|
|
1157
|
+
component_mapping=component_mapping,
|
|
1150
1158
|
)
|
|
1151
1159
|
return use_case.execute()
|
|
1152
1160
|
|
|
@@ -1670,3 +1678,17 @@ class Controller(BaseController):
|
|
|
1670
1678
|
return ItemManager.process_response(
|
|
1671
1679
|
self.service_provider, items, project, folder, map_fields=False
|
|
1672
1680
|
)
|
|
1681
|
+
|
|
1682
|
+
def query_items_count(self, project_name: str, query: str = None) -> int:
|
|
1683
|
+
project = self.get_project(project_name)
|
|
1684
|
+
|
|
1685
|
+
use_case = usecases.QueryEntitiesCountUseCase(
|
|
1686
|
+
reporter=self.get_default_reporter(),
|
|
1687
|
+
project=project,
|
|
1688
|
+
query=query,
|
|
1689
|
+
service_provider=self.service_provider,
|
|
1690
|
+
)
|
|
1691
|
+
response = use_case.execute()
|
|
1692
|
+
if response.errors:
|
|
1693
|
+
raise AppException(response.errors)
|
|
1694
|
+
return response.data["count"]
|
|
@@ -18,6 +18,8 @@ from lib.core.service_types import UploadAnnotations
|
|
|
18
18
|
from lib.core.service_types import UploadAnnotationsResponse
|
|
19
19
|
from lib.core.serviceproviders import BaseAnnotationService
|
|
20
20
|
from lib.infrastructure.stream_data_handler import StreamedAnnotations
|
|
21
|
+
from lib.infrastructure.utils import annotation_is_valid
|
|
22
|
+
from lib.infrastructure.utils import divide_to_chunks
|
|
21
23
|
|
|
22
24
|
try:
|
|
23
25
|
from pydantic.v1 import parse_obj_as
|
|
@@ -170,21 +172,29 @@ class AnnotationService(BaseAnnotationService):
|
|
|
170
172
|
self,
|
|
171
173
|
project: entities.ProjectEntity,
|
|
172
174
|
item_ids: List[int],
|
|
175
|
+
chunk_size: int = 1000,
|
|
173
176
|
) -> Dict[str, List]:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
177
|
+
small = []
|
|
178
|
+
large = []
|
|
179
|
+
|
|
180
|
+
chunks = divide_to_chunks(item_ids, chunk_size)
|
|
181
|
+
for chunk in chunks:
|
|
182
|
+
response = self.client.request(
|
|
183
|
+
method="POST",
|
|
184
|
+
url=urljoin(
|
|
185
|
+
self.get_assets_provider_url(), self.URL_CLASSIFY_ITEM_SIZE
|
|
186
|
+
),
|
|
187
|
+
params={"limit": len(chunk)},
|
|
188
|
+
data={
|
|
189
|
+
"project_id": project.id,
|
|
190
|
+
"item_ids": chunk,
|
|
191
|
+
},
|
|
192
|
+
)
|
|
193
|
+
if not response.ok:
|
|
194
|
+
raise AppException(response.error)
|
|
195
|
+
small.extend([i["data"] for i in response.data.get("small", {}).values()])
|
|
196
|
+
large.extend(response.data.get("large", []))
|
|
197
|
+
return {"small": small, "large": large}
|
|
188
198
|
|
|
189
199
|
async def download_big_annotation(
|
|
190
200
|
self,
|
|
@@ -218,6 +228,14 @@ class AnnotationService(BaseAnnotationService):
|
|
|
218
228
|
) as session:
|
|
219
229
|
start_response = await session.request("post", url, params=query_params)
|
|
220
230
|
res = await start_response.json()
|
|
231
|
+
if start_response.status > 299 or not annotation_is_valid(res):
|
|
232
|
+
logger.debug(
|
|
233
|
+
f"Failed to download large annotation; item_id [{item_id}];"
|
|
234
|
+
f" response: {res}; http_status: {start_response.status}"
|
|
235
|
+
)
|
|
236
|
+
raise AppException(
|
|
237
|
+
f"Failed to download large annotation, ID: {item_id}"
|
|
238
|
+
)
|
|
221
239
|
Path(download_path).mkdir(exist_ok=True, parents=True)
|
|
222
240
|
|
|
223
241
|
dest_path = Path(download_path) / (item_name + ".json")
|
|
@@ -10,6 +10,7 @@ from lib.core.service_types import ServiceResponse
|
|
|
10
10
|
from lib.core.service_types import SubsetListResponse
|
|
11
11
|
from lib.core.service_types import UploadCustomFieldValuesResponse
|
|
12
12
|
from lib.core.serviceproviders import BaseExploreService
|
|
13
|
+
from superannotate import AppException
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class ExploreService(BaseExploreService):
|
|
@@ -25,6 +26,7 @@ class ExploreService(BaseExploreService):
|
|
|
25
26
|
URL_UPLOAD_CUSTOM_VALUE = "custom/metadata/item"
|
|
26
27
|
URL_SAQUL_QUERY = "items/search"
|
|
27
28
|
URL_VALIDATE_SAQUL_QUERY = "items/parse/query"
|
|
29
|
+
URL_QUERY_COUNT = "items/count"
|
|
28
30
|
|
|
29
31
|
@property
|
|
30
32
|
def explore_service_url(self):
|
|
@@ -201,3 +203,24 @@ class ExploreService(BaseExploreService):
|
|
|
201
203
|
else:
|
|
202
204
|
response = ServiceResponse(status=200, res_data=[])
|
|
203
205
|
return response
|
|
206
|
+
|
|
207
|
+
def query_item_count(
|
|
208
|
+
self,
|
|
209
|
+
project: entities.ProjectEntity,
|
|
210
|
+
query: str = None,
|
|
211
|
+
) -> ServiceResponse:
|
|
212
|
+
|
|
213
|
+
params = {
|
|
214
|
+
"project_id": project.id,
|
|
215
|
+
"includeFolderNames": True,
|
|
216
|
+
}
|
|
217
|
+
data = {"query": query}
|
|
218
|
+
response = self.client.request(
|
|
219
|
+
urljoin(self.explore_service_url, self.URL_QUERY_COUNT),
|
|
220
|
+
"post",
|
|
221
|
+
params=params,
|
|
222
|
+
data=data,
|
|
223
|
+
)
|
|
224
|
+
if not response.ok:
|
|
225
|
+
raise AppException(response.error)
|
|
226
|
+
return response
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
1
3
|
from lib.core import entities
|
|
2
4
|
from lib.core.service_types import IntegrationListResponse
|
|
3
5
|
from lib.core.serviceproviders import BaseIntegrationService
|
|
@@ -23,6 +25,7 @@ class IntegrationService(BaseIntegrationService):
|
|
|
23
25
|
folder: entities.FolderEntity,
|
|
24
26
|
integration: entities.IntegrationEntity,
|
|
25
27
|
folder_name: str = None,
|
|
28
|
+
options: Dict[str, str] = None,
|
|
26
29
|
):
|
|
27
30
|
data = {
|
|
28
31
|
"team_id": project.team_id,
|
|
@@ -32,6 +35,8 @@ class IntegrationService(BaseIntegrationService):
|
|
|
32
35
|
}
|
|
33
36
|
if folder_name:
|
|
34
37
|
data["customer_folder_name"] = folder_name
|
|
38
|
+
if options:
|
|
39
|
+
data["options"] = options
|
|
35
40
|
return self.client.request(
|
|
36
41
|
self.URL_ATTACH_INTEGRATIONS.format(project.team_id), "post", data=data
|
|
37
42
|
)
|