From a124470fb883c932dd5dba7942ba6c3641015c87 Mon Sep 17 00:00:00 2001 From: Vaghinak Basentsyan Date: Mon, 14 Feb 2022 09:40:37 +0400 Subject: [PATCH 1/4] Changed init flow --- src/superannotate/__init__.py | 3 +- src/superannotate/lib/__init__.py | 20 ++- .../lib/app/interface/base_interface.py | 8 +- .../lib/app/interface/sdk_interface.py | 7 +- .../lib/infrastructure/controller.py | 126 ++++++------------ .../test_annotations_pre_processing.py | 2 +- tests/unit/test_controller_init.py | 34 +++-- 7 files changed, 91 insertions(+), 109 deletions(-) diff --git a/src/superannotate/__init__.py b/src/superannotate/__init__.py index c8ce59082..42057385a 100644 --- a/src/superannotate/__init__.py +++ b/src/superannotate/__init__.py @@ -4,8 +4,8 @@ import requests import superannotate.lib.core as constances +from lib import get_default_controller from packaging.version import parse -from superannotate.lib import get_default_controller from superannotate.lib.app.analytics.class_analytics import class_distribution from superannotate.lib.app.exceptions import AppException from superannotate.lib.app.input_converters.conversion import convert_json_version @@ -112,6 +112,7 @@ controller = get_default_controller() + __all__ = [ "__version__", "controller", diff --git a/src/superannotate/lib/__init__.py b/src/superannotate/lib/__init__.py index 89f5863a8..c4db8ec42 100644 --- a/src/superannotate/lib/__init__.py +++ b/src/superannotate/lib/__init__.py @@ -5,12 +5,22 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__))) sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -controller = None +DEFAULT_CONTROLLER = None -def get_default_controller(): + +def get_default_controller(raise_exception=False): from lib.infrastructure.controller import Controller + try: + global DEFAULT_CONTROLLER + if not DEFAULT_CONTROLLER: + DEFAULT_CONTROLLER = Controller() + return DEFAULT_CONTROLLER + except Exception: + if raise_exception: + raise + - global controller - controller = Controller() - return controller +def set_default_controller(controller_obj): + # global DEFAULT_CONTROLLER + DEFAULT_CONTROLLER = controller_obj diff --git a/src/superannotate/lib/app/interface/base_interface.py b/src/superannotate/lib/app/interface/base_interface.py index 2a0381430..ba9fc8e2b 100644 --- a/src/superannotate/lib/app/interface/base_interface.py +++ b/src/superannotate/lib/app/interface/base_interface.py @@ -1,16 +1,14 @@ -from lib.infrastructure.controller import Controller +from lib import get_default_controller from lib.infrastructure.repositories import ConfigRepository class BaseInterfaceFacade: def __init__(self): self._config_path = None + self._controller = get_default_controller() @property def controller(self): if not ConfigRepository().get_one("token"): raise Exception("Config does not exists!") - controller = Controller() - if self._config_path: - controller.init(config_path=self._config_path) - return controller + return self._controller diff --git a/src/superannotate/lib/app/interface/sdk_interface.py b/src/superannotate/lib/app/interface/sdk_interface.py index 02079eb8b..32e5ff1ce 100644 --- a/src/superannotate/lib/app/interface/sdk_interface.py +++ b/src/superannotate/lib/app/interface/sdk_interface.py @@ -11,8 +11,8 @@ from typing import Union import boto3 +import lib import lib.core as constances -from lib import controller from lib.app.annotation_helpers import add_annotation_bbox_to_json from lib.app.annotation_helpers import add_annotation_comment_to_json from lib.app.annotation_helpers import add_annotation_point_to_json @@ -42,6 +42,7 @@ from lib.core.types import ClassesJson from lib.core.types import MLModel from lib.core.types import Project +from lib.infrastructure.controller import Controller from pydantic import conlist from pydantic import parse_obj_as from pydantic import StrictBool @@ -50,6 +51,7 @@ logger = get_default_logger() +controller = lib.DEFAULT_CONTROLLER @validate_arguments @@ -65,8 +67,7 @@ def init(path_to_config_json: Optional[str] = None, token: str = None): :param token: Team token :type token: str """ - global controller - controller.init(config_path=path_to_config_json, token=token) + lib.DEFAULT_CONTROLLER = Controller(config_path=path_to_config_json, token=token) @validate_arguments diff --git a/src/superannotate/lib/infrastructure/controller.py b/src/superannotate/lib/infrastructure/controller.py index 63f35ef25..c28430cd0 100644 --- a/src/superannotate/lib/infrastructure/controller.py +++ b/src/superannotate/lib/infrastructure/controller.py @@ -1,12 +1,12 @@ import copy import io import os +from abc import ABCMeta from os.path import expanduser from pathlib import Path from typing import Iterable from typing import List from typing import Optional -from typing import Tuple from typing import Union import lib.core as constances @@ -37,21 +37,7 @@ from superannotate_schemas.validators import AnnotationValidators -class SingleInstanceMetaClass(type): - _instances = {} - - def __call__(cls, *args, **kwargs): - if cls not in SingleInstanceMetaClass._instances: - SingleInstanceMetaClass._instances[cls] = super().__call__(*args, **kwargs) - return SingleInstanceMetaClass._instances[cls] - - def get_instance(cls): - if cls._instances: - return cls._instances[cls] - return cls() - - -class BaseController(metaclass=SingleInstanceMetaClass): +class BaseController(metaclass=ABCMeta): def __init__(self, config_path: str, token: str = None): self._team_data = None self._token = None @@ -69,25 +55,26 @@ def __init__(self, config_path: str, token: str = None): self._user_id = None self._team_name = None self._reporter = None - self._ssl_verify = not os.environ.get("SA_TESTING", False) - self._config_path = expanduser(config_path) if config_path else constances.CONFIG_FILE_LOCATION + self._ssl_verify = not (os.environ.get("SA_TESTING", "False").lower() == "false") self._backend_url = os.environ.get("SA_URL", constances.BACKEND_URL) - if not token and not config_path: + + if token: + self._token = self._validate_token(os.environ.get("SA_TOKEN")) + elif config_path: + config_path = expanduser(config_path) + self.retrieve_configs(Path(config_path), raise_exception=True) + else: env_token = os.environ.get("SA_TOKEN") if env_token: self._token = self._validate_token(os.environ.get("SA_TOKEN")) - if token: - self._token = self._validate_token(token) - - if not self._token: - self._token, self._backend_url, self._ssl_verify = self.retrieve_configs( - Path(self._config_path), raise_exception=False - ) + else: + config_path = expanduser(constances.CONFIG_FILE_LOCATION) + self.retrieve_configs(Path(config_path), raise_exception=False) + self.initialize_backend_client() - def retrieve_configs( - self, path: Path, raise_exception=True - ) -> Tuple[Optional[str], Optional[str], Optional[str]]: + def retrieve_configs(self, path: Path, raise_exception=True): + token, backend_url, ssl_verify = None, None, None if not path.is_file() or not os.access(path, os.R_OK): if raise_exception: raise AppException( @@ -97,7 +84,7 @@ def retrieve_configs( ) try: config_repo = ConfigRepository(str(path)) - return ( + token, backend_url, ssl_verify = ( self._validate_token(config_repo.get_one("token").value), config_repo.get_one("main_endpoint").value, config_repo.get_one("ssl_verify").value, @@ -107,54 +94,36 @@ def retrieve_configs( raise AppException( f"Incorrect config file: token is not present in the config file {path}" ) - return None, None, None + self._token = token + self._backend_url = backend_url or self._backend_url + self._ssl_verify = ssl_verify or self._ssl_verify - def init( - self, token: str = None, backend_url: str = None, config_path: str = None, - ): - if backend_url: - self._backend_url = backend_url - if token: - if self._validate_token(token): - self._token = token - return self - else: - raise AppException("Invalid token.") - if not config_path: - raise AppException( - " Please provide correct config file location to sa.init()." - ) - self._config_path = config_path - self._token, self._backend_url, ssl_verify = self.retrieve_configs( - Path(config_path), raise_exception=True + @staticmethod + def _validate_token(token: str): + try: + int(token.split("=")[-1]) + except ValueError: + raise AppException("Invalid token.") + return token + + def initialize_backend_client(self): + if not self._token: + raise AppException("Team token not provided") + self._backend_client = SuperannotateBackendService( + api_url=self._backend_url, + auth_token=self._token, + logger=self._logger, + verify_ssl=self._ssl_verify, ) - self._ssl_verify = ssl_verify - return self + self._backend_client.get_session.cache_clear() + return self._backend_client @property def backend_client(self): if not self._backend_client: - if not self._token: - raise AppException("Team token not provided") - self._backend_client = SuperannotateBackendService( - api_url=self._backend_url, - auth_token=self._token, - logger=self._logger, - verify_ssl=self._ssl_verify, - ) - self._backend_client._api_url = self._backend_url - self._backend_client._auth_token = self._token - self._backend_client.get_session.cache_clear() + self.initialize_backend_client() return self._backend_client - @staticmethod - def is_valid_token(token: str): - return int(token.split("=")[-1]) - - @property - def config_path(self): - return self._config_path - @property def user_id(self): if not self._user_id: @@ -167,18 +136,11 @@ def team_name(self): _, self._team_name = self.get_team() return self._team_name - @staticmethod - def _validate_token(token: str): - try: - int(token.split("=")[-1]) - except ValueError: - raise AppException("Invalid token.") - return token - def set_token(self, token: str, backend_url: str = constances.BACKEND_URL): self._token = self._validate_token(token) - self._backend_url = backend_url - self._backend_client = self.backend_client + if backend_url: + self._backend_url = backend_url + self.initialize_backend_client() @property def projects(self): @@ -262,8 +224,8 @@ def annotation_validators(self) -> AnnotationValidators: class Controller(BaseController): - def __init__(self, config_path: str = None): - super().__init__(config_path) + def __init__(self, config_path: str = None, token: str = None): + super().__init__(config_path, token) self._team = None def _get_project(self, name: str): diff --git a/tests/integration/annotations/test_annotations_pre_processing.py b/tests/integration/annotations/test_annotations_pre_processing.py index cc1328b89..45d485384 100644 --- a/tests/integration/annotations/test_annotations_pre_processing.py +++ b/tests/integration/annotations/test_annotations_pre_processing.py @@ -45,7 +45,7 @@ def test_annotation_last_action_and_creation_type(self, reporter): self.assertEqual(instance["creationType"], CreationTypeEnum.PRE_ANNOTATION.value) self.assertEqual( type(annotation["metadata"]["lastAction"]["email"]), - type(sa.controller.team_data.data.creator_id) + type(sa.get_default_controller().team_data.data.creator_id) ) self.assertEqual( type(annotation["metadata"]["lastAction"]["timestamp"]), diff --git a/tests/unit/test_controller_init.py b/tests/unit/test_controller_init.py index 3c065011a..fdfb16c3e 100644 --- a/tests/unit/test_controller_init.py +++ b/tests/unit/test_controller_init.py @@ -1,3 +1,4 @@ +import os from os.path import join import json import pkg_resources @@ -20,21 +21,18 @@ class CLITest(TestCase): + CONFIG_FILE_DATA = '{"main_endpoint": "https://amazonaws.com:3000","token": "c9c55ct=6085","ssl_verify": false}' + # @pytest.mark.skip(reason="Need to adjust") - @pytest.mark.skip(reason="Need to adjust") @patch('builtins.input') def test_init_update(self, input_mock): input_mock.side_effect = ["y", "token"] - with open(CONFIG_FILE_LOCATION) as f: - config_data = f.read() - with patch('builtins.open', mock_open(read_data=config_data)) as config_file: + with patch('builtins.open', mock_open(read_data=self.CONFIG_FILE_DATA)) as config_file: try: with catch_prints() as out: cli = CLIFacade() cli.init() except SystemExit: - input_args = [i[0][0] for i in input_mock.call_args_list] - self.assertIn(f"File {CONFIG_FILE_LOCATION} exists. Do you want to overwrite? [y/n] : ", input_args) input_mock.assert_called_with("Input the team SDK token from https://app.superannotate.com/team : ") config_file().write.assert_called_once_with( json.dumps( @@ -65,6 +63,8 @@ def test_init_create(self, input_mock): class SKDInitTest(TestCase): + TEST_TOKEN = "toke=123" + VALID_JSON = { "token": "a"*28 + "=1234" } @@ -74,15 +74,28 @@ class SKDInitTest(TestCase): FILE_NAME = "config.json" FILE_NAME_2 = "config.json" - def test_init_flow(self): + @patch.dict(os.environ, {"SA_TOKEN": TEST_TOKEN}) + def test_env_flow(self): + import superannotate as sa + self.assertEqual(sa.get_default_controller()._token, self.TEST_TOKEN) + + def test_init_via_config_file(self): with tempfile.TemporaryDirectory() as temp_dir: token_path = f"{temp_dir}/config.json" with open(token_path, "w") as temp_config: - json.dump({"token": "token=1234"}, temp_config) + json.dump({"token": self.TEST_TOKEN}, temp_config) temp_config.close() import src.superannotate as sa sa.init(token_path) + @patch("lib.infrastructure.controller.Controller.retrieve_configs") + def test_init_default_configs_open(self, retrieve_configs): + import src.superannotate as sa + try: + sa.init() + except Exception: + self.assertTrue(retrieve_configs.call_args[0], sa.constances.CONFIG_FILE_LOCATION) + def test_init(self): with tempfile.TemporaryDirectory() as temp_dir: path = join(temp_dir, self.FILE_NAME) @@ -90,7 +103,4 @@ def test_init(self): json.dump(self.VALID_JSON, config) import src.superannotate as sa sa.init(path) - self.assertEqual(sa.controller.team_id, 1234) - - def test_(self): - import superannotate as sa \ No newline at end of file + self.assertEqual(sa.get_default_controller().team_id, 1234) From 9b08839362dbe0d80278fa593cb983c5c4260dac Mon Sep 17 00:00:00 2001 From: Vaghinak Basentsyan Date: Mon, 14 Feb 2022 14:38:29 +0400 Subject: [PATCH 2/4] Fix init flow --- src/superannotate/lib/infrastructure/controller.py | 4 ++-- tests/unit/test_controller_init.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/superannotate/lib/infrastructure/controller.py b/src/superannotate/lib/infrastructure/controller.py index 0f14d9aa7..be72631f3 100644 --- a/src/superannotate/lib/infrastructure/controller.py +++ b/src/superannotate/lib/infrastructure/controller.py @@ -38,7 +38,7 @@ class BaseController(metaclass=ABCMeta): - def __init__(self, config_path: str, token: str = None): + def __init__(self, config_path: str = None, token: str = None): self._team_data = None self._token = None self._backend_url = None @@ -60,7 +60,7 @@ def __init__(self, config_path: str, token: str = None): self._backend_url = os.environ.get("SA_URL", constances.BACKEND_URL) if token: - self._token = self._validate_token(os.environ.get("SA_TOKEN")) + self._token = self._validate_token(token) elif config_path: config_path = expanduser(config_path) self.retrieve_configs(Path(config_path), raise_exception=True) diff --git a/tests/unit/test_controller_init.py b/tests/unit/test_controller_init.py index fdfb16c3e..356950770 100644 --- a/tests/unit/test_controller_init.py +++ b/tests/unit/test_controller_init.py @@ -22,8 +22,8 @@ class CLITest(TestCase): CONFIG_FILE_DATA = '{"main_endpoint": "https://amazonaws.com:3000","token": "c9c55ct=6085","ssl_verify": false}' - # @pytest.mark.skip(reason="Need to adjust") + @pytest.mark.skip(reason="Need to adjust") @patch('builtins.input') def test_init_update(self, input_mock): input_mock.side_effect = ["y", "token"] From 7ea128206159ea5befd1dd94e5031a8e1a695f32 Mon Sep 17 00:00:00 2001 From: Vaghinak Basentsyan Date: Mon, 14 Feb 2022 14:44:58 +0400 Subject: [PATCH 3/4] Fix mixpanel --- src/superannotate/__init__.py | 3 +- src/superannotate/lib/__init__.py | 18 +- .../lib/app/interface/cli_interface.py | 5 +- .../lib/app/interface/sdk_interface.py | 198 +++++++++--------- src/superannotate/lib/app/mixp/decorators.py | 8 +- .../lib/app/mixp/utils/parsers.py | 23 +- .../lib/infrastructure/controller.py | 15 ++ tests/unit/test_controller_init.py | 1 - 8 files changed, 135 insertions(+), 136 deletions(-) diff --git a/src/superannotate/__init__.py b/src/superannotate/__init__.py index 42057385a..45e317788 100644 --- a/src/superannotate/__init__.py +++ b/src/superannotate/__init__.py @@ -4,7 +4,7 @@ import requests import superannotate.lib.core as constances -from lib import get_default_controller +from superannotate.lib import get_default_controller from packaging.version import parse from superannotate.lib.app.analytics.class_analytics import class_distribution from superannotate.lib.app.exceptions import AppException @@ -107,6 +107,7 @@ ) from superannotate.lib.app.interface.sdk_interface import validate_annotations from superannotate.logger import get_default_logger +from superannotate.lib.infrastructure.controller import Controller from superannotate.version import __version__ diff --git a/src/superannotate/lib/__init__.py b/src/superannotate/lib/__init__.py index c4db8ec42..281eecbd3 100644 --- a/src/superannotate/lib/__init__.py +++ b/src/superannotate/lib/__init__.py @@ -6,21 +6,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -DEFAULT_CONTROLLER = None - - -def get_default_controller(raise_exception=False): +def get_default_controller(): from lib.infrastructure.controller import Controller - try: - global DEFAULT_CONTROLLER - if not DEFAULT_CONTROLLER: - DEFAULT_CONTROLLER = Controller() - return DEFAULT_CONTROLLER - except Exception: - if raise_exception: - raise - + return Controller.get_default() -def set_default_controller(controller_obj): - # global DEFAULT_CONTROLLER - DEFAULT_CONTROLLER = controller_obj diff --git a/src/superannotate/lib/app/interface/cli_interface.py b/src/superannotate/lib/app/interface/cli_interface.py index fa0526924..b6226d845 100644 --- a/src/superannotate/lib/app/interface/cli_interface.py +++ b/src/superannotate/lib/app/interface/cli_interface.py @@ -12,7 +12,6 @@ from lib.app.interface.sdk_interface import attach_document_urls_to_project from lib.app.interface.sdk_interface import attach_image_urls_to_project from lib.app.interface.sdk_interface import attach_video_urls_to_project -from lib.app.interface.sdk_interface import controller from lib.app.interface.sdk_interface import create_folder from lib.app.interface.sdk_interface import create_project from lib.app.interface.sdk_interface import upload_annotations_from_folder_to_project @@ -21,6 +20,10 @@ from lib.app.interface.sdk_interface import upload_videos_from_folder_to_project from lib.core.entities import ConfigEntity from lib.infrastructure.repositories import ConfigRepository +from lib.infrastructure.controller import Controller + + +controller = Controller.get_default() class CLIFacade(BaseInterfaceFacade): diff --git a/src/superannotate/lib/app/interface/sdk_interface.py b/src/superannotate/lib/app/interface/sdk_interface.py index 697a960ef..8004d6384 100644 --- a/src/superannotate/lib/app/interface/sdk_interface.py +++ b/src/superannotate/lib/app/interface/sdk_interface.py @@ -11,7 +11,6 @@ from typing import Union import boto3 -import lib import lib.core as constances from lib.app.annotation_helpers import add_annotation_bbox_to_json from lib.app.annotation_helpers import add_annotation_comment_to_json @@ -50,7 +49,6 @@ logger = get_default_logger() -controller = lib.DEFAULT_CONTROLLER @validate_arguments @@ -66,12 +64,12 @@ def init(path_to_config_json: Optional[str] = None, token: str = None): :param token: Team token :type token: str """ - lib.DEFAULT_CONTROLLER = Controller(config_path=path_to_config_json, token=token) + Controller.get_default().set_default(Controller(config_path=path_to_config_json, token=token)) @validate_arguments def set_auth_token(token: str): - controller.set_token(token) + Controller.get_default().set_token(token) @Trackable @@ -82,7 +80,7 @@ def get_team_metadata(): :return: team metadata :rtype: dict """ - response = controller.get_team() + response = Controller.get_default().get_team() return TeamSerializer(response.data).serialize() @@ -109,7 +107,7 @@ def search_team_contributors( :rtype: list of dicts """ - contributors = controller.search_team_contributors( + contributors = Controller.get_default().search_team_contributors( email=email, first_name=first_name, last_name=last_name ).data if not return_metadata: @@ -140,7 +138,7 @@ def search_projects( :return: project names or metadatas :rtype: list of strs or dicts """ - result = controller.search_project( + result = Controller.get_default().search_project( name=name, include_complete_image_count=include_complete_image_count ).data if return_metadata: @@ -168,7 +166,7 @@ def create_project( :return: dict object metadata the new project :rtype: dict """ - response = controller.create_project( + response = Controller.get_default().create_project( name=project_name, description=project_description, project_type=project_type ) if response.errors: @@ -188,7 +186,7 @@ def create_project_from_metadata(project_metadata: Project): :rtype: dict """ project_metadata = project_metadata.dict() - response = controller.create_project( + response = Controller.get_default().create_project( name=project_metadata["name"], description=project_metadata["description"], project_type=project_metadata["type"], @@ -234,7 +232,7 @@ def clone_project( :return: dict object metadata of the new project :rtype: dict """ - response = controller.clone_project( + response = Controller.get_default().clone_project( name=project_name, from_name=from_project, project_description=project_description, @@ -274,9 +272,9 @@ def search_images( """ project_name, folder_name = extract_project_folder(project) - project = controller._get_project(project_name) + project = Controller.get_default()._get_project(project_name) - response = controller.search_images( + response = Controller.get_default().search_images( project_name=project_name, folder_path=folder_name, annotation_status=annotation_status, @@ -307,7 +305,7 @@ def create_folder(project: NotEmptyStr, folder_name: NotEmptyStr): :rtype: dict """ - res = controller.create_folder(project=project, folder_name=folder_name) + res = Controller.get_default().create_folder(project=project, folder_name=folder_name) if res.data: folder = res.data logger.info(f"Folder {folder.name} created in project {project}") @@ -327,7 +325,7 @@ def delete_project(project: Union[NotEmptyStr, dict]): name = project if isinstance(project, dict): name = project["name"] - controller.delete_project(name=name) + Controller.get_default().delete_project(name=name) @Trackable @@ -341,7 +339,7 @@ def rename_project(project: NotEmptyStr, new_name: NotEmptyStr): :type new_name: str """ - response = controller.update_project(name=project, project_data={"name": new_name}) + response = Controller.get_default().update_project(name=project, project_data={"name": new_name}) if response.errors: raise AppException(response.errors) @@ -363,7 +361,7 @@ def get_folder_metadata(project: NotEmptyStr, folder_name: NotEmptyStr): :return: metadata of folder :rtype: dict """ - result = controller.get_folder(project_name=project, folder_name=folder_name).data + result = Controller.get_default().get_folder(project_name=project, folder_name=folder_name).data if not result: raise AppException("Folder not found.") return result.to_dict() @@ -380,7 +378,7 @@ def delete_folders(project: NotEmptyStr, folder_names: List[NotEmptyStr]): :type folder_names: list of strs """ - res = controller.delete_folders(project_name=project, folder_names=folder_names) + res = Controller.get_default().delete_folders(project_name=project, folder_names=folder_names) if res.errors: raise AppException(res.errors) logger.info(f"Folders {folder_names} deleted in project {project}") @@ -400,7 +398,7 @@ def get_project_and_folder_metadata(project: Union[NotEmptyStr, dict]): """ project_name, folder_name = extract_project_folder(project) project = ProjectSerializer( - controller.search_project(project_name).data[0] + Controller.get_default().search_project(project_name).data[0] ).serialize() folder = None if folder_name: @@ -428,7 +426,7 @@ def search_folders( :rtype: list of strs or dicts """ - response = controller.search_folders( + response = Controller.get_default().search_folders( project_name=project, folder_name=folder_name, include_users=return_metadata ) if response.errors: @@ -472,8 +470,8 @@ def copy_image( destination_project, destination_folder = extract_project_folder( destination_project ) - source_project_metadata = controller.get_project_metadata(source_project_name).data - destination_project_metadata = controller.get_project_metadata( + source_project_metadata = Controller.get_default().get_project_metadata(source_project_name).data + destination_project_metadata = Controller.get_default().get_project_metadata( destination_project ).data @@ -488,7 +486,7 @@ def copy_image( LIMITED_FUNCTIONS[source_project_metadata["project"].project_type] ) - response = controller.copy_image( + response = Controller.get_default().copy_image( from_project_name=source_project_name, from_folder_name=source_folder_name, to_project_name=destination_project, @@ -500,7 +498,7 @@ def copy_image( raise AppException(response.errors) if include_annotations: - controller.copy_image_annotation_classes( + Controller.get_default().copy_image_annotation_classes( from_project_name=source_project_name, from_folder_name=source_folder_name, to_folder_name=destination_folder, @@ -508,7 +506,7 @@ def copy_image( image_name=image_name, ) if copy_pin: - controller.update_image( + Controller.get_default().update_image( project_name=destination_project, folder_name=destination_folder, image_name=image_name, @@ -552,7 +550,7 @@ def upload_images_from_public_urls_to_project( project_name, folder_name = extract_project_folder(project) - use_case = controller.upload_images_from_public_urls_to_project( + use_case = Controller.get_default().upload_images_from_public_urls_to_project( project_name=project_name, folder_name=folder_name, image_urls=img_urls, @@ -603,12 +601,12 @@ def copy_images( "Source and destination projects should be the same for copy_images" ) if not image_names: - images = controller.search_images( + images = Controller.get_default().search_images( project_name=project_name, folder_path=source_folder_name ).data image_names = [image.name for image in images] - res = controller.bulk_copy_images( + res = Controller.get_default().bulk_copy_images( project_name=project_name, from_folder_name=source_folder_name, to_folder_name=destination_folder_name, @@ -656,7 +654,7 @@ def move_images( """ project_name, source_folder_name = extract_project_folder(source_project) - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data if project["project"].project_type in [ constances.ProjectType.VIDEO.value, constances.ProjectType.DOCUMENT.value, @@ -673,13 +671,13 @@ def move_images( ) if not image_names: - images = controller.search_images( + images = Controller.get_default().search_images( project_name=project_name, folder_path=source_folder_name ) images = images.data image_names = [image.name for image in images] - response = controller.bulk_move_images( + response = Controller.get_default().bulk_move_images( project_name=project_name, from_folder_name=source_folder_name, to_folder_name=destination_folder_name, @@ -739,7 +737,7 @@ def get_project_metadata( :rtype: dict """ project_name, folder_name = extract_project_folder(project) - response = controller.get_project_metadata( + response = Controller.get_default().get_project_metadata( project_name, include_annotation_classes, include_settings, @@ -778,7 +776,7 @@ def get_project_settings(project: Union[NotEmptyStr, dict]): :rtype: list of dicts """ project_name, folder_name = extract_project_folder(project) - settings = controller.get_project_settings(project_name=project_name) + settings = Controller.get_default().get_project_settings(project_name=project_name) settings = [ SettingsSerializer(attribute).serialize() for attribute in settings.data ] @@ -799,7 +797,7 @@ def get_project_workflow(project: Union[str, dict]): :rtype: list of dicts """ project_name, folder_name = extract_project_folder(project) - workflow = controller.get_project_workflow(project_name=project_name) + workflow = Controller.get_default().get_project_workflow(project_name=project_name) if workflow.errors: raise AppException(workflow.errors) return workflow.data @@ -822,7 +820,7 @@ def search_annotation_classes( :rtype: list of dicts """ project_name, folder_name = extract_project_folder(project) - classes = controller.search_annotation_classes(project_name, name_prefix) + classes = Controller.get_default().search_annotation_classes(project_name, name_prefix) classes = [BaseSerializers(attribute).serialize() for attribute in classes.data] return classes @@ -842,7 +840,7 @@ def set_project_default_image_quality_in_editor( project_name, folder_name = extract_project_folder(project) image_quality_in_editor = ImageQuality.get_value(image_quality_in_editor) - response = controller.set_project_settings( + response = Controller.get_default().set_project_settings( project_name=project_name, new_settings=[{"attribute": "ImageQuality", "value": image_quality_in_editor}], ) @@ -866,7 +864,7 @@ def pin_image( :type pin: bool """ project_name, folder_name = extract_project_folder(project) - controller.update_image( + Controller.get_default().update_image( project_name=project_name, image_name=image_name, folder_name=folder_name, @@ -890,8 +888,8 @@ def get_image_metadata( :rtype: dict """ project_name, folder_name = extract_project_folder(project) - project = controller._get_project(project_name) - response = controller.get_image_metadata(project_name, folder_name, image_name) + project = Controller.get_default()._get_project(project_name) + response = Controller.get_default().get_image_metadata(project_name, folder_name, image_name) if response.errors: raise AppException(response.errors) @@ -916,7 +914,7 @@ def set_images_annotation_statuses( :type annotation_status: str """ project_name, folder_name = extract_project_folder(project) - response = controller.set_images_annotation_statuses( + response = Controller.get_default().set_images_annotation_statuses( project_name, folder_name, image_names, annotation_status ) if response.errors: @@ -941,7 +939,7 @@ def delete_images( if not isinstance(image_names, list) and image_names is not None: raise AppException("Image_names should be a list of str or None.") - response = controller.delete_images( + response = Controller.get_default().delete_images( project_name=project_name, folder_name=folder_name, image_names=image_names ) if response.errors: @@ -967,7 +965,7 @@ def assign_images(project: Union[NotEmptyStr, dict], image_names: List[str], use :type user: str """ project_name, folder_name = extract_project_folder(project) - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data if project["project"].project_type in [ constances.ProjectType.VIDEO.value, @@ -978,7 +976,7 @@ def assign_images(project: Union[NotEmptyStr, dict], image_names: List[str], use if not folder_name: folder_name = "root" contributors = ( - controller.get_project_metadata( + Controller.get_default().get_project_metadata( project_name=project_name, include_contributors=True ) .data["project"] @@ -995,7 +993,7 @@ def assign_images(project: Union[NotEmptyStr, dict], image_names: List[str], use ) return - response = controller.assign_images(project_name, folder_name, image_names, user) + response = Controller.get_default().assign_images(project_name, folder_name, image_names, user) if not response.errors: logger.info(f"Assign images to user {user}") else: @@ -1016,7 +1014,7 @@ def unassign_images(project: Union[NotEmptyStr, dict], image_names: List[NotEmpt """ project_name, folder_name = extract_project_folder(project) - response = controller.un_assign_images( + response = Controller.get_default().un_assign_images( project_name=project_name, folder_name=folder_name, image_names=image_names ) if response.errors: @@ -1035,7 +1033,7 @@ def unassign_folder(project_name: NotEmptyStr, folder_name: NotEmptyStr): :param folder_name: folder name to remove assignees :type folder_name: str """ - response = controller.un_assign_folder( + response = Controller.get_default().un_assign_folder( project_name=project_name, folder_name=folder_name ) if response.errors: @@ -1059,7 +1057,7 @@ def assign_folder( """ contributors = ( - controller.get_project_metadata( + Controller.get_default().get_project_metadata( project_name=project_name, include_contributors=True ) .data["project"] @@ -1077,7 +1075,7 @@ def assign_folder( if not verified_users: return - response = controller.assign_folder( + response = Controller.get_default().assign_folder( project_name=project_name, folder_name=folder_name, users=list(verified_users) ) @@ -1108,11 +1106,11 @@ def share_project( if isinstance(user, dict): user_id = user["id"] else: - response = controller.search_team_contributors(email=user) + response = Controller.get_default().search_team_contributors(email=user) if not response.data: raise AppException(f"User {user} not found.") user_id = response.data[0]["id"] - response = controller.share_project( + response = Controller.get_default().share_project( project_name=project_name, user_id=user_id, user_role=user_role ) if response.errors: @@ -1137,7 +1135,7 @@ def get_image_annotations(project: Union[NotEmptyStr, dict], image_name: NotEmpt :rtype: dict """ project_name, folder_name = extract_project_folder(project) - res = controller.get_image_annotations( + res = Controller.get_default().get_image_annotations( project_name=project_name, folder_name=folder_name, image_name=image_name ) if res.errors: @@ -1227,7 +1225,7 @@ def upload_images_from_folder_to_project( exclude_file_patterns, ) - use_case = controller.upload_images_from_folder_to_project( + use_case = Controller.get_default().upload_images_from_folder_to_project( project_name=project_name, folder_name=folder_name, folder_path=folder_path, @@ -1274,7 +1272,7 @@ def get_project_image_count( project_name, folder_name = extract_project_folder(project) - response = controller.get_project_image_count( + response = Controller.get_default().get_project_image_count( project_name=project_name, folder_name=folder_name, with_all_subfolders=with_all_subfolders, @@ -1305,7 +1303,7 @@ def download_image_annotations( :rtype: tuple """ project_name, folder_name = extract_project_folder(project) - res = controller.download_image_annotations( + res = Controller.get_default().download_image_annotations( project_name=project_name, folder_name=folder_name, image_name=image_name, @@ -1329,7 +1327,7 @@ def get_exports(project: NotEmptyStr, return_metadata: Optional[StrictBool] = Fa :return: names or metadata objects of the all prepared exports of the project :rtype: list of strs or dicts """ - response = controller.get_exports( + response = Controller.get_default().get_exports( project_name=project, return_metadata=return_metadata ) return response.data @@ -1377,7 +1375,7 @@ def prepare_export( constances.AnnotationStatus.COMPLETED.name, constances.AnnotationStatus.SKIPPED.name, ] - response = controller.prepare_export( + response = Controller.get_default().prepare_export( project_name=project_name, folder_names=folders, include_fuse=include_fuse, @@ -1454,7 +1452,7 @@ def upload_videos_from_folder_to_project( video_paths += list(Path(folder_path).rglob(f"*.{extension.upper()}")) video_paths = [str(path) for path in video_paths] - response = controller.upload_videos( + response = Controller.get_default().upload_videos( project_name=project_name, folder_name=folder_name, paths=video_paths, @@ -1508,7 +1506,7 @@ def upload_video_to_project( project_name, folder_name = extract_project_folder(project) - response = controller.upload_videos( + response = Controller.get_default().upload_videos( project_name=project_name, folder_name=folder_name, paths=[video_path], @@ -1555,7 +1553,7 @@ def create_annotation_class( attribute_groups = ( list(map(lambda x: x.dict(), attribute_groups)) if attribute_groups else [] ) - response = controller.create_annotation_class( + response = Controller.get_default().create_annotation_class( project_name=project, name=name, color=color, @@ -1577,7 +1575,7 @@ def delete_annotation_class( :param annotation_class: annotation class name or metadata :type annotation_class: str or dict """ - controller.delete_annotation_class( + Controller.get_default().delete_annotation_class( project_name=project, annotation_class_name=annotation_class ) @@ -1595,7 +1593,7 @@ def download_annotation_classes_json(project: NotEmptyStr, folder: Union[str, Pa :return: path of the download file :rtype: str """ - response = controller.download_annotation_classes( + response = Controller.get_default().download_annotation_classes( project_name=project, download_path=folder ) if response.errors: @@ -1642,7 +1640,7 @@ def create_annotation_classes_from_classes_json( project, classes_json_initial, ) - response = controller.create_annotation_classes( + response = Controller.get_default().create_annotation_classes( project_name=project, annotation_classes=annotation_classes, ) if response.errors: @@ -1680,7 +1678,7 @@ def download_export( project_name, folder_name = extract_project_folder(project) export_name = export["name"] if isinstance(export, dict) else export - use_case = controller.download_export( + use_case = Controller.get_default().download_export( project_name=project_name, export_name=export_name, folder_path=folder_path, @@ -1724,13 +1722,13 @@ def set_image_annotation_status( :rtype: dict """ project_name, folder_name = extract_project_folder(project) - project_entity = controller._get_project(project_name) - response = controller.set_images_annotation_statuses( + project_entity = Controller.get_default()._get_project(project_name) + response = Controller.get_default().set_images_annotation_statuses( project_name, folder_name, [image_name], annotation_status ) if response.errors: raise AppException(response.errors) - image = controller.get_image_metadata(project_name, folder_name, image_name).data + image = Controller.get_default().get_image_metadata(project_name, folder_name, image_name).data return ImageSerializer(image).serialize_by_project(project=project_entity) @@ -1750,7 +1748,7 @@ def set_project_workflow(project: Union[NotEmptyStr, dict], new_workflow: List[d :type new_workflow: list of dicts """ project_name, _ = extract_project_folder(project) - response = controller.set_project_workflow( + response = Controller.get_default().set_project_workflow( project_name=project_name, steps=new_workflow ) if response.errors: @@ -1790,7 +1788,7 @@ def download_image( :rtype: tuple """ project_name, folder_name = extract_project_folder(project) - response = controller.download_image( + response = Controller.get_default().download_image( project_name=project_name, folder_name=folder_name, image_name=image_name, @@ -1826,7 +1824,7 @@ def attach_image_urls_to_project( :rtype: tuple """ project_name, folder_name = extract_project_folder(project) - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data project_folder_name = project_name + (f"/{folder_name}" if folder_name else "") if project["project"].project_type in [ @@ -1839,7 +1837,7 @@ def attach_image_urls_to_project( ) ) images_to_upload, duplicate_images = get_paths_and_duplicated_from_csv(attachments) - use_case = controller.interactive_attach_urls( + use_case = Controller.get_default().interactive_attach_urls( project_name=project_name, folder_name=folder_name, files=ImageSerializer.deserialize(images_to_upload), # noqa: E203 @@ -1893,7 +1891,7 @@ def attach_video_urls_to_project( :rtype: (list, list, list) """ project_name, folder_name = extract_project_folder(project) - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data project_folder_name = project_name + (f"/{folder_name}" if folder_name else "") if project["project"].project_type != constances.ProjectType.VIDEO.value: @@ -1904,7 +1902,7 @@ def attach_video_urls_to_project( ) images_to_upload, duplicate_images = get_paths_and_duplicated_from_csv(attachments) - use_case = controller.interactive_attach_urls( + use_case = Controller.get_default().interactive_attach_urls( project_name=project_name, folder_name=folder_name, files=ImageSerializer.deserialize(images_to_upload), # noqa: E203 @@ -1990,7 +1988,7 @@ def upload_annotations_from_folder_to_project( logger.info( f"Uploading {len(annotation_paths)} annotations from {folder_path} to the project {project_folder_name}." ) - response = controller.upload_annotations_from_folder( + response = Controller.get_default().upload_annotations_from_folder( project_name=project_name, folder_name=folder_name, annotation_paths=annotation_paths, # noqa: E203 @@ -2035,7 +2033,7 @@ def upload_preannotations_from_folder_to_project( """ project_name, folder_name = extract_project_folder(project) project_folder_name = project_name + (f"/{folder_name}" if folder_name else "") - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data if project["project"].project_type in [ constances.ProjectType.VIDEO.value, constances.ProjectType.DOCUMENT.value, @@ -2056,7 +2054,7 @@ def upload_preannotations_from_folder_to_project( logger.info( f"Uploading {len(annotation_paths)} annotations from {folder_path} to the project {project_folder_name}." ) - response = controller.upload_annotations_from_folder( + response = Controller.get_default().upload_annotations_from_folder( project_name=project_name, folder_name=folder_name, annotation_paths=annotation_paths, # noqa: E203 @@ -2093,7 +2091,7 @@ def upload_image_annotations( project_name, folder_name = extract_project_folder(project) - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data if project["project"].project_type in [ constances.ProjectType.VIDEO.value, constances.ProjectType.DOCUMENT.value, @@ -2115,7 +2113,7 @@ def upload_image_annotations( if verbose: logger.info("Uploading annotations from %s.", annotation_json) annotation_json = json.load(open(annotation_json)) - response = controller.upload_image_annotations( + response = Controller.get_default().upload_image_annotations( project_name=project_name, folder_name=folder_name, image_name=image_name, @@ -2140,7 +2138,7 @@ def download_model(model: MLModel, output_dir: Union[str, Path]): :return: the metadata of the model :rtype: dict """ - res = controller.download_ml_model( + res = Controller.get_default().download_ml_model( model_data=model.dict(), download_path=output_dir ) if res.errors: @@ -2184,7 +2182,7 @@ def benchmark( if isinstance(project, dict): project_name = project["name"] - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data if project["project"].project_type in [ constances.ProjectType.VIDEO.value, constances.ProjectType.DOCUMENT.value, @@ -2193,7 +2191,7 @@ def benchmark( if not export_root: with tempfile.TemporaryDirectory() as temp_dir: - response = controller.benchmark( + response = Controller.get_default().benchmark( project_name=project_name, ground_truth_folder_name=gt_folder, folder_names=folder_names, @@ -2204,7 +2202,7 @@ def benchmark( ) else: - response = controller.benchmark( + response = Controller.get_default().benchmark( project_name=project_name, ground_truth_folder_name=gt_folder, folder_names=folder_names, @@ -2250,7 +2248,7 @@ def consensus( if export_root is None: with tempfile.TemporaryDirectory() as temp_dir: export_root = temp_dir - response = controller.consensus( + response = Controller.get_default().consensus( project_name=project, folder_names=folder_names, export_path=export_root, @@ -2260,7 +2258,7 @@ def consensus( ) else: - response = controller.consensus( + response = Controller.get_default().consensus( project_name=project, folder_names=folder_names, export_path=export_root, @@ -2302,7 +2300,7 @@ def run_prediction( if isinstance(model, dict): model_name = model["name"] - response = controller.run_prediction( + response = Controller.get_default().run_prediction( project_name=project_name, images_list=images_list, model_name=model_name, @@ -2342,7 +2340,7 @@ def add_annotation_bbox_to_image( :type error: bool """ project_name, folder_name = extract_project_folder(project) - response = controller.get_image_annotations( + response = Controller.get_default().get_image_annotations( project_name=project_name, folder_name=folder_name, image_name=image_name ) if response.errors: @@ -2357,7 +2355,7 @@ def add_annotation_bbox_to_image( image_name, ) - controller.upload_image_annotations( + Controller.get_default().upload_image_annotations( *extract_project_folder(project), image_name, annotations ) @@ -2390,7 +2388,7 @@ def add_annotation_point_to_image( :type error: bool """ project_name, folder_name = extract_project_folder(project) - response = controller.get_image_annotations( + response = Controller.get_default().get_image_annotations( project_name=project_name, folder_name=folder_name, image_name=image_name ) if response.errors: @@ -2404,7 +2402,7 @@ def add_annotation_point_to_image( annotation_class_attributes, error, ) - controller.upload_image_annotations( + Controller.get_default().upload_image_annotations( *extract_project_folder(project), image_name, annotations ) @@ -2435,7 +2433,7 @@ def add_annotation_comment_to_image( :type resolved: bool """ project_name, folder_name = extract_project_folder(project) - response = controller.get_image_annotations( + response = Controller.get_default().get_image_annotations( project_name=project_name, folder_name=folder_name, image_name=image_name ) if response.errors: @@ -2449,7 +2447,7 @@ def add_annotation_comment_to_image( resolved=resolved, image_name=image_name, ) - controller.upload_image_annotations( + Controller.get_default().upload_image_annotations( *extract_project_folder(project), image_name, annotations ) @@ -2480,8 +2478,8 @@ def search_images_all_folders( :rtype: list of dicts or strs """ - project_entity = controller._get_project(project) - res = controller.list_images( + project_entity = Controller.get_default()._get_project(project) + res = Controller.get_default().list_images( project_name=project, name_prefix=image_name_prefix, annotation_status=annotation_status, @@ -2524,7 +2522,7 @@ def upload_image_to_project( """ project_name, folder_name = extract_project_folder(project) - response = controller.upload_image_to_project( + response = Controller.get_default().upload_image_to_project( project_name=project_name, folder_name=folder_name, image_name=image_name, @@ -2560,7 +2558,7 @@ def search_models( :return: ml model metadata :rtype: list of dicts """ - res = controller.search_models( + res = Controller.get_default().search_models( name=name, model_type=type_, project_id=project_id, @@ -2603,7 +2601,7 @@ def upload_images_to_project( """ project_name, folder_name = extract_project_folder(project) - use_case = controller.upload_images_to_project( + use_case = Controller.get_default().upload_images_to_project( project_name=project_name, folder_name=folder_name, paths=img_paths, @@ -2697,7 +2695,7 @@ def delete_annotations( project_name, folder_name = extract_project_folder(project) - response = controller.delete_annotations( + response = Controller.get_default().delete_annotations( project_name=project_name, folder_name=folder_name, image_names=image_names ) if response.errors: @@ -2724,7 +2722,7 @@ def attach_document_urls_to_project( :rtype: tuple """ project_name, folder_name = extract_project_folder(project) - project = controller.get_project_metadata(project_name).data + project = Controller.get_default().get_project_metadata(project_name).data project_folder_name = project_name + (f"/{folder_name}" if folder_name else "") if project["project"].project_type != constances.ProjectType.DOCUMENT.value: @@ -2736,7 +2734,7 @@ def attach_document_urls_to_project( images_to_upload, duplicate_images = get_paths_and_duplicated_from_csv(attachments) - use_case = controller.interactive_attach_urls( + use_case = Controller.get_default().interactive_attach_urls( project_name=project_name, folder_name=folder_name, files=ImageSerializer.deserialize(images_to_upload), # noqa: E203 @@ -2787,7 +2785,7 @@ def validate_annotations( """ with open(annotations_json) as file: annotation_data = json.loads(file.read()) - response = controller.validate_annotations( + response = Controller.get_default().validate_annotations( project_type, annotation_data, allow_extra=False ) if response.errors: @@ -2818,7 +2816,7 @@ def add_contributors_to_project( :return: lists of added, skipped contributors of the project :rtype: tuple (2 members) of lists of strs """ - response = controller.add_contributors_to_project( + response = Controller.get_default().add_contributors_to_project( project_name=project, emails=emails, role=role ) if response.errors: @@ -2842,7 +2840,7 @@ def invite_contributors_to_team( :return: lists of invited, skipped contributors of the team :rtype: tuple (2 members) of lists of strs """ - response = controller.invite_contributors_to_team(emails=emails, set_admin=admin) + response = Controller.get_default().invite_contributors_to_team(emails=emails, set_admin=admin) if response.errors: raise AppException(response.errors) return response.data diff --git a/src/superannotate/lib/app/mixp/decorators.py b/src/superannotate/lib/app/mixp/decorators.py index 335992bef..8e1a0040e 100644 --- a/src/superannotate/lib/app/mixp/decorators.py +++ b/src/superannotate/lib/app/mixp/decorators.py @@ -8,12 +8,10 @@ from .utils import parsers -controller = get_default_controller() - # TODO: try: - if "api.annotate.online" in controller._backend_client.api_url: + if "api.annotate.online" in get_default_controller()._backend_client.api_url: TOKEN = "ca95ed96f80e8ec3be791e2d3097cf51" else: TOKEN = "e741d4863e7e05b1a45833d01865ef0d" @@ -51,7 +49,7 @@ def __init__(self, function, initial=False): @property def team(self): - return controller.get_team() + return get_default_controller().get_team() def track(self, *args, **kwargs): try: @@ -82,7 +80,7 @@ def track(self, *args, **kwargs): def __call__(self, *args, **kwargs): try: - self.__class__.TEAM_DATA = controller.get_team() + self.__class__.TEAM_DATA = get_default_controller().get_team() result = self.function(*args, **kwargs) self._success = True except Exception as e: diff --git a/src/superannotate/lib/app/mixp/utils/parsers.py b/src/superannotate/lib/app/mixp/utils/parsers.py index 656e54cc4..fe1c2e9f4 100644 --- a/src/superannotate/lib/app/mixp/utils/parsers.py +++ b/src/superannotate/lib/app/mixp/utils/parsers.py @@ -2,8 +2,7 @@ from lib import get_default_controller from lib.app.helpers import extract_project_folder from lib.core.enums import ProjectType - -controller = get_default_controller() +from lib.infrastructure.controller import Controller def get_project_name(project): @@ -98,7 +97,7 @@ def clone_project(*args, **kwargs): if not project: project = args[0] - result = controller.get_project_metadata(project) + result = Controller.get_default().get_project_metadata(project) project_metadata = result.data["project"] project_type = ProjectType.get_name(project_metadata.project_type) @@ -522,7 +521,7 @@ def run_prediction(*args, **kwargs): if not project: project = args[0] project_name = get_project_name(project) - res = controller.get_project_metadata(project_name) + res = Controller.get_default().get_project_metadata(project_name) project_metadata = res.data["project"] project_type = ProjectType.get_name(project_metadata.project_type) image_list = kwargs.get("images_list", None) @@ -611,7 +610,7 @@ def move_images(*args, **kwargs): if image_names == False: image_names = args[1] if image_names is None: - res = controller.search_images(project) + res = Controller.get_default().search_images(project) image_names = res.data return { @@ -636,7 +635,7 @@ def copy_images(*args, **kwargs): if image_names == False: image_names = args[1] if image_names is None: - res = controller.search_images(project) + res = Controller.get_default().search_images(project) image_names = res.data return { "event_name": "copy_images", @@ -664,7 +663,7 @@ def consensus(*args, **kwargs): image_list = args[4:5] if image_list: if image_list[0] is None: - res = controller.search_images(project) + res = Controller.get_default().search_images(project) image_list = res.data else: image_list = image_list[0] @@ -706,7 +705,7 @@ def benchmark(*args, **kwargs): image_list = args[4:5] if image_list: if image_list[0] is None: - res = controller.search_images(project) + res = Controller.get_default().search_images(project) image_list = res.data else: image_list = image_list[0] @@ -741,7 +740,7 @@ def upload_annotations_from_folder_to_project(*args, **kwargs): if not project: project = args[0] project_name = get_project_name(project) - res = controller.get_project_metadata(project_name) + res = Controller.get_default().get_project_metadata(project_name) project_metadata = res.data["project"] project_type = ProjectType.get_name(project_metadata.project_type) @@ -766,7 +765,7 @@ def upload_preannotations_from_folder_to_project(*args, **kwargs): if not project: project = args[0] project_name = get_project_name(project) - res = controller.get_project_metadata(project_name) + res = Controller.get_default().get_project_metadata(project_name) project_metadata = res.data["project"] project_type = ProjectType.get_name(project_metadata.project_type) folder_path = kwargs.get("folder_path", None) @@ -892,7 +891,7 @@ def assign_images(*args, **kwargs): if not user: user = args[2] - contributors = controller.get_project_metadata( + contributors = Controller.get_default().get_project_metadata( project_name=project, include_contributors=True ).data["contributors"] contributor = None @@ -1110,7 +1109,7 @@ def delete_images(*args, **kwargs): if not image_names: image_names = args[1] if image_names is None: - res = controller.search_images(project) + res = Controller.get_default().search_images(project) image_names = res.data return { "event_name": "delete_images", diff --git a/src/superannotate/lib/infrastructure/controller.py b/src/superannotate/lib/infrastructure/controller.py index be72631f3..ad1c05991 100644 --- a/src/superannotate/lib/infrastructure/controller.py +++ b/src/superannotate/lib/infrastructure/controller.py @@ -223,11 +223,26 @@ def annotation_validators(self) -> AnnotationValidators: class Controller(BaseController): + DEFAULT = None def __init__(self, config_path: str = None, token: str = None): super().__init__(config_path, token) self._team = None + @classmethod + def get_default(cls): + if not cls.DEFAULT: + try: + cls.DEFAULT = Controller() + except Exception: + pass + return cls.DEFAULT + + @classmethod + def set_default(cls, obj): + cls.DEFAULT = obj + return cls.DEFAULT + def _get_project(self, name: str): use_case = usecases.GetProjectByNameUseCase( name=name, diff --git a/tests/unit/test_controller_init.py b/tests/unit/test_controller_init.py index 356950770..c87fc08a0 100644 --- a/tests/unit/test_controller_init.py +++ b/tests/unit/test_controller_init.py @@ -10,7 +10,6 @@ from src.superannotate.lib.app.interface.cli_interface import CLIFacade -from src.superannotate.lib.core import CONFIG_FILE_LOCATION from tests.utils.helpers import catch_prints From 636637283edeb1ef6c7cce3aa7268685c431236f Mon Sep 17 00:00:00 2001 From: Vaghinak Basentsyan Date: Mon, 14 Feb 2022 16:02:18 +0400 Subject: [PATCH 4/4] tod --- src/superannotate/lib/app/interface/sdk_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/superannotate/lib/app/interface/sdk_interface.py b/src/superannotate/lib/app/interface/sdk_interface.py index 8004d6384..0b9c3bb66 100644 --- a/src/superannotate/lib/app/interface/sdk_interface.py +++ b/src/superannotate/lib/app/interface/sdk_interface.py @@ -64,7 +64,7 @@ def init(path_to_config_json: Optional[str] = None, token: str = None): :param token: Team token :type token: str """ - Controller.get_default().set_default(Controller(config_path=path_to_config_json, token=token)) + Controller.set_default(Controller(config_path=path_to_config_json, token=token)) @validate_arguments