def upload_node(self, node: TreeNode, parent_id: str = "LOCAL_ROOT"): """Carica un nodo, all'interno del parent passato""" headers = {"cookie": self.cookie} name = node.get_name() content = open(node.get_payload().path, "rb") updated_at = node.get_updated_at() created_at = node.get_payload().created_at multipart_form = { "command": "upload", "name": name, "content": content, "parent": self.get_user_id() + "/" + parent_id, "updated-at": updated_at, "created-at": created_at } response = requests.post(self.url_files, headers=headers, files=multipart_form) if response.ok: self.logger.info( f"Upload del file {name}, completato con successo") else: self.logger.info(f"Upload del file {name}, fallito") # alzo le eccezioni del caso self.check_status_code(response)
def __init__(self, tree: TreeNode, override_name: str = None): self._name = tree.get_name( ) if override_name is None else override_name self._node = tree self._files = [] self._dirs = [] self._path = tree.get_payload().path self.update_list_of_content()
def _test_tree_node(self, node_to_test: TreeNode, test_node: TreeNode): self.assertEqual(node_to_test.get_name(), test_node.get_name()) payload_to_test = node_to_test.get_payload() test_payload = test_node.get_payload() self.assertEqual(payload_to_test.id, test_payload.id) self.assertEqual(payload_to_test.type, test_payload.type) self.assertEqual(payload_to_test.updated_at, test_payload.updated_at) self.assertEqual(payload_to_test.created_at, test_payload.created_at) self.assertEqual(payload_to_test.path, test_payload.path)
def test_upload_folder_with_folder(self, mocked_fun): updated = 200 created = 100 test_node = TreeNode(Node("CLIENT_NODE", self.folder_name, Type.Folder, created, updated, self.path)) test_node.add_node(TreeNode(Node("CLIENT_NODE", self.file_name, Type.Folder, created, updated, self.path))) os_handler.upload_folder(test_node, self.path) self.assertEqual(mocked_fun.call_count, 2)
def upload_folder(node: TreeNode, parent_folder_id: str = "LOCAL_ROOT") -> None: """Il nodo rappresenta la cartella che non esiste nel server""" parent_folder_id = create_folder(node.get_name(), parent_folder_id) for _node in node.get_children(): if _node.is_directory(): upload_folder(_node, parent_folder_id) else: upload_file(_node, parent_folder_id)
def test_upload_folder_with_file(self, mocked_create, mocked_upload): updated = 200 created = 100 test_node = TreeNode(Node("CLIENT_NODE", self.folder_name, Type.Folder, created, updated, self.path)) test_node.add_node(TreeNode(Node("CLIENT_NODE", self.file_name, Type.File, created, updated, self.path))) os_handler.upload_folder(test_node, self.path) mocked_upload.assert_called_once() mocked_create.assert_called_once()
def test_download_folder_with_file(self, mock_1, mock_2, mock_3): updated = 200 created = 100 test_node = TreeNode(Node("CLIENT_NODE", self.folder_name, Type.Folder, created, updated, self.path)) test_node.add_node(TreeNode(Node("CLIENT_NODE", self.file_name, Type.File, created, updated, self.path))) x = os_handler.download_folder(test_node, self.path) self.assertEqual(x, [True]) mock_1.assert_called_once() mock_2.assert_called_once() mock_3.assert_called_once()
def _compareFiles(client: TreeNode, server: TreeNode) -> list: client_files = _get_only_files(client._children) server_files = _get_only_files(server._children) update_files: list = [] for cl_file in client_files: trovato = False for sr_file in server_files: if cl_file.get_name() == sr_file.get_name(): if cl_file.get_updated_at() > sr_file.get_updated_at(): update_files.append({ "node": cl_file, "id": server.get_payload().id, "action": Actions.CLIENT_UPDATE_FILE }) elif sr_file.get_updated_at() > cl_file.get_updated_at(): update_files.append({ "node": sr_file, "path": client.get_payload().path, "snap_last_update": cl_file.get_updated_at(), "action": Actions.SERVER_UPDATE_FILE }) trovato = True break if not trovato: # Il client ha un file che nel server non c'è update_files.append({ "node": cl_file, "id": server.get_payload().id, "action": Actions.CLIENT_NEW_FILE }) for sr_file in server_files: trovato = False for cl_file in client_files: if sr_file.get_name() == cl_file.get_name(): trovato = True if not trovato: # Il server ha un file che nel client non c'è update_files.append({ "node": sr_file, "path": client.get_payload().path, "action": Actions.SERVER_NEW_FILE }) return update_files
def test_download_folder_with_folder(self): created = 100 updated = 200 test_node = TreeNode(Node("CLIENT_NODE", self.folder_name, Type.Folder, created, updated, self.path)) test_node.add_node(TreeNode(Node("CLIENT_NODE", self.folder_name, Type.Folder, created, updated, self.path))) x = os_handler.download_folder(test_node, self.path) self.assertEqual(x, []) folder_path = os.path.join(self.path, self.folder_name) inner_folder_path = os.path.join(folder_path, self.folder_name) self.assertEqual(os.path.exists(folder_path), False) self.assertEqual(os.path.exists(inner_folder_path), False)
def download_file(node: TreeNode, path_folder: str) -> Optional[dict]: node_id = node.get_payload().id if settings_model.is_id_in_sync_list(node_id): quota_libera = settings_model.get_quota_libera() return network_model.download_node(node, path_folder, quota_libera) else: return None
def test_create_node_from_dict(self): _dict = _get_default_dict() test_node = TreeNode( Node(_dict["id"], _dict["name"], Type.File, _dict["created_at"] / 1000, _dict["updated_at"] / 1000)) node_to_test = tree_builder._create_node_from_dict(_dict) self._test_tree_node(node_to_test, test_node)
def get_tree_from_system(path: str, root_name: str = "ROOT", prev_node: TreeNode = None) -> TreeNode: """Funzione ricorsiva per costruire l'albero dato un path""" parent_node = _build_tree_node(path, root_name) for name in os.listdir(path): if name not in black_list: abs_path = os.path.join(path, name) if os.path.isdir(abs_path): get_tree_from_system(abs_path, name, parent_node) else: parent_node.add_node(_build_tree_node(abs_path, name)) if prev_node is not None: prev_node.add_node(parent_node) return parent_node
def test_get_tree_from_node_id(self, mocked_function): _dict = _get_default_dict() test_node = TreeNode( Node(_dict["id"], _dict["name"], Type.Folder, _dict["created_at"] / 1000, _dict["updated_at"] / 1000)) node_to_test = tree_builder.get_tree_from_node_id("test") mocked_function.assert_called_once() self._test_tree_node(node_to_test, test_node)
def test_build_tree_node(self): node_name = "prova" self.tree = tree_builder._build_tree_node(self.path, node_name) updated = int(os.stat(self.path).st_mtime) created = int(os.stat(self.path).st_ctime) test_node = TreeNode( Node("CLIENT_NODE", node_name, Type.Folder, created, updated, self.path)) self._test_tree_node(self.tree, test_node)
def _build_tree_node(path: str, name: str) -> TreeNode: """Costruisce un TreeNode a partire dal path""" id = "CLIENT_NODE" # name = os.path.basename(path) if not os.path.exists(path): raise FileNotFoundError() type = Type.Folder if os.path.isdir(path) else Type.File created_at = math.trunc(os.stat(path).st_ctime) updated_at = math.trunc(os.stat(path).st_mtime) return TreeNode(Node(id, name, type, created_at, updated_at, path=path))
def download_node(self, node: TreeNode, path_folder: str, quota_libera: float) -> dict: remote_node = self.api_implementation.get_content_from_node( node.get_payload().id) file_size = remote_node["getNode"]["size"] # Se ho spazio procedo al download if quota_libera > file_size: result = self.api_implementation.download_node(node, path_folder) return { "node_name": node.get_name(), "result": result, "type": "network_error" if not result else "" } return { "node_name": node.get_name(), "result": False, "type": "space_error" }
def test_common_strategy_client_new_file_id_not_exists(self, m1, m2): node_raw = { "action": Actions.CLIENT_NEW_FILE, "node": TreeNode(Node("a", "ciao.txt", Type.File, 100, 200, "a/ciao.txt")) } logger = default_code.FakeLogger() strategy.common_strategy(node_raw, logger) m1.assert_not_called() m2.assert_called_once()
def test_get_tree_from_system(self): self.tree = tree_builder.get_tree_from_system(self.path) updated = int(os.stat(self.path).st_mtime) created = int(os.stat(self.path).st_ctime) test_node = TreeNode( Node("CLIENT_NODE", "ROOT", Type.Folder, created, updated, self.path)) self._test_tree_node(self.tree, test_node) curr_dir_content = os.listdir(self.path) tree_childs = self.tree.get_children() tree_childs.reverse() for content in curr_dir_content: node = tree_childs.pop() file_path = os.path.join(self.path, content) created = int(os.stat(file_path).st_ctime) updated = int(os.stat(file_path).st_mtime) test_node = TreeNode( Node("CLIENT_NODE", content, Type.File, created, updated, file_path)) self._test_tree_node(node, test_node)
def check_node_in_nodelist(tree: TreeNode, file_node_list: list) -> bool: # Per velocizzarlo di più forse è meglio ordinare i children mettendo prima i files for node in tree.get_children(): if node.is_directory(): # Se la cartella analizzata ha un nodo positivo, # ritorna True altrimenti guardiamo gli altri nodi if check_node_in_nodelist(node, file_node_list): return True else: if node.get_payload().id in file_node_list: return True return False
def test_download_node_from_server_error(self, mocked_response, mocked_get_id): updated = 200 created = 100 test_node = TreeNode( Node("CLIENT_NODE", self.file_name, Type.Folder, created, updated, self.path)) try: self.api.download_node(test_node, self.path) except APIException as e: mocked_response.assert_called_once() mocked_get_id.assert_called_once() self.assertEqual(str(e), str(APIException()))
def test_download_node_from_server_ok(self, mocked_1, mocked_2): updated = 200 created = 100 test_node = TreeNode( Node("CLIENT_NODE", self.file_name, Type.Folder, created, updated, self.path)) result = self.api.download_node(test_node, self.path) self.assertEqual(result, True) mocked_1.assert_called_once() mocked_2.assert_called_once() file_path = os.path.join(self.path, self.file_name) self.assertTrue(os.path.exists(file_path)) self.assertEqual(os.path.getmtime(file_path), updated)
def test_upload_success(self, mocked_response, mocked_get_id): # creo file da leggere, potrei mockare anche la call # di lettura ma questo risulta piu facile ed indolore anche # se molto brutto full_path = os.path.join(self.path, self.file_name) with open(full_path, "w"): pass updated = 200 created = 100 test_node = TreeNode( Node("CLIENT_NODE", self.file_name, Type.Folder, created, updated, full_path)) self.assertIsNone(self.api.upload_node(test_node)) mocked_response.assert_called_once() mocked_get_id.assert_called_once()
def compareFolders(client: TreeNode, server: TreeNode) -> list: update_files: list = [] # Controllo prima SOLO i file update_files.extend(_compareFiles(client, server)) client_folders = _get_only_folders(client._children) server_folders = _get_only_folders(server._children) for cl_folder in client_folders: trovato = False for sr_folder in server_folders: if cl_folder.get_name() == sr_folder.get_name(): trovato = True update_files.extend(compareFolders(cl_folder, sr_folder)) if not trovato: # Il client ha un cartella che nel server non c'è update_files.append({ "node": cl_folder, "id": server.get_payload().id, "action": Actions.CLIENT_NEW_FOLDER }) for sr_folder in server_folders: trovato = False for cl_folder in client_folders: if sr_folder.get_name() == cl_folder.get_name(): trovato = True if not trovato: # Il server ha una cartella che nel client non c'è update_files.append({ "node": sr_folder, "path": client.get_payload().path, "action": Actions.SERVER_NEW_FOLDER }) return update_files
def download_folder(node: TreeNode, path: str) -> list[dict]: """Il nodo rappresenta la cartella che non esiste, ritorna i risultati dei download che sono stati fatti""" # Controlliamo se la cartella ha dei nodi da scaricare file_node_list = settings_model.get_sync_list() res = check_node_in_nodelist(node, file_node_list) download_operations_list = [] if res: path_folder = os.path.join(path, node.get_name()) os.mkdir(path_folder) for _node in node.get_children(): if _node.is_directory(): result = download_folder(_node, path_folder) download_operations_list.extend(result) else: result = download_file(_node, path_folder) if result is not None: download_operations_list.append(result) return download_operations_list
def test_upload_error(self, mocked_response, mocked_get_id): # creo file da leggere, potrei mockare anche la call # di lettura ma questo risulta piu facile ed indolore anche # se molto brutto full_path = os.path.join(self.path, self.file_name) with open(full_path, "w"): pass updated = 200 created = 100 test_node = TreeNode( Node("CLIENT_NODE", self.file_name, Type.Folder, created, updated, full_path)) try: self.api.upload_node(test_node) except APIException as e: mocked_response.assert_called_once() mocked_get_id.assert_called_once() self.assertEqual(str(e), str(APIException()))
def _create_node_from_dict(dict: str) -> TreeNode: """Costruisce un TreeNode a partire dal dict""" id = dict["id"] name = dict["name"] type = Type.File if dict["type"] == "File" else Type.Folder created_at = math.trunc(dict["created_at"] / 1000) updated_at = math.trunc(dict["updated_at"] / 1000) size = 0 if type == Type.Folder else dict["size"] last_editor = None if dict["last_editor"] is None else dict["last_editor"][ "email"] node = Node(id, name, type, created_at, updated_at, size=size, last_editor=last_editor) return TreeNode(node)
def get_data(self) -> Tuple[list[RemoteFile], list[RemoteDirectory]]: list_of_files = [] list_of_dirs = [] try: for entry in self.get_current_tree().get_children(): if entry.get_payload().type == Type.File: list_of_files.append(RemoteFile(entry)) else: list_of_dirs.append(RemoteDirectory(entry)) if self.folder_queue[-1] != "LOCAL_ROOT": previous_folder = RemoteDirectory( TreeNode( Node(self.folder_queue[-1], '..', Type.Folder, None, None))) list_of_dirs.insert(0, previous_folder) except APIException: return None return list_of_files, list_of_dirs
def download_node(self, node: TreeNode, path: str) -> bool: """Il TreeNode viene scaricato e salvato nel path, ritorna un bool a seconda dell'esito""" headers = {"cookie": self.cookie} payload = node.get_payload() url = f"{self.url_files}{self.get_user_id()}/{payload.id}" response = requests.get(url, headers=headers) if response.ok: path = os.path.join(path, payload.name) with open(path, "wb") as fh: fh.write(response.content) # Cambiare la data di creazione sembra non funzionare os.utime(path, (payload.created_at, payload.updated_at)) self.logger.info( f"Download del file {payload.name}, completato con successo") return True else: self.logger.info(f"Download del file {payload.name}, fallito") # alzo le eccezioni del caso self.check_status_code(response) return False
def setUp(self): """Metodo che viene chiamato prima di ogni metodo""" self.files: list[Node] = [ Node("CLIENT_NODE", "Test", Type.File, 1000, 1022, "root/file.txt"), Node("CLIENT_NODE", "Test2", Type.File, 1000, 1024, "root/file2.txt"), Node("CLIENT_NODE", "Test3", Type.File, 1000, 1026, "root/root2/file3.txt"), ] self.folders: list[Node] = [ Node("CLIENT_NODE", "Test Folder", Type.Folder, 1000, 1022, "root"), Node("CLIENT_NODE", "Test Folder2", Type.Folder, 1000, 1025, "root/root2"), ] self.tree_node = TreeNode(self.folders[0]) self.tree_node.add_node(TreeNode(self.files[0])) self.tree_node.add_node(TreeNode(self.files[1])) self.tree_node_sub = TreeNode(self.folders[1]) self.tree_node_sub.add_node(TreeNode(self.files[2])) self.tree_node.add_node(self.tree_node_sub)
def __init__(self, node: TreeNode): super().__init__(node) self._path = node.get_payload().path self._size = SettingsModel.convert_size( os.stat(node.get_payload().path).st_size)