From ab724101c8405517e23d227efbeeb175285d4d6c Mon Sep 17 00:00:00 2001 From: zhiren Date: Thu, 21 Mar 2024 17:01:50 -0400 Subject: [PATCH 01/18] add [p] prefix for project folder when listing items under project --- app/models/folder.py | 22 -------- app/models/item.py | 55 +++++++++++++++++++ app/services/file_manager/file_list.py | 12 +++- .../file_manager/file_upload/file_upload.py | 4 +- app/utils/aggregated.py | 12 ++-- tests/app/commands/test_file.py | 2 +- .../file_upload/test_file_upload.py | 10 ++-- tests/app/utils/test_aggregated.py | 10 ++-- 8 files changed, 84 insertions(+), 43 deletions(-) delete mode 100644 app/models/folder.py create mode 100644 app/models/item.py diff --git a/app/models/folder.py b/app/models/folder.py deleted file mode 100644 index 180c337c..00000000 --- a/app/models/folder.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2023-2024 Indoc Systems -# -# Contact Indoc Systems for any questions regarding the use of this source code. - -from enum import Enum - - -class FolderType(str, Enum): - """Available folder types.""" - - NAMEFOLDER = 'namefolder' - PROJECTFOLDER = 'projectfolder' - - def get_prefix(self) -> str: - """Get the prefix for the folder type.""" - - prefix = { - 'namefolder': '', - 'projectfolder': 'shared/', - } - - return prefix.get(self.value) diff --git a/app/models/item.py b/app/models/item.py new file mode 100644 index 00000000..233bca73 --- /dev/null +++ b/app/models/item.py @@ -0,0 +1,55 @@ +# Copyright (C) 2023-2024 Indoc Systems +# +# Contact Indoc Systems for any questions regarding the use of this source code. + +from enum import Enum + + +class FolderPrefix(str, Enum): + """In database, name folders and project folders will prefix with different path. and user will need to key in the + keyword to get the correct path. eg. + + - project folder: + - key in: /projectfolder/ + - path: /shared/ + - name folder: + - key in: // + - path: // + """ + + NAMEFOLDER = 'namefolder' + PROJECTFOLDER = 'projectfolder' + + def get_prefix(self) -> str: + """Get the prefix for the folder type.""" + + prefix = { + 'namefolder': '', + 'projectfolder': 'shared/', + } + + return prefix.get(self.value) + + +class ItemType(str, Enum): + """The class to reflect the type of item in database.""" + + FILE = 'file' + Folder = 'folder' + NAMEFOLDER = 'name_folder' + PROJECTFOLDER = 'project_folder' + + @classmethod + def get_item_type(cls, value): + # Define a mapping for alternative values + alternative_mapping = { + 'namefolder': cls.NAMEFOLDER, + } + # Check if the value is in the alternative mapping + if value in alternative_mapping: + return alternative_mapping[value] + # Fall back to normal lookup by value + for item in cls: + if item.value == value: + return item + return None diff --git a/app/services/file_manager/file_list.py b/app/services/file_manager/file_list.py index 39982cd9..45b00cbc 100644 --- a/app/services/file_manager/file_list.py +++ b/app/services/file_manager/file_list.py @@ -9,6 +9,7 @@ import app.services.logger_services.log_functions as logger from app.configs.app_config import AppConfig from app.configs.user_config import UserConfig +from app.models.item import ItemType from app.models.service_meta_class import MetaService from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import SrvErrorHandler @@ -59,10 +60,17 @@ def list_files(self, paths, zone, page, page_size): # then format the console output files, folders = '', '' for f in res: - if 'file' == f.get('type'): + item_type = ItemType(f.get('type')) + + if item_type == ItemType.FILE: files = files + f.get('name') + ' ...' - elif f.get('type') in ['folder', 'name_folder', 'project_folder']: + else: + # add [p] in front of the project folder + if item_type == ItemType.PROJECTFOLDER: + f['name'] = f'[p]{f.get("name")}' + folders = folders + f"\033[34m{f.get('name')}\033[0m ..." + f_string = folders + files return f_string diff --git a/app/services/file_manager/file_upload/file_upload.py b/app/services/file_manager/file_upload/file_upload.py index 4dda080b..9f5e335f 100644 --- a/app/services/file_manager/file_upload/file_upload.py +++ b/app/services/file_manager/file_upload/file_upload.py @@ -18,7 +18,7 @@ import app.services.logger_services.log_functions as logger import app.services.output_manager.message_handler as mhandler from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import FolderPrefix from app.services.file_manager.file_upload.models import FileObject from app.services.file_manager.file_upload.models import ItemStatus from app.services.file_manager.file_upload.models import UploadType @@ -44,7 +44,7 @@ def compress_folder_to_zip(path): def assemble_path( - f: str, target_folder: str, project_code: str, folder_type: FolderType, zone: str + f: str, target_folder: str, project_code: str, folder_type: FolderPrefix, zone: str ) -> Tuple[str, Dict, bool, str]: ''' Summary: diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index 662db673..e18c21eb 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -17,7 +17,7 @@ from app.configs.app_config import AppConfig from app.configs.config import ConfigClass from app.configs.user_config import UserConfig -from app.models.folder import FolderType +from app.models.item import FolderPrefix from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import SrvErrorHandler from app.services.user_authentication.decorator import require_valid_token @@ -166,7 +166,7 @@ def get_file_in_folder(path): return files_list -def identify_target_folder(project_path: str) -> Tuple[str, FolderType, str]: +def identify_target_folder(project_path: str) -> Tuple[str, FolderPrefix, str]: ''' Summary: the function will validate if input folder path doesn't @@ -187,14 +187,14 @@ def identify_target_folder(project_path: str) -> Tuple[str, FolderType, str]: # check folder type if is project folder or name folder # there will be a extra string for project folder between project code and folder name if len(temp_paths) == 2: - folder_type = FolderType.NAMEFOLDER + folder_type = FolderPrefix.NAMEFOLDER folder_name = temp_paths[1] elif len(temp_paths) >= 3: - if temp_paths[1] == FolderType.PROJECTFOLDER.value: - folder_type = FolderType.PROJECTFOLDER + if temp_paths[1] == FolderPrefix.PROJECTFOLDER.value: + folder_type = FolderPrefix.PROJECTFOLDER folder_name = temp_paths[2] else: - folder_type = FolderType.NAMEFOLDER + folder_type = FolderPrefix.NAMEFOLDER folder_name = os.path.join(temp_paths[1], temp_paths[2]) else: SrvErrorHandler.customized_handle(ECustomizedError.INVALID_NAMEFOLDER, True) diff --git a/tests/app/commands/test_file.py b/tests/app/commands/test_file.py index 3abe2cab..2492102c 100644 --- a/tests/app/commands/test_file.py +++ b/tests/app/commands/test_file.py @@ -193,7 +193,7 @@ def test_file_list_with_pagination_with_name_project_folder(requests_mock, mocke questionary.select.return_value.ask.return_value = 'exit' result = cli_runner.invoke(file_list, ['testproject/admin', '-z', 'greenroom']) outputs = result.output.split('\n') - assert outputs[0] == 'folder1 name_folder1 project_folder1 ' + assert outputs[0] == 'folder1 name_folder1 [p]project_folder1 ' def test_empty_file_list_with_pagination(requests_mock, mocker, cli_runner): diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index b4a9ffb2..655f823b 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -3,7 +3,7 @@ # Contact Indoc Systems for any questions regarding the use of this source code. from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import FolderPrefix from app.services.file_manager.file_upload.file_upload import assemble_path from app.services.file_manager.file_upload.file_upload import resume_upload from app.services.file_manager.file_upload.file_upload import simple_upload @@ -34,7 +34,7 @@ def test_assemble_path_at_name_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, FolderPrefix.NAMEFOLDER, zone ) assert current_file_path == 'admin/file.txt' assert parent_folder.get('name') == 'admin' @@ -73,7 +73,7 @@ def test_assemble_path_at_exsting_folder(mocker): mocker.patch('app.services.file_manager.file_upload.file_upload.search_item', side_effect=node_list) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, FolderPrefix.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_exist/file.txt' assert parent_folder.get('name') == 'test_folder_exist' @@ -104,7 +104,7 @@ def test_assemble_path_at_non_existing_folder(mocker): mocker.patch('app.services.file_manager.file_upload.file_upload.click.confirm', return_value=None) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, FolderPrefix.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_not_exist' assert parent_folder.get('name') == 'admin' @@ -132,7 +132,7 @@ def test_assemble_path_at_project_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( - local_file_path, target_folder, project_code, FolderType.PROJECTFOLDER, zone + local_file_path, target_folder, project_code, FolderPrefix.PROJECTFOLDER, zone ) assert current_file_path == 'shared/project_folder/file.txt' assert parent_folder.get('name') == 'project_folder' diff --git a/tests/app/utils/test_aggregated.py b/tests/app/utils/test_aggregated.py index 88194ca2..d6912e00 100644 --- a/tests/app/utils/test_aggregated.py +++ b/tests/app/utils/test_aggregated.py @@ -5,7 +5,7 @@ import pytest from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import FolderPrefix from app.utils.aggregated import check_item_duplication from app.utils.aggregated import identify_target_folder from app.utils.aggregated import search_item @@ -136,10 +136,10 @@ def test_validate_folder_name(folder_name): @pytest.mark.parametrize( 'input_path,expected_result', [ - ('project_code/username', ('project_code', FolderType.NAMEFOLDER, 'username')), - ('project_code/username/folder1', ('project_code', FolderType.NAMEFOLDER, 'username/folder1')), - ('project_code/projectfolder/folder1', ('project_code', FolderType.PROJECTFOLDER, 'folder1')), - ('project_code/projectfolder/folder1/folder2', ('project_code', FolderType.PROJECTFOLDER, 'folder1/folder2')), + ('project_code/username', ('project_code', FolderPrefix.NAMEFOLDER, 'username')), + ('project_code/username/folder1', ('project_code', FolderPrefix.NAMEFOLDER, 'username/folder1')), + ('project_code/projectfolder/folder1', ('project_code', FolderPrefix.PROJECTFOLDER, 'folder1')), + ('project_code/projectfolder/folder1/folder2', ('project_code', FolderPrefix.PROJECTFOLDER, 'folder1/folder2')), ], ) def test_identify_target_folder_success_with_different_path(mocker, input_path, expected_result): From 777843726688a987678d38d4e3f272c87695de68 Mon Sep 17 00:00:00 2001 From: zhiren Date: Fri, 22 Mar 2024 11:52:58 -0400 Subject: [PATCH 02/18] group itemprefix class with itemtype class --- app/models/item.py | 57 +++++++------------ .../file_manager/file_upload/file_upload.py | 8 +-- app/utils/aggregated.py | 11 ++-- .../file_upload/test_file_upload.py | 11 ++-- tests/app/utils/test_aggregated.py | 10 ++-- 5 files changed, 39 insertions(+), 58 deletions(-) diff --git a/app/models/item.py b/app/models/item.py index 233bca73..2269bc40 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -5,32 +5,6 @@ from enum import Enum -class FolderPrefix(str, Enum): - """In database, name folders and project folders will prefix with different path. and user will need to key in the - keyword to get the correct path. eg. - - - project folder: - - key in: /projectfolder/ - - path: /shared/ - - name folder: - - key in: // - - path: // - """ - - NAMEFOLDER = 'namefolder' - PROJECTFOLDER = 'projectfolder' - - def get_prefix(self) -> str: - """Get the prefix for the folder type.""" - - prefix = { - 'namefolder': '', - 'projectfolder': 'shared/', - } - - return prefix.get(self.value) - - class ItemType(str, Enum): """The class to reflect the type of item in database.""" @@ -40,16 +14,25 @@ class ItemType(str, Enum): PROJECTFOLDER = 'project_folder' @classmethod - def get_item_type(cls, value): - # Define a mapping for alternative values + def get_type_from_keyword(self, keyword: str): + """The function will return the type of the item based on the keyword. + + - name folder will have keyword 'namefolder' as input + - project folder will not have any keyword + """ + alternative_mapping = { - 'namefolder': cls.NAMEFOLDER, + 'projectfolder': self.PROJECTFOLDER, + } + + return alternative_mapping.get(keyword, self.NAMEFOLDER) + + def get_prefix_by_type(self) -> str: + """Get the prefix for the folder type.""" + + prefix = { + self.NAMEFOLDER: '', + self.PROJECTFOLDER: 'shared/', } - # Check if the value is in the alternative mapping - if value in alternative_mapping: - return alternative_mapping[value] - # Fall back to normal lookup by value - for item in cls: - if item.value == value: - return item - return None + + return prefix.get(self.value, '') diff --git a/app/services/file_manager/file_upload/file_upload.py b/app/services/file_manager/file_upload/file_upload.py index 9f5e335f..952ec259 100644 --- a/app/services/file_manager/file_upload/file_upload.py +++ b/app/services/file_manager/file_upload/file_upload.py @@ -18,7 +18,7 @@ import app.services.logger_services.log_functions as logger import app.services.output_manager.message_handler as mhandler from app.configs.app_config import AppConfig -from app.models.item import FolderPrefix +from app.models.item import ItemType from app.services.file_manager.file_upload.models import FileObject from app.services.file_manager.file_upload.models import ItemStatus from app.services.file_manager.file_upload.models import UploadType @@ -44,7 +44,7 @@ def compress_folder_to_zip(path): def assemble_path( - f: str, target_folder: str, project_code: str, folder_type: FolderPrefix, zone: str + f: str, target_folder: str, project_code: str, folder_type: ItemType, zone: str ) -> Tuple[str, Dict, bool, str]: ''' Summary: @@ -80,8 +80,8 @@ def assemble_path( current_folder_node = target_folder if os.path.isfile(f) else current_file_path create_folder_flag = False # add prefix to folder - current_folder_node = folder_type.get_prefix() + current_folder_node - target_folder = folder_type.get_prefix() + target_folder + current_folder_node = folder_type.get_prefix_by_type() + current_folder_node + target_folder = folder_type.get_prefix_by_type() + target_folder if len(current_file_path.split('/')) > 2: sub_path = target_folder.split('/') diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index e18c21eb..025c5008 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -17,7 +17,7 @@ from app.configs.app_config import AppConfig from app.configs.config import ConfigClass from app.configs.user_config import UserConfig -from app.models.item import FolderPrefix +from app.models.item import ItemType from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import SrvErrorHandler from app.services.user_authentication.decorator import require_valid_token @@ -166,7 +166,7 @@ def get_file_in_folder(path): return files_list -def identify_target_folder(project_path: str) -> Tuple[str, FolderPrefix, str]: +def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: ''' Summary: the function will validate if input folder path doesn't @@ -187,14 +187,13 @@ def identify_target_folder(project_path: str) -> Tuple[str, FolderPrefix, str]: # check folder type if is project folder or name folder # there will be a extra string for project folder between project code and folder name if len(temp_paths) == 2: - folder_type = FolderPrefix.NAMEFOLDER + folder_type = ItemType.NAMEFOLDER folder_name = temp_paths[1] elif len(temp_paths) >= 3: - if temp_paths[1] == FolderPrefix.PROJECTFOLDER.value: - folder_type = FolderPrefix.PROJECTFOLDER + folder_type = ItemType.get_type_from_keyword(temp_paths[1]) + if folder_type == ItemType.PROJECTFOLDER: folder_name = temp_paths[2] else: - folder_type = FolderPrefix.NAMEFOLDER folder_name = os.path.join(temp_paths[1], temp_paths[2]) else: SrvErrorHandler.customized_handle(ECustomizedError.INVALID_NAMEFOLDER, True) diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index 655f823b..5fa26447 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -3,7 +3,7 @@ # Contact Indoc Systems for any questions regarding the use of this source code. from app.configs.app_config import AppConfig -from app.models.item import FolderPrefix +from app.models.item import ItemType from app.services.file_manager.file_upload.file_upload import assemble_path from app.services.file_manager.file_upload.file_upload import resume_upload from app.services.file_manager.file_upload.file_upload import simple_upload @@ -34,7 +34,7 @@ def test_assemble_path_at_name_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderPrefix.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/file.txt' assert parent_folder.get('name') == 'admin' @@ -71,9 +71,8 @@ def test_assemble_path_at_exsting_folder(mocker): ] mocker.patch('app.services.file_manager.file_upload.file_upload.search_item', side_effect=node_list) - current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderPrefix.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_exist/file.txt' assert parent_folder.get('name') == 'test_folder_exist' @@ -104,7 +103,7 @@ def test_assemble_path_at_non_existing_folder(mocker): mocker.patch('app.services.file_manager.file_upload.file_upload.click.confirm', return_value=None) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderPrefix.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_not_exist' assert parent_folder.get('name') == 'admin' @@ -132,7 +131,7 @@ def test_assemble_path_at_project_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( - local_file_path, target_folder, project_code, FolderPrefix.PROJECTFOLDER, zone + local_file_path, target_folder, project_code, ItemType.PROJECTFOLDER, zone ) assert current_file_path == 'shared/project_folder/file.txt' assert parent_folder.get('name') == 'project_folder' diff --git a/tests/app/utils/test_aggregated.py b/tests/app/utils/test_aggregated.py index d6912e00..b81254df 100644 --- a/tests/app/utils/test_aggregated.py +++ b/tests/app/utils/test_aggregated.py @@ -5,7 +5,7 @@ import pytest from app.configs.app_config import AppConfig -from app.models.item import FolderPrefix +from app.models.item import ItemType from app.utils.aggregated import check_item_duplication from app.utils.aggregated import identify_target_folder from app.utils.aggregated import search_item @@ -136,10 +136,10 @@ def test_validate_folder_name(folder_name): @pytest.mark.parametrize( 'input_path,expected_result', [ - ('project_code/username', ('project_code', FolderPrefix.NAMEFOLDER, 'username')), - ('project_code/username/folder1', ('project_code', FolderPrefix.NAMEFOLDER, 'username/folder1')), - ('project_code/projectfolder/folder1', ('project_code', FolderPrefix.PROJECTFOLDER, 'folder1')), - ('project_code/projectfolder/folder1/folder2', ('project_code', FolderPrefix.PROJECTFOLDER, 'folder1/folder2')), + ('project_code/username', ('project_code', ItemType.NAMEFOLDER, 'username')), + ('project_code/username/folder1', ('project_code', ItemType.NAMEFOLDER, 'username/folder1')), + ('project_code/projectfolder/folder1', ('project_code', ItemType.PROJECTFOLDER, 'folder1')), + ('project_code/projectfolder/folder1/folder2', ('project_code', ItemType.PROJECTFOLDER, 'folder1/folder2')), ], ) def test_identify_target_folder_success_with_different_path(mocker, input_path, expected_result): From e86765f65a1180798afce7bf617530eb4fa7559d Mon Sep 17 00:00:00 2001 From: zhiren Date: Fri, 22 Mar 2024 16:50:42 -0400 Subject: [PATCH 03/18] add double quotation when item name contains space --- app/services/file_manager/file_list.py | 3 +++ tests/app/commands/test_file.py | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/services/file_manager/file_list.py b/app/services/file_manager/file_list.py index 45b00cbc..35338de2 100644 --- a/app/services/file_manager/file_list.py +++ b/app/services/file_manager/file_list.py @@ -61,6 +61,9 @@ def list_files(self, paths, zone, page, page_size): files, folders = '', '' for f in res: item_type = ItemType(f.get('type')) + # if there is space within the nane add double quotation to aviod confusion + if ' ' in f.get('name'): + f['name'] = f'"{f.get("name")}"' if item_type == ItemType.FILE: files = files + f.get('name') + ' ...' diff --git a/tests/app/commands/test_file.py b/tests/app/commands/test_file.py index 2492102c..ab9e64bc 100644 --- a/tests/app/commands/test_file.py +++ b/tests/app/commands/test_file.py @@ -185,7 +185,9 @@ def test_file_list_with_pagination_with_name_project_folder(requests_mock, mocke 'result': [ {'type': 'folder', 'name': 'folder1'}, {'type': 'name_folder', 'name': 'name_folder1'}, - {'type': 'project_folder', 'name': 'project_folder1'}, + {'type': 'project_folder', 'name': 'project folder1'}, + {'type': 'folder', 'name': 'test folder2'}, + {'type': 'project_folder', 'name': 'project folder2'}, ], }, ) @@ -193,7 +195,8 @@ def test_file_list_with_pagination_with_name_project_folder(requests_mock, mocke questionary.select.return_value.ask.return_value = 'exit' result = cli_runner.invoke(file_list, ['testproject/admin', '-z', 'greenroom']) outputs = result.output.split('\n') - assert outputs[0] == 'folder1 name_folder1 [p]project_folder1 ' + assert outputs[0] == 'folder1 name_folder1 [p]"project folder1" ' + assert outputs[1] == '"test folder2" [p]"project folder2" ' def test_empty_file_list_with_pagination(requests_mock, mocker, cli_runner): From 2b6b7f26c21ac4e44dd07ab7a1319d627183c247 Mon Sep 17 00:00:00 2001 From: zhiren Date: Mon, 1 Apr 2024 16:06:43 -0400 Subject: [PATCH 04/18] udpate move/rename commands to distinguish project folder/name folder --- app/commands/file.py | 18 +++++++++++++++++- .../file_manager/file_move/file_move_client.py | 6 +++--- app/utils/aggregated.py | 3 ++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/app/commands/file.py b/app/commands/file.py index e83baa27..9fa841a4 100644 --- a/app/commands/file.py +++ b/app/commands/file.py @@ -12,6 +12,7 @@ import app.services.output_manager.help_page as file_help import app.services.output_manager.message_handler as message_handler from app.configs.app_config import AppConfig +from app.models.item import ItemType from app.services.file_manager.file_download.download_client import SrvFileDownload from app.services.file_manager.file_list import SrvFileList from app.services.file_manager.file_manifests import SrvFileManifests @@ -544,8 +545,23 @@ def file_move(**kwargs): zone = kwargs.get('zone') skip_confirm = kwargs.get('yes') + if len(src_item_path.split('/')) == 1 and len(dest_item_path.split('/')) == 1: + raise Exception('Invalid path') + + # tranlate keyword to correct object path + src_keyword, src_path = src_item_path.split('/', 1) + dest_keyword, dest_path = dest_item_path.split('/', 1) + + src_type = ItemType.get_type_from_keyword(src_keyword) + dest_type = ItemType.get_type_from_keyword(dest_keyword) + + src_path = (src_type.get_prefix_by_type() + src_path) if src_type == ItemType.PROJECTFOLDER else src_item_path + dest_path = (dest_type.get_prefix_by_type() + dest_path) if dest_type == ItemType.PROJECTFOLDER else dest_item_path + + # raise + zone = get_zone(zone) if zone else AppConfig.Env.green_zone.lower() - file_meta_client = FileMoveClient(zone, project_code, src_item_path, dest_item_path, skip_confirm=skip_confirm) + file_meta_client = FileMoveClient(zone, project_code, src_path, dest_path, skip_confirm=skip_confirm) file_meta_client.move_file() message_handler.SrvOutPutHandler.move_action_success(src_item_path, dest_item_path) diff --git a/app/services/file_manager/file_move/file_move_client.py b/app/services/file_manager/file_move/file_move_client.py index 17478598..2c5d36dd 100644 --- a/app/services/file_manager/file_move/file_move_client.py +++ b/app/services/file_manager/file_move/file_move_client.py @@ -62,9 +62,9 @@ def create_object_path_if_not_exist(self, folder_path: str) -> dict: path_list = folder_path.split('/') # first get the root folder to check if it is name folder # or project folder - root_item = search_item(self.project_code, self.zone, path_list[0]).get('result') - if root_item.get('type') == 'project_folder': - path_list[0] = '/'.join([root_item.get('parent_path'), path_list[0]]) + # root_item = search_item(self.project_code, self.zone, path_list[0]).get('result') + # if root_item.get('type') == 'project_folder': + # path_list[0] = '/'.join([root_item.get('parent_path'), path_list[0]]) # first check every folder in path exist or not # the loop start with index 1 since we assume cli will not diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index 025c5008..6fa3c78b 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -89,7 +89,8 @@ def check_item_duplication(item_list: List[str], zone: int, project_code: str) - - list of item path that already exists in the project ''' - url = AppConfig.Connections.url_base + '/portal/v1/files/exists' + # url = AppConfig.Connections.url_base + '/portal/v1/files/exists' + url = 'http://localhost:5060/v1/files/exists' headers = {'Authorization': 'Bearer ' + UserConfig().access_token} payload = { 'locations': item_list, From 3d76446bb3a24ce665103764bdafe05c8b8f6dba Mon Sep 17 00:00:00 2001 From: zhiren Date: Mon, 1 Apr 2024 16:50:57 -0400 Subject: [PATCH 05/18] change enum type PROJECTFOLDER to SHAREDFOLDER --- app/models/item.py | 6 +++--- app/services/file_manager/file_list.py | 2 +- app/utils/aggregated.py | 2 +- .../services/file_manager/file_upload/test_file_upload.py | 2 +- tests/app/utils/test_aggregated.py | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/models/item.py b/app/models/item.py index 2269bc40..a7a91029 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -11,7 +11,7 @@ class ItemType(str, Enum): FILE = 'file' Folder = 'folder' NAMEFOLDER = 'name_folder' - PROJECTFOLDER = 'project_folder' + SHAREDFOLDER = 'project_folder' @classmethod def get_type_from_keyword(self, keyword: str): @@ -22,7 +22,7 @@ def get_type_from_keyword(self, keyword: str): """ alternative_mapping = { - 'projectfolder': self.PROJECTFOLDER, + 'projectfolder': self.SHAREDFOLDER, } return alternative_mapping.get(keyword, self.NAMEFOLDER) @@ -32,7 +32,7 @@ def get_prefix_by_type(self) -> str: prefix = { self.NAMEFOLDER: '', - self.PROJECTFOLDER: 'shared/', + self.SHAREDFOLDER: 'shared/', } return prefix.get(self.value, '') diff --git a/app/services/file_manager/file_list.py b/app/services/file_manager/file_list.py index 35338de2..2131903a 100644 --- a/app/services/file_manager/file_list.py +++ b/app/services/file_manager/file_list.py @@ -69,7 +69,7 @@ def list_files(self, paths, zone, page, page_size): files = files + f.get('name') + ' ...' else: # add [p] in front of the project folder - if item_type == ItemType.PROJECTFOLDER: + if item_type == ItemType.SHAREDFOLDER: f['name'] = f'[p]{f.get("name")}' folders = folders + f"\033[34m{f.get('name')}\033[0m ..." diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index 025c5008..e338ae5f 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -191,7 +191,7 @@ def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: folder_name = temp_paths[1] elif len(temp_paths) >= 3: folder_type = ItemType.get_type_from_keyword(temp_paths[1]) - if folder_type == ItemType.PROJECTFOLDER: + if folder_type == ItemType.SHAREDFOLDER: folder_name = temp_paths[2] else: folder_name = os.path.join(temp_paths[1], temp_paths[2]) diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index 5fa26447..fb385057 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -131,7 +131,7 @@ def test_assemble_path_at_project_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( - local_file_path, target_folder, project_code, ItemType.PROJECTFOLDER, zone + local_file_path, target_folder, project_code, ItemType.SHAREDFOLDER, zone ) assert current_file_path == 'shared/project_folder/file.txt' assert parent_folder.get('name') == 'project_folder' diff --git a/tests/app/utils/test_aggregated.py b/tests/app/utils/test_aggregated.py index b81254df..91454cbb 100644 --- a/tests/app/utils/test_aggregated.py +++ b/tests/app/utils/test_aggregated.py @@ -138,8 +138,8 @@ def test_validate_folder_name(folder_name): [ ('project_code/username', ('project_code', ItemType.NAMEFOLDER, 'username')), ('project_code/username/folder1', ('project_code', ItemType.NAMEFOLDER, 'username/folder1')), - ('project_code/projectfolder/folder1', ('project_code', ItemType.PROJECTFOLDER, 'folder1')), - ('project_code/projectfolder/folder1/folder2', ('project_code', ItemType.PROJECTFOLDER, 'folder1/folder2')), + ('project_code/projectfolder/folder1', ('project_code', ItemType.SHAREDFOLDER, 'folder1')), + ('project_code/projectfolder/folder1/folder2', ('project_code', ItemType.SHAREDFOLDER, 'folder1/folder2')), ], ) def test_identify_target_folder_success_with_different_path(mocker, input_path, expected_result): From 8673b947d9bd4b021da80a372d7ee7580ae3a7d9 Mon Sep 17 00:00:00 2001 From: zhiren Date: Tue, 2 Apr 2024 16:16:45 -0400 Subject: [PATCH 06/18] update move/rename logic but will need to fix upload/list command for prefix changes --- app/models/item.py | 7 ++++--- .../file_manager/file_move/file_move_client.py | 7 +------ .../file_manager/file_upload/test_file_upload.py | 12 ++++++------ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/app/models/item.py b/app/models/item.py index a7a91029..1e876fb8 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -11,7 +11,7 @@ class ItemType(str, Enum): FILE = 'file' Folder = 'folder' NAMEFOLDER = 'name_folder' - SHAREDFOLDER = 'project_folder' + SHAREDFOLDER = 'shared_folder' @classmethod def get_type_from_keyword(self, keyword: str): @@ -22,7 +22,8 @@ def get_type_from_keyword(self, keyword: str): """ alternative_mapping = { - 'projectfolder': self.SHAREDFOLDER, + 'shared': self.SHAREDFOLDER, + 'users': self.NAMEFOLDER, } return alternative_mapping.get(keyword, self.NAMEFOLDER) @@ -31,7 +32,7 @@ def get_prefix_by_type(self) -> str: """Get the prefix for the folder type.""" prefix = { - self.NAMEFOLDER: '', + self.NAMEFOLDER: 'users/', self.SHAREDFOLDER: 'shared/', } diff --git a/app/services/file_manager/file_move/file_move_client.py b/app/services/file_manager/file_move/file_move_client.py index 2c5d36dd..a64c59e7 100644 --- a/app/services/file_manager/file_move/file_move_client.py +++ b/app/services/file_manager/file_move/file_move_client.py @@ -60,11 +60,6 @@ def create_object_path_if_not_exist(self, folder_path: str) -> dict: """ path_list = folder_path.split('/') - # first get the root folder to check if it is name folder - # or project folder - # root_item = search_item(self.project_code, self.zone, path_list[0]).get('result') - # if root_item.get('type') == 'project_folder': - # path_list[0] = '/'.join([root_item.get('parent_path'), path_list[0]]) # first check every folder in path exist or not # the loop start with index 1 since we assume cli will not @@ -123,7 +118,7 @@ def move_file(self) -> None: Move file. """ - self.create_object_path_if_not_exist(self.dest_item_path) + # self.create_object_path_if_not_exist(self.dest_item_path) try: url = AppConfig.Connections.url_bff + f'/v1/{self.project_code}/files' diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index fb385057..d357e082 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -112,7 +112,7 @@ def test_assemble_path_at_non_existing_folder(mocker): def test_assemble_path_at_project_folder(mocker): local_file_path = './test/file.txt' - target_folder = 'project_folder' + target_folder = ItemType.SHAREDFOLDER.value project_code = 'test_project' zone = 0 @@ -123,9 +123,9 @@ def test_assemble_path_at_project_folder(mocker): 'id': 'test', 'parent_id': 'test_parent', 'parent_path': '', - 'name': 'project_folder', + 'name': target_folder, 'zone': 0, - 'type': 'project_folder', + 'type': target_folder, } }, ) @@ -133,9 +133,9 @@ def test_assemble_path_at_project_folder(mocker): current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( local_file_path, target_folder, project_code, ItemType.SHAREDFOLDER, zone ) - assert current_file_path == 'shared/project_folder/file.txt' - assert parent_folder.get('name') == 'project_folder' - assert target_folder == 'shared/project_folder' + assert current_file_path == f'shared/{target_folder}/file.txt' + assert parent_folder.get('name') == target_folder + assert target_folder == f'shared/{target_folder}' assert create_folder_flag is False From 3f38db5d8368c2650a36757bd874d1a34e55ced5 Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 11:10:39 -0400 Subject: [PATCH 07/18] replace PROJECTFOLDER with SHAREDFOLDER --- app/commands/file.py | 4 ++-- app/models/item.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/commands/file.py b/app/commands/file.py index 9fa841a4..52c75f08 100644 --- a/app/commands/file.py +++ b/app/commands/file.py @@ -555,8 +555,8 @@ def file_move(**kwargs): src_type = ItemType.get_type_from_keyword(src_keyword) dest_type = ItemType.get_type_from_keyword(dest_keyword) - src_path = (src_type.get_prefix_by_type() + src_path) if src_type == ItemType.PROJECTFOLDER else src_item_path - dest_path = (dest_type.get_prefix_by_type() + dest_path) if dest_type == ItemType.PROJECTFOLDER else dest_item_path + src_path = (src_type.get_prefix_by_type() + src_path) if src_type == ItemType.SHAREDFOLDER else src_item_path + dest_path = (dest_type.get_prefix_by_type() + dest_path) if dest_type == ItemType.SHAREDFOLDER else dest_item_path # raise diff --git a/app/models/item.py b/app/models/item.py index 1e876fb8..569bc066 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -11,7 +11,7 @@ class ItemType(str, Enum): FILE = 'file' Folder = 'folder' NAMEFOLDER = 'name_folder' - SHAREDFOLDER = 'shared_folder' + SHAREDFOLDER = 'project_folder' @classmethod def get_type_from_keyword(self, keyword: str): From 09c4ca3b746fe3939daf2ff014b842dbfcce5bcd Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 11:18:55 -0400 Subject: [PATCH 08/18] replace PROJECTFOLDER with SHAREDFOLDER --- app/models/folder.py | 22 ----------- app/models/item.py | 39 +++++++++++++++++++ .../file_manager/file_upload/file_upload.py | 8 ++-- app/utils/aggregated.py | 12 +++--- .../file_upload/test_file_upload.py | 10 ++--- tests/app/utils/test_aggregated.py | 10 ++--- 6 files changed, 59 insertions(+), 42 deletions(-) delete mode 100644 app/models/folder.py create mode 100644 app/models/item.py diff --git a/app/models/folder.py b/app/models/folder.py deleted file mode 100644 index 180c337c..00000000 --- a/app/models/folder.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2023-2024 Indoc Systems -# -# Contact Indoc Systems for any questions regarding the use of this source code. - -from enum import Enum - - -class FolderType(str, Enum): - """Available folder types.""" - - NAMEFOLDER = 'namefolder' - PROJECTFOLDER = 'projectfolder' - - def get_prefix(self) -> str: - """Get the prefix for the folder type.""" - - prefix = { - 'namefolder': '', - 'projectfolder': 'shared/', - } - - return prefix.get(self.value) diff --git a/app/models/item.py b/app/models/item.py new file mode 100644 index 00000000..569bc066 --- /dev/null +++ b/app/models/item.py @@ -0,0 +1,39 @@ +# Copyright (C) 2023-2024 Indoc Systems +# +# Contact Indoc Systems for any questions regarding the use of this source code. + +from enum import Enum + + +class ItemType(str, Enum): + """The class to reflect the type of item in database.""" + + FILE = 'file' + Folder = 'folder' + NAMEFOLDER = 'name_folder' + SHAREDFOLDER = 'project_folder' + + @classmethod + def get_type_from_keyword(self, keyword: str): + """The function will return the type of the item based on the keyword. + + - name folder will have keyword 'namefolder' as input + - project folder will not have any keyword + """ + + alternative_mapping = { + 'shared': self.SHAREDFOLDER, + 'users': self.NAMEFOLDER, + } + + return alternative_mapping.get(keyword, self.NAMEFOLDER) + + def get_prefix_by_type(self) -> str: + """Get the prefix for the folder type.""" + + prefix = { + self.NAMEFOLDER: 'users/', + self.SHAREDFOLDER: 'shared/', + } + + return prefix.get(self.value, '') diff --git a/app/services/file_manager/file_upload/file_upload.py b/app/services/file_manager/file_upload/file_upload.py index 4dda080b..952ec259 100644 --- a/app/services/file_manager/file_upload/file_upload.py +++ b/app/services/file_manager/file_upload/file_upload.py @@ -18,7 +18,7 @@ import app.services.logger_services.log_functions as logger import app.services.output_manager.message_handler as mhandler from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.services.file_manager.file_upload.models import FileObject from app.services.file_manager.file_upload.models import ItemStatus from app.services.file_manager.file_upload.models import UploadType @@ -44,7 +44,7 @@ def compress_folder_to_zip(path): def assemble_path( - f: str, target_folder: str, project_code: str, folder_type: FolderType, zone: str + f: str, target_folder: str, project_code: str, folder_type: ItemType, zone: str ) -> Tuple[str, Dict, bool, str]: ''' Summary: @@ -80,8 +80,8 @@ def assemble_path( current_folder_node = target_folder if os.path.isfile(f) else current_file_path create_folder_flag = False # add prefix to folder - current_folder_node = folder_type.get_prefix() + current_folder_node - target_folder = folder_type.get_prefix() + target_folder + current_folder_node = folder_type.get_prefix_by_type() + current_folder_node + target_folder = folder_type.get_prefix_by_type() + target_folder if len(current_file_path.split('/')) > 2: sub_path = target_folder.split('/') diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index 662db673..af4a0b08 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -17,7 +17,7 @@ from app.configs.app_config import AppConfig from app.configs.config import ConfigClass from app.configs.user_config import UserConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import SrvErrorHandler from app.services.user_authentication.decorator import require_valid_token @@ -166,7 +166,7 @@ def get_file_in_folder(path): return files_list -def identify_target_folder(project_path: str) -> Tuple[str, FolderType, str]: +def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: ''' Summary: the function will validate if input folder path doesn't @@ -187,14 +187,14 @@ def identify_target_folder(project_path: str) -> Tuple[str, FolderType, str]: # check folder type if is project folder or name folder # there will be a extra string for project folder between project code and folder name if len(temp_paths) == 2: - folder_type = FolderType.NAMEFOLDER + folder_type = ItemType.NAMEFOLDER folder_name = temp_paths[1] elif len(temp_paths) >= 3: - if temp_paths[1] == FolderType.PROJECTFOLDER.value: - folder_type = FolderType.PROJECTFOLDER + if temp_paths[1] == ItemType.SHAREDFOLDER.value: + folder_type = ItemType.SHAREDFOLDER folder_name = temp_paths[2] else: - folder_type = FolderType.NAMEFOLDER + folder_type = ItemType.NAMEFOLDER folder_name = os.path.join(temp_paths[1], temp_paths[2]) else: SrvErrorHandler.customized_handle(ECustomizedError.INVALID_NAMEFOLDER, True) diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index b4a9ffb2..4be1b77b 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -3,7 +3,7 @@ # Contact Indoc Systems for any questions regarding the use of this source code. from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.services.file_manager.file_upload.file_upload import assemble_path from app.services.file_manager.file_upload.file_upload import resume_upload from app.services.file_manager.file_upload.file_upload import simple_upload @@ -34,7 +34,7 @@ def test_assemble_path_at_name_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/file.txt' assert parent_folder.get('name') == 'admin' @@ -73,7 +73,7 @@ def test_assemble_path_at_exsting_folder(mocker): mocker.patch('app.services.file_manager.file_upload.file_upload.search_item', side_effect=node_list) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_exist/file.txt' assert parent_folder.get('name') == 'test_folder_exist' @@ -104,7 +104,7 @@ def test_assemble_path_at_non_existing_folder(mocker): mocker.patch('app.services.file_manager.file_upload.file_upload.click.confirm', return_value=None) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_not_exist' assert parent_folder.get('name') == 'admin' @@ -132,7 +132,7 @@ def test_assemble_path_at_project_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( - local_file_path, target_folder, project_code, FolderType.PROJECTFOLDER, zone + local_file_path, target_folder, project_code, ItemType.SHAREDFOLDER, zone ) assert current_file_path == 'shared/project_folder/file.txt' assert parent_folder.get('name') == 'project_folder' diff --git a/tests/app/utils/test_aggregated.py b/tests/app/utils/test_aggregated.py index 88194ca2..91454cbb 100644 --- a/tests/app/utils/test_aggregated.py +++ b/tests/app/utils/test_aggregated.py @@ -5,7 +5,7 @@ import pytest from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.utils.aggregated import check_item_duplication from app.utils.aggregated import identify_target_folder from app.utils.aggregated import search_item @@ -136,10 +136,10 @@ def test_validate_folder_name(folder_name): @pytest.mark.parametrize( 'input_path,expected_result', [ - ('project_code/username', ('project_code', FolderType.NAMEFOLDER, 'username')), - ('project_code/username/folder1', ('project_code', FolderType.NAMEFOLDER, 'username/folder1')), - ('project_code/projectfolder/folder1', ('project_code', FolderType.PROJECTFOLDER, 'folder1')), - ('project_code/projectfolder/folder1/folder2', ('project_code', FolderType.PROJECTFOLDER, 'folder1/folder2')), + ('project_code/username', ('project_code', ItemType.NAMEFOLDER, 'username')), + ('project_code/username/folder1', ('project_code', ItemType.NAMEFOLDER, 'username/folder1')), + ('project_code/projectfolder/folder1', ('project_code', ItemType.SHAREDFOLDER, 'folder1')), + ('project_code/projectfolder/folder1/folder2', ('project_code', ItemType.SHAREDFOLDER, 'folder1/folder2')), ], ) def test_identify_target_folder_success_with_different_path(mocker, input_path, expected_result): From bfadd0f6be2cf85e8c086a6eb14e97574b978646 Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 11:40:57 -0400 Subject: [PATCH 09/18] fixup test cases --- app/utils/aggregated.py | 27 ++++++++++-------- tests/app/commands/test_file.py | 11 +++++++- .../file_upload/test_file_upload.py | 28 ++++++++++++++++--- tests/app/utils/test_aggregated.py | 20 ++++++++++--- 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index af4a0b08..c975783a 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -173,8 +173,8 @@ def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: contain invalid characters and return the project code and target folder Parameters: - project_path: - - for project folder the input folder path (eg. /projectfolder/) - - for name folder the input folder path will be (eg. /) + - for project folder the input folder path (eg. /shared/) + - for name folder the input folder path will be (eg. /users/) Return: - project_code: the project code - folder_type: the folder type @@ -186,16 +186,19 @@ def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: # check folder type if is project folder or name folder # there will be a extra string for project folder between project code and folder name - if len(temp_paths) == 2: - folder_type = ItemType.NAMEFOLDER - folder_name = temp_paths[1] - elif len(temp_paths) >= 3: - if temp_paths[1] == ItemType.SHAREDFOLDER.value: - folder_type = ItemType.SHAREDFOLDER - folder_name = temp_paths[2] - else: - folder_type = ItemType.NAMEFOLDER - folder_name = os.path.join(temp_paths[1], temp_paths[2]) + # if len(temp_paths) == 2: + # folder_type = ItemType.NAMEFOLDER + # folder_name = temp_paths[1] + # el + if len(temp_paths) >= 3: + # if temp_paths[1] == ItemType.SHAREDFOLDER.value: + # folder_type = ItemType.SHAREDFOLDER + # folder_name = temp_paths[2] + # else: + # folder_type = ItemType.NAMEFOLDER + # folder_name = os.path.join(temp_paths[1], temp_paths[2]) + folder_type = ItemType.get_type_from_keyword(temp_paths[1]) + folder_name = temp_paths[2] else: SrvErrorHandler.customized_handle(ECustomizedError.INVALID_NAMEFOLDER, True) target_folder = '' diff --git a/tests/app/commands/test_file.py b/tests/app/commands/test_file.py index 3abe2cab..1679c8f7 100644 --- a/tests/app/commands/test_file.py +++ b/tests/app/commands/test_file.py @@ -16,6 +16,7 @@ from app.commands.file import file_move from app.commands.file import file_put from app.commands.file import file_resume +from app.models.item import ItemType from app.services.file_manager.file_metadata.file_metadata_client import FileMetaClient from app.services.file_manager.file_upload.models import FileObject from app.services.output_manager.error_handler import ECustomizedError @@ -45,7 +46,15 @@ def test_file_upload_command_success_with_attribute(mocker, cli_runner): result = cli_runner.invoke( file_put, - ['--project-path', 'test_project/admin', '--thread', 1, '--attribute', 'template.json', 'test.txt'], + [ + '--project-path', + f'test_project/{ItemType.NAMEFOLDER.get_prefix_by_type()}admin', + '--thread', + 1, + '--attribute', + 'template.json', + 'test.txt', + ], ) assert result.exit_code == 0 diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index 4be1b77b..15277aab 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -36,7 +36,7 @@ def test_assemble_path_at_name_folder(mocker): current_file_path, parent_folder, create_folder_flag, _ = assemble_path( local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) - assert current_file_path == 'admin/file.txt' + assert current_file_path == f'{ItemType.NAMEFOLDER.get_prefix_by_type()}admin/file.txt' assert parent_folder.get('name') == 'admin' assert create_folder_flag is False @@ -53,6 +53,16 @@ def test_assemble_path_at_exsting_folder(mocker): 'id': 'test', 'parent_id': 'test_parent', 'parent_path': '', + 'name': ItemType.NAMEFOLDER.get_prefix_by_type().strip('/'), + 'zone': 0, + 'type': 'folder', + } + }, + { + 'result': { + 'id': 'test', + 'parent_id': 'test_parent', + 'parent_path': ItemType.NAMEFOLDER.get_prefix_by_type(), 'name': 'admin', 'zone': 0, 'type': 'folder', @@ -62,7 +72,7 @@ def test_assemble_path_at_exsting_folder(mocker): 'result': { 'id': 'test', 'parent_id': 'test_parent', - 'parent_path': 'admin', + 'parent_path': ItemType.NAMEFOLDER.get_prefix_by_type() + 'admin', 'name': 'test_folder_exist', 'zone': 0, 'type': 'folder', @@ -75,7 +85,7 @@ def test_assemble_path_at_exsting_folder(mocker): current_file_path, parent_folder, create_folder_flag, _ = assemble_path( local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) - assert current_file_path == 'admin/test_folder_exist/file.txt' + assert current_file_path == f'{ItemType.NAMEFOLDER.get_prefix_by_type()}admin/test_folder_exist/file.txt' assert parent_folder.get('name') == 'test_folder_exist' assert create_folder_flag is False @@ -92,6 +102,16 @@ def test_assemble_path_at_non_existing_folder(mocker): 'id': 'test', 'parent_id': 'test_parent', 'parent_path': '', + 'name': ItemType.NAMEFOLDER.get_prefix_by_type().strip('/'), + 'zone': 0, + 'type': 'folder', + } + }, + { + 'result': { + 'id': 'test', + 'parent_id': 'test_parent', + 'parent_path': ItemType.NAMEFOLDER.get_prefix_by_type(), 'name': 'admin', 'zone': 0, 'type': 'folder', @@ -106,7 +126,7 @@ def test_assemble_path_at_non_existing_folder(mocker): current_file_path, parent_folder, create_folder_flag, _ = assemble_path( local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) - assert current_file_path == 'admin/test_folder_not_exist' + assert current_file_path == f'{ItemType.NAMEFOLDER.get_prefix_by_type()}admin/test_folder_not_exist' assert parent_folder.get('name') == 'admin' assert create_folder_flag is True diff --git a/tests/app/utils/test_aggregated.py b/tests/app/utils/test_aggregated.py index 91454cbb..1a892dc7 100644 --- a/tests/app/utils/test_aggregated.py +++ b/tests/app/utils/test_aggregated.py @@ -136,10 +136,22 @@ def test_validate_folder_name(folder_name): @pytest.mark.parametrize( 'input_path,expected_result', [ - ('project_code/username', ('project_code', ItemType.NAMEFOLDER, 'username')), - ('project_code/username/folder1', ('project_code', ItemType.NAMEFOLDER, 'username/folder1')), - ('project_code/projectfolder/folder1', ('project_code', ItemType.SHAREDFOLDER, 'folder1')), - ('project_code/projectfolder/folder1/folder2', ('project_code', ItemType.SHAREDFOLDER, 'folder1/folder2')), + ( + f'project_code/{ItemType.NAMEFOLDER.get_prefix_by_type()}username', + ('project_code', ItemType.NAMEFOLDER, 'username'), + ), + ( + f'project_code/{ItemType.NAMEFOLDER.get_prefix_by_type()}username/folder1', + ('project_code', ItemType.NAMEFOLDER, 'username/folder1'), + ), + ( + f'project_code/{ItemType.SHAREDFOLDER.get_prefix_by_type()}folder1', + ('project_code', ItemType.SHAREDFOLDER, 'folder1'), + ), + ( + f'project_code/{ItemType.SHAREDFOLDER.get_prefix_by_type()}folder1/folder2', + ('project_code', ItemType.SHAREDFOLDER, 'folder1/folder2'), + ), ], ) def test_identify_target_folder_success_with_different_path(mocker, input_path, expected_result): From 1ce8df747a42755b7b80f19234a402204aefad33 Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 16:28:04 -0400 Subject: [PATCH 10/18] fixup logic for different prefix --- app/models/item.py | 2 +- app/resources/custom_help.py | 6 +----- app/utils/aggregated.py | 10 ---------- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/app/models/item.py b/app/models/item.py index 569bc066..c670e293 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -32,7 +32,7 @@ def get_prefix_by_type(self) -> str: """Get the prefix for the folder type.""" prefix = { - self.NAMEFOLDER: 'users/', + self.NAMEFOLDER: '', self.SHAREDFOLDER: 'shared/', } diff --git a/app/resources/custom_help.py b/app/resources/custom_help.py index 3e4b17e6..f0edb329 100644 --- a/app/resources/custom_help.py +++ b/app/resources/custom_help.py @@ -43,11 +43,7 @@ class HelpPage: 'FILE_SYNC_ZIP': 'Download files as a zip.', 'FILE_SYNC_I': 'Enable downloading by geid.', 'FILE_SYNC_Z': 'Target Zone (i.e., core/greenroom).', - 'FILE_UPLOAD_P': ( - 'Project folder path starting from Project Code(i.e. /user/folder). ' - 'A new key word `projectfolder` is required to specify project folder(i.e. ' - '/projectfolder/folder1)' - ), + 'FILE_UPLOAD_P': 'Project folder path starting from Project Code(i.e. /users/admin/folder). ', 'FILE_UPLOAD_A': 'Add attributes to the file using a File Attribute Template.', 'FILE_UPLOAD_T': 'Add tags to the file using a Tag file.', 'FILE_UPLOAD_M': 'The message used to comment on the purpose of uploading your processed file.', diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index c975783a..a645d972 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -186,17 +186,7 @@ def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: # check folder type if is project folder or name folder # there will be a extra string for project folder between project code and folder name - # if len(temp_paths) == 2: - # folder_type = ItemType.NAMEFOLDER - # folder_name = temp_paths[1] - # el if len(temp_paths) >= 3: - # if temp_paths[1] == ItemType.SHAREDFOLDER.value: - # folder_type = ItemType.SHAREDFOLDER - # folder_name = temp_paths[2] - # else: - # folder_type = ItemType.NAMEFOLDER - # folder_name = os.path.join(temp_paths[1], temp_paths[2]) folder_type = ItemType.get_type_from_keyword(temp_paths[1]) folder_name = temp_paths[2] else: From 7020626ac24e512556c2425382fec27fcacc4398 Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 16:32:00 -0400 Subject: [PATCH 11/18] add prefix for name folder --- app/models/item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/item.py b/app/models/item.py index c670e293..569bc066 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -32,7 +32,7 @@ def get_prefix_by_type(self) -> str: """Get the prefix for the folder type.""" prefix = { - self.NAMEFOLDER: '', + self.NAMEFOLDER: 'users/', self.SHAREDFOLDER: 'shared/', } From 77133af00443e3846b3ce0b1a5534cd25db35150 Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 16:36:34 -0400 Subject: [PATCH 12/18] bump up version to 3.0.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 07a4eeb4..c5a8b4c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "app" -version = "2.10.0" +version = "3.0.0" description = "This service is designed to support pilot platform" authors = ["Indoc Systems"] From 0602417ed62d048ee2d9a9ac896dccdf55bc9a49 Mon Sep 17 00:00:00 2001 From: zhiren Date: Wed, 3 Apr 2024 17:42:20 -0400 Subject: [PATCH 13/18] fixup test cases --- .../app/services/file_manager/file_upload/test_file_upload.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index 15277aab..efacf163 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -154,9 +154,9 @@ def test_assemble_path_at_project_folder(mocker): current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( local_file_path, target_folder, project_code, ItemType.SHAREDFOLDER, zone ) - assert current_file_path == 'shared/project_folder/file.txt' + assert current_file_path == f'{ItemType.SHAREDFOLDER.get_prefix_by_type()}project_folder/file.txt' assert parent_folder.get('name') == 'project_folder' - assert target_folder == 'shared/project_folder' + assert target_folder == f'{ItemType.SHAREDFOLDER.get_prefix_by_type()}project_folder' assert create_folder_flag is False From 1900019065a88dc85c2973cf372f4497c7a4fec2 Mon Sep 17 00:00:00 2001 From: zhiren Date: Fri, 5 Apr 2024 17:38:57 -0400 Subject: [PATCH 14/18] fixup test cases --- app/commands/file.py | 2 -- app/services/file_manager/file_move/file_move_client.py | 2 +- app/utils/aggregated.py | 3 +-- tests/app/commands/test_file.py | 7 +++++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/commands/file.py b/app/commands/file.py index 52c75f08..5304eaf1 100644 --- a/app/commands/file.py +++ b/app/commands/file.py @@ -558,8 +558,6 @@ def file_move(**kwargs): src_path = (src_type.get_prefix_by_type() + src_path) if src_type == ItemType.SHAREDFOLDER else src_item_path dest_path = (dest_type.get_prefix_by_type() + dest_path) if dest_type == ItemType.SHAREDFOLDER else dest_item_path - # raise - zone = get_zone(zone) if zone else AppConfig.Env.green_zone.lower() file_meta_client = FileMoveClient(zone, project_code, src_path, dest_path, skip_confirm=skip_confirm) file_meta_client.move_file() diff --git a/app/services/file_manager/file_move/file_move_client.py b/app/services/file_manager/file_move/file_move_client.py index a64c59e7..2c998428 100644 --- a/app/services/file_manager/file_move/file_move_client.py +++ b/app/services/file_manager/file_move/file_move_client.py @@ -118,7 +118,7 @@ def move_file(self) -> None: Move file. """ - # self.create_object_path_if_not_exist(self.dest_item_path) + self.create_object_path_if_not_exist(self.dest_item_path) try: url = AppConfig.Connections.url_bff + f'/v1/{self.project_code}/files' diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index 51b1651f..a645d972 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -89,8 +89,7 @@ def check_item_duplication(item_list: List[str], zone: int, project_code: str) - - list of item path that already exists in the project ''' - # url = AppConfig.Connections.url_base + '/portal/v1/files/exists' - url = 'http://localhost:5060/v1/files/exists' + url = AppConfig.Connections.url_base + '/portal/v1/files/exists' headers = {'Authorization': 'Bearer ' + UserConfig().access_token} payload = { 'locations': item_list, diff --git a/tests/app/commands/test_file.py b/tests/app/commands/test_file.py index 4b45c6b3..fb1d253b 100644 --- a/tests/app/commands/test_file.py +++ b/tests/app/commands/test_file.py @@ -388,7 +388,10 @@ def test_file_move_success(mocker, cli_runner): return_value=None, ) - result = cli_runner.invoke(file_move, ['test_project', 'src_item_path', 'dest_item_path']) + src_path = 'src_item_path/test' + dest_path = 'dest_item_path/test' + result = cli_runner.invoke(file_move, ['test_project', src_path, dest_path]) + outputs = result.output.split('\n') - assert outputs[0] == 'Successfully moved src_item_path to dest_item_path' + assert outputs[0] == f'Successfully moved {src_path} to {dest_path}' file_move_mock.assert_called_once() From 6197fbdda983c1a7ed0d036ed677642dabeec871 Mon Sep 17 00:00:00 2001 From: zhiren Date: Thu, 25 Apr 2024 15:34:15 -0400 Subject: [PATCH 15/18] remove SHAREFOLDER specific logic --- app/commands/file.py | 4 ++-- app/models/item.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/commands/file.py b/app/commands/file.py index 5304eaf1..319f2221 100644 --- a/app/commands/file.py +++ b/app/commands/file.py @@ -555,8 +555,8 @@ def file_move(**kwargs): src_type = ItemType.get_type_from_keyword(src_keyword) dest_type = ItemType.get_type_from_keyword(dest_keyword) - src_path = (src_type.get_prefix_by_type() + src_path) if src_type == ItemType.SHAREDFOLDER else src_item_path - dest_path = (dest_type.get_prefix_by_type() + dest_path) if dest_type == ItemType.SHAREDFOLDER else dest_item_path + src_path = src_type.get_prefix_by_type() + src_path + dest_path = dest_type.get_prefix_by_type() + dest_path zone = get_zone(zone) if zone else AppConfig.Env.green_zone.lower() file_meta_client = FileMoveClient(zone, project_code, src_path, dest_path, skip_confirm=skip_confirm) diff --git a/app/models/item.py b/app/models/item.py index db1068d8..b7c84b6c 100644 --- a/app/models/item.py +++ b/app/models/item.py @@ -27,7 +27,7 @@ def get_type_from_keyword(self, keyword: str): 'users': self.NAMEFOLDER, } - return alternative_mapping.get(keyword, '') + return alternative_mapping.get(keyword, self.FOLDER) def get_prefix_by_type(self) -> str: """Get the prefix for the folder type.""" From d60c5d6c925533a0696e5a13e0de18e2c4eb32f8 Mon Sep 17 00:00:00 2001 From: zhiren Date: Thu, 25 Apr 2024 15:36:30 -0400 Subject: [PATCH 16/18] fixup test cases --- tests/app/commands/test_file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/app/commands/test_file.py b/tests/app/commands/test_file.py index 40a924af..8b558768 100644 --- a/tests/app/commands/test_file.py +++ b/tests/app/commands/test_file.py @@ -208,7 +208,7 @@ def test_empty_file_list_with_pagination(requests_mock, mocker, cli_runner): questionary.select.return_value.ask.return_value = 'exit' result = cli_runner.invoke(file_list, ['testproject/admin', '-z', 'greenroom']) outputs = result.output.split('\n') - assert outputs[0] == '' + assert outputs[0] == ' ' @pytest.mark.parametrize('parent_folder_type', [ItemType.NAMEFOLDER.value, ItemType.SHAREDFOLDER.value]) From 52b544591d3a7997fa805eab1b61ea414a8a1a24 Mon Sep 17 00:00:00 2001 From: zhiren Date: Thu, 25 Apr 2024 15:44:45 -0400 Subject: [PATCH 17/18] bumpup version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c5a8b4c7..d2b215b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "app" -version = "3.0.0" +version = "3.0.1" description = "This service is designed to support pilot platform" authors = ["Indoc Systems"] From 15cc6652301ef78986a5120d30b3ef999b4b3673 Mon Sep 17 00:00:00 2001 From: Color Zhan Date: Thu, 25 Apr 2024 15:59:18 -0400 Subject: [PATCH 18/18] Pilot 4807: CLI differentiates the item path of downloading metadata between Project Folders and Name Folders (#138) * use keyword and prefix to config the path under project folder or name folder * fixup test cases * remove old comments * remove response is used before assignment --------- Co-authored-by: zhiren --- .../file_metadata/file_metadata_client.py | 12 +- app/services/project_manager/project.py | 2 +- .../test_file_metadata_client.py | 109 ++++++++---------- 3 files changed, 53 insertions(+), 70 deletions(-) diff --git a/app/services/file_manager/file_metadata/file_metadata_client.py b/app/services/file_manager/file_metadata/file_metadata_client.py index ad3833a3..fad9cc02 100644 --- a/app/services/file_manager/file_metadata/file_metadata_client.py +++ b/app/services/file_manager/file_metadata/file_metadata_client.py @@ -19,6 +19,7 @@ import app.services.logger_services.log_functions as logger import app.services.output_manager.message_handler as message_handler +from app.models.item import ItemType from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import customized_error_msg from app.utils.aggregated import get_attribute_template_by_id @@ -109,14 +110,15 @@ def download_file_metadata(self) -> List[Dict[str, Any]]: """ project_code, object_path = self.file_path.split('/', 1) + root_folder, object_path = object_path.split('/', 1) + root_type = ItemType.get_type_from_keyword(root_folder) + object_path = join(root_type.get_prefix_by_type(), object_path) item_res = search_item(project_code, self.zone, object_path) - # double check if the file is in shared folder if item_res.get('code') == 404: - item_res = search_item(project_code, self.zone, f'shared/{object_path}') - if item_res.get('code') == 404: - logger.error(f'Cannot find item {self.file_path} at {self.zone}.') - exit(1) + logger.error(f'Cannot find item {self.file_path} at {self.zone}.') + exit(1) + # filter out item metadata item_res = item_res.get('result', {}) extra_info = item_res.pop('extended', {}).get('extra') tags = extra_info.get('tags', []) diff --git a/app/services/project_manager/project.py b/app/services/project_manager/project.py index ec98c503..ef832bc0 100644 --- a/app/services/project_manager/project.py +++ b/app/services/project_manager/project.py @@ -48,4 +48,4 @@ def list_projects(self, page, page_size, order, order_by): else: SrvErrorHandler.default_handle(response.content, True) except Exception: - SrvErrorHandler.default_handle(response.content, True) + SrvErrorHandler.default_handle('Error when listing projects', True) diff --git a/tests/app/services/file_manager/file_metadata/test_file_metadata_client.py b/tests/app/services/file_manager/file_metadata/test_file_metadata_client.py index dafeeaac..05b72110 100644 --- a/tests/app/services/file_manager/file_metadata/test_file_metadata_client.py +++ b/tests/app/services/file_manager/file_metadata/test_file_metadata_client.py @@ -2,19 +2,30 @@ # # Contact Indoc Systems for any questions regarding the use of this source code. +import pytest + from app.configs.app_config import AppConfig +from app.models.item import ItemType from app.services.file_manager.file_metadata.file_metadata_client import FileMetaClient from tests.conftest import decoded_token -def test_file_metadata_client_get_detail_success(mocker, httpx_mock): +@pytest.mark.parametrize( + 'root_folder', + [ItemType.NAMEFOLDER, ItemType.SHAREDFOLDER], +) +def test_file_metadata_client_get_detail_success(mocker, httpx_mock, root_folder: ItemType): + file_name = 'test_file.txt' + project_code = 'project_code' item_info = { 'id': 'test', 'parent_id': 'test_parent', - 'parent_path': '', - 'name': 'admin', + 'parent_path': root_folder.get_prefix_by_type(), + 'name': file_name, 'zone': 0, 'status': 'ACTIVE', + 'container_code': project_code, + 'container_type': 'project', } tags = ['test'] attri_template_uid = 'template_uid' @@ -41,9 +52,11 @@ def test_file_metadata_client_get_detail_success(mocker, httpx_mock): return_value=None, ) - file_meta_client = FileMetaClient('zone', 'project_code/object_path', 'general', 'attr', 'tag') - assert file_meta_client.project_code == 'project_code' - assert file_meta_client.object_path == 'object_path' + file_meta_client = FileMetaClient( + 'zone', f'{project_code}/{root_folder.get_prefix_by_type()}/{file_name}', 'general', 'attr', 'tag' + ) + assert file_meta_client.project_code == project_code + assert file_meta_client.object_path == f'{root_folder.get_prefix_by_type()}/{file_name}' item_info, res_attributes, tags = file_meta_client.download_file_metadata() assert item_info == item_info @@ -51,14 +64,22 @@ def test_file_metadata_client_get_detail_success(mocker, httpx_mock): assert tags == tags -def test_file_metadata_client_get_detail_success_with_no_tag_attributes(mocker, httpx_mock): +@pytest.mark.parametrize( + 'root_folder', + [ItemType.NAMEFOLDER, ItemType.SHAREDFOLDER], +) +def test_file_metadata_client_get_detail_success_with_no_tag_attributes(mocker, root_folder: ItemType): + file_name = 'test_file.txt' + project_code = 'project_code' item_info = { 'id': 'test', 'parent_id': 'test_parent', - 'parent_path': '', - 'name': 'admin', + 'parent_path': root_folder.get_prefix_by_type(), + 'name': file_name, 'zone': 0, 'status': 'ACTIVE', + 'container_code': project_code, + 'container_type': 'project', } mocker.patch( @@ -76,9 +97,11 @@ def test_file_metadata_client_get_detail_success_with_no_tag_attributes(mocker, return_value=None, ) - file_meta_client = FileMetaClient('zone', 'project_code/object_path', 'general', 'attr', 'tag') - assert file_meta_client.project_code == 'project_code' - assert file_meta_client.object_path == 'object_path' + file_meta_client = FileMetaClient( + 'zone', f'{project_code}/{root_folder.get_prefix_by_type()}/{file_name}', 'general', 'attr', 'tag' + ) + assert file_meta_client.project_code == project_code + assert file_meta_client.object_path == f'{root_folder.get_prefix_by_type()}/{file_name}' item_info, res_attributes, tags = file_meta_client.download_file_metadata() assert item_info == item_info @@ -86,20 +109,11 @@ def test_file_metadata_client_get_detail_success_with_no_tag_attributes(mocker, assert tags == tags -def test_metadata_download_from_project_folder(mocker, httpx_mock): - item_info = { - 'id': 'test', - 'parent_id': 'test_parent', - 'parent_path': 'shared/path', - 'name': 'admin', - 'zone': 0, - 'status': 'ACTIVE', - } - tags = ['test'] - attri_template_uid = 'template_uid' - attri_template_name = 'template_name' - attributes = {attri_template_uid: {'attr_1': 'value'}} - +@pytest.mark.parametrize( + 'root_folder', + [ItemType.NAMEFOLDER, ItemType.SHAREDFOLDER], +) +def test_metadata_download_fail_when_file_doesnot_exist(mocker, capfd, root_folder: ItemType): mocker.patch( 'app.services.user_authentication.token_manager.SrvTokenManager.decode_access_token', return_value=decoded_token(), @@ -107,53 +121,20 @@ def test_metadata_download_from_project_folder(mocker, httpx_mock): search_mock = mocker.patch( 'app.services.file_manager.file_metadata.file_metadata_client.search_item', - ) - search_mock.side_effect = [ - {'result': {}, 'code': 404}, - {'result': {**item_info, 'extended': {'extra': {'tags': tags, 'attributes': attributes}}}}, - ] - httpx_mock.add_response( - url=AppConfig.Connections.url_portal + f'/v1/data/manifest/{attri_template_uid}', - method='GET', - json={'result': {'id': attri_template_uid, 'name': attri_template_name}}, + return_value={'result': {}, 'code': 404}, ) - mocker.patch( - 'app.services.file_manager.file_metadata.file_metadata_client.FileMetaClient.save_file_metadata', - return_value=None, + file_meta_client = FileMetaClient( + 'zone', f'project_code/{root_folder.get_prefix_by_type()}/file_name', 'general', 'attr', 'tag' ) - file_meta_client = FileMetaClient('zone', 'project_code/object_path', 'general', 'attr', 'tag') - assert file_meta_client.project_code == 'project_code' - assert file_meta_client.object_path == 'object_path' - - item_info, res_attributes, tags = file_meta_client.download_file_metadata() - assert item_info == item_info - assert res_attributes == {attri_template_name: attributes.get(attri_template_uid)} - assert tags == tags - assert search_mock.call_count == 2 - - -def test_metadata_download_fail_when_file_doesnot_exist(mocker, capfd): - mocker.patch( - 'app.services.user_authentication.token_manager.SrvTokenManager.decode_access_token', - return_value=decoded_token(), - ) - - search_mock = mocker.patch( - 'app.services.file_manager.file_metadata.file_metadata_client.search_item', - ) - search_mock.side_effect = [{'result': {}, 'code': 404}, {'result': {}, 'code': 404}] - - file_meta_client = FileMetaClient('zone', 'project_code/object_path', 'general', 'attr', 'tag') - try: file_meta_client.download_file_metadata() except SystemExit: - assert search_mock.call_count == 2 + assert search_mock.call_count == 1 out, _ = capfd.readouterr() - expect = 'Cannot find item project_code/object_path at zone.\n' + expect = f'Cannot find item project_code/{root_folder.get_prefix_by_type()}/file_name at zone.\n' assert out == expect else: AssertionError('SystemExit not raised')