saviialib 0.9.0__tar.gz → 0.10.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of saviialib might be problematic. Click here for more details.
- {saviialib-0.9.0 → saviialib-0.10.1}/PKG-INFO +1 -1
- {saviialib-0.9.0 → saviialib-0.10.1}/pyproject.toml +1 -1
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/api/epii_api_types.py +3 -0
- saviialib-0.10.1/src/saviialib/libs/directory_client/__init__.py +4 -0
- saviialib-0.10.1/src/saviialib/libs/directory_client/client/os_client.py +23 -0
- saviialib-0.10.1/src/saviialib/libs/directory_client/directory_client.py +28 -0
- saviialib-0.10.1/src/saviialib/libs/directory_client/directory_client_contract.py +19 -0
- saviialib-0.10.1/src/saviialib/libs/directory_client/types/directory_client_types.py +6 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/__init__.py +2 -2
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/clients/aiofiles_client.py +12 -3
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/types/files_client_types.py +2 -1
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/api.py +3 -1
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/upload_backup_to_sharepoint.py +2 -1
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py +1 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py +2 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py +77 -45
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/utils/upload_backup_to_sharepoint_utils.py +10 -14
- {saviialib-0.9.0 → saviialib-0.10.1}/LICENSE +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/README.md +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/api/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/api/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/api/epii_api_error_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/common/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/common/common_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/files_client.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/files_client_contract.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/clients/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/clients/aioftp_client.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/ftp_client.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/ftp_client_contract.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/types/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/types/ftp_client_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/sharepoint_client/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/sharepoint_client/clients/sharepoint_rest_api.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/sharepoint_client/sharepoint_client.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/sharepoint_client/sharepoint_client_contract.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/sharepoint_client/types/sharepoint_client_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/zero_dependency/utils/datetime_utils.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/types/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/types/update_thies_data_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/types/upload_backup_to_sharepoint_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/update_thies_data.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/constants/update_thies_data_constants.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/types/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/types/update_thies_data_types.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/update_thies_data.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/utils/__init__.py +0 -0
- {saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/utils/update_thies_data_utils.py +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
+
from logging import Logger
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
@dataclass
|
|
@@ -27,6 +28,7 @@ class EpiiAPIConfig:
|
|
|
27
28
|
sharepoint_tenant_id: str
|
|
28
29
|
sharepoint_tenant_name: str
|
|
29
30
|
sharepoint_site_name: str
|
|
31
|
+
logger: Logger
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
@dataclass
|
|
@@ -80,3 +82,4 @@ class EpiiSharepointBackupConfig:
|
|
|
80
82
|
sharepoint_site_name: str
|
|
81
83
|
local_backup_source_path: str
|
|
82
84
|
destination_folders: str
|
|
85
|
+
logger: Logger
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from saviialib.libs.directory_client.directory_client_contract import (
|
|
2
|
+
DirectoryClientContract,
|
|
3
|
+
)
|
|
4
|
+
import os
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class OsClient(DirectoryClientContract):
|
|
9
|
+
@staticmethod
|
|
10
|
+
def join_paths(*paths: str) -> str:
|
|
11
|
+
return os.path.join(*paths)
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
async def path_exists(path: str) -> bool:
|
|
15
|
+
return await asyncio.to_thread(os.path.exists, path)
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
async def listdir(path: str) -> list:
|
|
19
|
+
return await asyncio.to_thread(os.listdir, path)
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
async def isdir(path: str) -> list:
|
|
23
|
+
return await asyncio.to_thread(os.path.isdir, path)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from .client.os_client import OsClient
|
|
2
|
+
from .directory_client_contract import DirectoryClientContract
|
|
3
|
+
from .types.directory_client_types import DirectoryClientArgs
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DirectoryClient(DirectoryClientContract):
|
|
7
|
+
CLIENTS = {"os_client"}
|
|
8
|
+
|
|
9
|
+
def __init__(self, args: DirectoryClientArgs) -> None:
|
|
10
|
+
if args.client_name not in DirectoryClient.CLIENTS:
|
|
11
|
+
msg = f"Unsupported client {args.client_name}"
|
|
12
|
+
raise KeyError(msg)
|
|
13
|
+
|
|
14
|
+
if args.client_name == "os_client":
|
|
15
|
+
self.client_obj = OsClient()
|
|
16
|
+
self.client_name = args.client_name
|
|
17
|
+
|
|
18
|
+
def join_paths(self, *paths: str) -> str:
|
|
19
|
+
return self.client_obj.join_paths(*paths)
|
|
20
|
+
|
|
21
|
+
async def path_exists(self, path: str) -> bool:
|
|
22
|
+
return await self.client_obj.path_exists(path)
|
|
23
|
+
|
|
24
|
+
async def listdir(self, path: str) -> list:
|
|
25
|
+
return await self.client_obj.listdir(path)
|
|
26
|
+
|
|
27
|
+
async def isdir(self, path: str) -> bool:
|
|
28
|
+
return await self.client_obj.isdir(path)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DirectoryClientContract(ABC):
|
|
5
|
+
@abstractmethod
|
|
6
|
+
def join_paths(self, *paths: str) -> str:
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
async def path_exists(self, path: str) -> bool:
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
@abstractmethod
|
|
14
|
+
async def listdir(self, path: str) -> list:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
async def isdir(self, path) -> bool:
|
|
19
|
+
pass
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
from .files_client import FilesClient
|
|
2
|
-
from .types.files_client_types import FilesClientInitArgs, ReadArgs
|
|
2
|
+
from .types.files_client_types import FilesClientInitArgs, ReadArgs, WriteArgs
|
|
3
3
|
|
|
4
|
-
__all__ = ["FilesClient", "FilesClientInitArgs", "ReadArgs"]
|
|
4
|
+
__all__ = ["FilesClient", "FilesClientInitArgs", "ReadArgs", "WriteArgs"]
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/clients/aiofiles_client.py
RENAMED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import aiofiles
|
|
2
|
-
|
|
2
|
+
from saviialib.libs.directory_client.directory_client import (
|
|
3
|
+
DirectoryClient,
|
|
4
|
+
DirectoryClientArgs,
|
|
5
|
+
)
|
|
3
6
|
from saviialib.libs.files_client.files_client_contract import FilesClientContract
|
|
4
7
|
from saviialib.libs.files_client.types.files_client_types import (
|
|
5
8
|
FilesClientInitArgs,
|
|
@@ -10,7 +13,7 @@ from saviialib.libs.files_client.types.files_client_types import (
|
|
|
10
13
|
|
|
11
14
|
class AioFilesClient(FilesClientContract):
|
|
12
15
|
def __init__(self, args: FilesClientInitArgs):
|
|
13
|
-
|
|
16
|
+
self.dir_client = DirectoryClient(DirectoryClientArgs(client_name="os_client"))
|
|
14
17
|
|
|
15
18
|
async def read(self, args: ReadArgs) -> str | bytes:
|
|
16
19
|
encoding = None if args.mode == "rb" else args.encoding
|
|
@@ -18,4 +21,10 @@ class AioFilesClient(FilesClientContract):
|
|
|
18
21
|
return await file.read()
|
|
19
22
|
|
|
20
23
|
async def write(self, args: WriteArgs) -> None:
|
|
21
|
-
|
|
24
|
+
file_path = (
|
|
25
|
+
self.dir_client.join_paths(args.destination_path, args.file_name)
|
|
26
|
+
if args.destination_path
|
|
27
|
+
else args.file_name
|
|
28
|
+
)
|
|
29
|
+
async with aiofiles.open(file_path, args.mode) as file:
|
|
30
|
+
await file.write(args.file_content)
|
|
@@ -28,6 +28,7 @@ class EpiiAPI:
|
|
|
28
28
|
self.sharepoint_tenant_id = config.sharepoint_tenant_id
|
|
29
29
|
self.sharepoint_tenant_name = config.sharepoint_tenant_name
|
|
30
30
|
self.sharepoint_site_name = config.sharepoint_site_name
|
|
31
|
+
self.logger = config.logger
|
|
31
32
|
|
|
32
33
|
async def update_thies_data(self) -> Dict[str, Any]:
|
|
33
34
|
"""
|
|
@@ -70,7 +71,8 @@ class EpiiAPI:
|
|
|
70
71
|
sharepoint_tenant_id=self.sharepoint_tenant_id,
|
|
71
72
|
sharepoint_tenant_name=self.sharepoint_tenant_name,
|
|
72
73
|
local_backup_source_path=local_backup_source_path,
|
|
73
|
-
destination_folders=destination_folders
|
|
74
|
+
destination_folders=destination_folders,
|
|
75
|
+
logger=self.logger,
|
|
74
76
|
)
|
|
75
77
|
|
|
76
78
|
controller = UploadBackupToSharepointController(
|
|
@@ -34,7 +34,8 @@ class UploadBackupToSharepointController:
|
|
|
34
34
|
sharepoint_tenant_id=input.config.sharepoint_tenant_id,
|
|
35
35
|
),
|
|
36
36
|
local_backup_source_path=input.config.local_backup_source_path,
|
|
37
|
-
destination_folders=input.config.destination_folders
|
|
37
|
+
destination_folders=input.config.destination_folders,
|
|
38
|
+
logger=input.config.logger,
|
|
38
39
|
)
|
|
39
40
|
)
|
|
40
41
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from saviialib.general_types.api.epii_api_types import SharepointConfig
|
|
3
|
+
from logging import Logger
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
@dataclass
|
|
@@ -7,3 +8,4 @@ class UploadBackupToSharepointUseCaseInput:
|
|
|
7
8
|
sharepoint_config: SharepointConfig
|
|
8
9
|
local_backup_source_path: str
|
|
9
10
|
destination_folders: dict
|
|
11
|
+
logger: Logger
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import os
|
|
3
2
|
from time import time
|
|
3
|
+
from logging import Logger
|
|
4
4
|
import saviialib.services.epii.use_cases.constants.upload_backup_to_sharepoint_constants as c
|
|
5
5
|
from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
6
6
|
BackupEmptyError,
|
|
@@ -10,7 +10,13 @@ from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
|
10
10
|
from saviialib.general_types.error_types.common import (
|
|
11
11
|
SharepointClientError,
|
|
12
12
|
)
|
|
13
|
-
from saviialib.libs.
|
|
13
|
+
from saviialib.libs.directory_client import DirectoryClient, DirectoryClientArgs
|
|
14
|
+
from saviialib.libs.files_client import (
|
|
15
|
+
FilesClient,
|
|
16
|
+
FilesClientInitArgs,
|
|
17
|
+
ReadArgs,
|
|
18
|
+
WriteArgs,
|
|
19
|
+
)
|
|
14
20
|
from saviialib.libs.sharepoint_client import (
|
|
15
21
|
SharepointClient,
|
|
16
22
|
SharepointClientInitArgs,
|
|
@@ -19,7 +25,6 @@ from saviialib.libs.sharepoint_client import (
|
|
|
19
25
|
from saviialib.services.epii.utils.upload_backup_to_sharepoint_utils import (
|
|
20
26
|
calculate_percentage_uploaded,
|
|
21
27
|
count_files_in_directory,
|
|
22
|
-
directory_exists,
|
|
23
28
|
extract_error_message,
|
|
24
29
|
parse_execute_response,
|
|
25
30
|
show_upload_result,
|
|
@@ -28,7 +33,6 @@ from saviialib.services.epii.utils.upload_backup_to_sharepoint_utils import (
|
|
|
28
33
|
from .types.upload_backup_to_sharepoint_types import (
|
|
29
34
|
UploadBackupToSharepointUseCaseInput,
|
|
30
35
|
)
|
|
31
|
-
from .constants.upload_backup_to_sharepoint_constants import LOGGER
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
class UploadBackupToSharepointUsecase:
|
|
@@ -36,35 +40,48 @@ class UploadBackupToSharepointUsecase:
|
|
|
36
40
|
self.sharepoint_config = input.sharepoint_config
|
|
37
41
|
self.local_backup_source_path = input.local_backup_source_path
|
|
38
42
|
self.destination_folders = input.destination_folders
|
|
39
|
-
self.grouped_files_by_folder = self._extract_filesnames_by_folder()
|
|
40
43
|
self.files_client = self._initialize_files_client()
|
|
41
|
-
self.
|
|
42
|
-
len(files) for files in self.grouped_files_by_folder.values()
|
|
43
|
-
)
|
|
44
|
+
self.dir_client = self._initialize_directory_client()
|
|
44
45
|
self.log_history = []
|
|
46
|
+
self.grouped_files_by_folder = None
|
|
47
|
+
self.total_files = None
|
|
48
|
+
self.logger: Logger = input.logger
|
|
49
|
+
|
|
50
|
+
def _initialize_directory_client(self):
|
|
51
|
+
return DirectoryClient(DirectoryClientArgs(client_name="os_client"))
|
|
45
52
|
|
|
46
53
|
def _initialize_files_client(self):
|
|
47
54
|
return FilesClient(FilesClientInitArgs(client_name="aiofiles_client"))
|
|
48
55
|
|
|
49
|
-
def _extract_filesnames_by_folder(self) -> dict[str, list[str]]:
|
|
56
|
+
async def _extract_filesnames_by_folder(self) -> dict[str, list[str]]:
|
|
50
57
|
"""Groups files by their parent folder."""
|
|
51
|
-
|
|
58
|
+
backup_folder_exists = await self.dir_client.path_exists(
|
|
59
|
+
self.local_backup_source_path
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if not backup_folder_exists:
|
|
52
63
|
return {}
|
|
64
|
+
folder_names = await self.dir_client.listdir(self.local_backup_source_path)
|
|
53
65
|
return {
|
|
54
66
|
folder_name: [
|
|
55
67
|
file_name
|
|
56
|
-
for file_name in
|
|
57
|
-
|
|
68
|
+
for file_name in await self.dir_client.listdir(
|
|
69
|
+
self.dir_client.join_paths(
|
|
70
|
+
self.local_backup_source_path, folder_name
|
|
71
|
+
)
|
|
58
72
|
)
|
|
59
73
|
]
|
|
60
|
-
for folder_name in
|
|
74
|
+
for folder_name in folder_names
|
|
61
75
|
}
|
|
62
76
|
|
|
63
|
-
def _save_log_history(self) -> None:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
async def _save_log_history(self) -> None:
|
|
78
|
+
await self.files_client.write(
|
|
79
|
+
WriteArgs(
|
|
80
|
+
file_name="BACKUP_LOG_HISTORY.log",
|
|
81
|
+
file_content="\n".join(self.log_history),
|
|
82
|
+
mode="w",
|
|
83
|
+
)
|
|
84
|
+
)
|
|
68
85
|
|
|
69
86
|
async def export_file_to_sharepoint(
|
|
70
87
|
self, folder_name: str, file_name: str, file_content: bytes
|
|
@@ -84,7 +101,9 @@ class UploadBackupToSharepointUsecase:
|
|
|
84
101
|
|
|
85
102
|
async with sharepoint_client:
|
|
86
103
|
try:
|
|
87
|
-
destination_folder = self.destination_folders.get(
|
|
104
|
+
destination_folder = self.destination_folders.get(
|
|
105
|
+
folder_name, folder_name
|
|
106
|
+
)
|
|
88
107
|
folder_url = f"{c.SHAREPOINT_BASE_URL}/{destination_folder}"
|
|
89
108
|
args = SpUploadFileArgs(
|
|
90
109
|
folder_relative_url=folder_url,
|
|
@@ -99,20 +118,22 @@ class UploadBackupToSharepointUsecase:
|
|
|
99
118
|
|
|
100
119
|
return uploaded, error_message
|
|
101
120
|
|
|
102
|
-
async def
|
|
121
|
+
async def _upload_and_log_progress_task(self, folder_name, file_name) -> dict:
|
|
103
122
|
"""Task for uploads a file and logs progress."""
|
|
104
123
|
uploading_message = (
|
|
105
124
|
f"[BACKUP] Uploading file '{file_name}' from '{folder_name}' "
|
|
106
125
|
)
|
|
107
126
|
self.log_history.append(uploading_message)
|
|
108
|
-
|
|
109
|
-
file_path =
|
|
127
|
+
self.logger.debug(uploading_message)
|
|
128
|
+
file_path = self.dir_client.join_paths(
|
|
129
|
+
self.local_backup_source_path, folder_name, file_name
|
|
130
|
+
)
|
|
110
131
|
file_content = await self.files_client.read(ReadArgs(file_path, mode="rb"))
|
|
111
132
|
uploaded, error_message = await self.export_file_to_sharepoint(
|
|
112
133
|
folder_name, file_name, file_content
|
|
113
134
|
)
|
|
114
135
|
result_message = show_upload_result(uploaded, file_name)
|
|
115
|
-
|
|
136
|
+
self.logger.debug(result_message)
|
|
116
137
|
self.log_history.append(result_message)
|
|
117
138
|
return {
|
|
118
139
|
"parent_folder": folder_name,
|
|
@@ -128,42 +149,55 @@ class UploadBackupToSharepointUsecase:
|
|
|
128
149
|
f"[BACKUP] Retrying upload for {len(failed_files)} failed files... 🚨"
|
|
129
150
|
)
|
|
130
151
|
self.log_history.append(retry_message)
|
|
131
|
-
|
|
152
|
+
self.logger.debug(retry_message)
|
|
132
153
|
for file in failed_files:
|
|
133
154
|
tasks.append(
|
|
134
|
-
self.
|
|
155
|
+
self._upload_and_log_progress_task(
|
|
135
156
|
file["parent_folder"], file["file_name"]
|
|
136
157
|
)
|
|
137
158
|
)
|
|
138
159
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
139
160
|
success = calculate_percentage_uploaded(results, self.total_files)
|
|
140
161
|
if success < 100.0:
|
|
141
|
-
raise BackupUploadError(
|
|
162
|
+
raise BackupUploadError(
|
|
163
|
+
reason=extract_error_message(self.logger, results, success)
|
|
164
|
+
)
|
|
142
165
|
else:
|
|
143
166
|
successful_upload_retry = (
|
|
144
167
|
"[BACKUP] All files uploaded successfully after retry."
|
|
145
168
|
)
|
|
146
169
|
self.log_history.append(successful_upload_retry)
|
|
147
|
-
|
|
148
|
-
self._save_log_history()
|
|
170
|
+
self.logger.debug(successful_upload_retry)
|
|
171
|
+
await self._save_log_history()
|
|
149
172
|
return parse_execute_response(results)
|
|
150
173
|
|
|
151
174
|
async def execute(self):
|
|
152
175
|
"""Exports all files from the local backup folder to SharePoint cloud."""
|
|
176
|
+
self.grouped_files_by_folder = await self._extract_filesnames_by_folder()
|
|
177
|
+
self.total_files = sum(
|
|
178
|
+
len(files) for files in self.grouped_files_by_folder.values()
|
|
179
|
+
)
|
|
153
180
|
tasks = []
|
|
154
181
|
start_time = time()
|
|
155
|
-
|
|
182
|
+
|
|
156
183
|
# Check if the local path exists in the main directory
|
|
157
|
-
if not
|
|
184
|
+
if not await self.dir_client.path_exists(self.local_backup_source_path):
|
|
158
185
|
raise BackupSourcePathError(
|
|
159
186
|
reason=f"'{self.local_backup_source_path}' doesn't exist."
|
|
160
187
|
)
|
|
161
188
|
|
|
162
189
|
# Check if the current folder only have files.
|
|
163
|
-
|
|
190
|
+
items = [
|
|
191
|
+
item
|
|
192
|
+
for item in await self.dir_client.listdir(self.local_backup_source_path)
|
|
193
|
+
]
|
|
194
|
+
for item in items:
|
|
164
195
|
folder_included = item in self.destination_folders.keys()
|
|
165
|
-
is_file = not
|
|
166
|
-
|
|
196
|
+
is_file = not await self.dir_client.isdir(
|
|
197
|
+
self.dir_client.join_paths(self.local_backup_source_path, item)
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if not folder_included and not is_file:
|
|
167
201
|
raise BackupSourcePathError(
|
|
168
202
|
reason=(
|
|
169
203
|
f"'{item}' must be included in the destination folders dictionary",
|
|
@@ -171,36 +205,34 @@ class UploadBackupToSharepointUsecase:
|
|
|
171
205
|
)
|
|
172
206
|
elif folder_included and is_file:
|
|
173
207
|
print(folder_included, is_file)
|
|
174
|
-
raise BackupSourcePathError(
|
|
175
|
-
|
|
176
|
-
f"'{item}' must be a directory.",
|
|
177
|
-
)
|
|
178
|
-
)
|
|
179
|
-
|
|
208
|
+
raise BackupSourcePathError(reason=(f"'{item}' must be a directory.",))
|
|
209
|
+
|
|
180
210
|
if self.total_files == 0:
|
|
181
211
|
no_files_message = (
|
|
182
212
|
f"[BACKUP] {self.local_backup_source_path} has no files ⚠️"
|
|
183
213
|
)
|
|
184
214
|
self.log_history.append(no_files_message)
|
|
185
|
-
|
|
215
|
+
self.logger.debug(no_files_message)
|
|
186
216
|
raise BackupEmptyError
|
|
187
217
|
# Create task for each file stored in the the local backup folder.
|
|
188
218
|
for folder_name in self.grouped_files_by_folder:
|
|
189
219
|
if (
|
|
190
|
-
count_files_in_directory(
|
|
220
|
+
await count_files_in_directory(
|
|
221
|
+
self.local_backup_source_path, folder_name
|
|
222
|
+
)
|
|
191
223
|
== 0
|
|
192
224
|
):
|
|
193
225
|
empty_folder_message = f"[BACKUP] The folder '{folder_name}' is empty ⚠️"
|
|
194
|
-
|
|
226
|
+
self.logger.debug(empty_folder_message)
|
|
195
227
|
self.log_history.append(empty_folder_message)
|
|
196
228
|
continue
|
|
197
229
|
extracting_files_message = (
|
|
198
230
|
"[BACKUP]" + f" Extracting files from '{folder_name} ".center(15, "*")
|
|
199
231
|
)
|
|
200
232
|
self.log_history.append(extracting_files_message)
|
|
201
|
-
|
|
233
|
+
self.logger.debug(extracting_files_message)
|
|
202
234
|
for file_name in self.grouped_files_by_folder[folder_name]:
|
|
203
|
-
tasks.append(self.
|
|
235
|
+
tasks.append(self._upload_and_log_progress_task(folder_name, file_name))
|
|
204
236
|
|
|
205
237
|
# Execution of multiple asynchronous tasks for files migration.
|
|
206
238
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
@@ -220,5 +252,5 @@ class UploadBackupToSharepointUsecase:
|
|
|
220
252
|
)
|
|
221
253
|
self.log_history.append(finished_backup_message)
|
|
222
254
|
|
|
223
|
-
self._save_log_history()
|
|
255
|
+
await self._save_log_history()
|
|
224
256
|
return parse_execute_response(results)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import re
|
|
2
|
+
from logging import Logger
|
|
2
3
|
from typing import List, Dict, Optional
|
|
3
|
-
import os
|
|
4
4
|
from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
5
5
|
BackupSourcePathError,
|
|
6
6
|
)
|
|
7
|
-
from saviialib.
|
|
8
|
-
|
|
9
|
-
)
|
|
7
|
+
from saviialib.libs.directory_client import DirectoryClient, DirectoryClientArgs
|
|
8
|
+
|
|
9
|
+
dir_client = DirectoryClient(DirectoryClientArgs(client_name="os_client"))
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def extract_error_information(error: str) -> Optional[Dict[str, str]]:
|
|
@@ -29,8 +29,8 @@ def explain_status_code(status_code: int) -> str:
|
|
|
29
29
|
return explanations.get(status_code, "Unknown error occurred.")
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def extract_error_message(results: List[Dict], success: float) -> str:
|
|
33
|
-
|
|
32
|
+
def extract_error_message(logger: Logger, results: List[Dict], success: float) -> str:
|
|
33
|
+
logger.info(
|
|
34
34
|
"[BACKUP] Not all files uploaded ⚠️\n"
|
|
35
35
|
f"[BACKUP] Files failed to upload: {(1 - success):.2%}"
|
|
36
36
|
)
|
|
@@ -58,9 +58,9 @@ def extract_error_message(results: List[Dict], success: float) -> str:
|
|
|
58
58
|
|
|
59
59
|
# Summary
|
|
60
60
|
for code, items in grouped_errors.items():
|
|
61
|
-
|
|
61
|
+
logger.info(f"[BACKUP] Status code {code} - {explain_status_code(int(code))}")
|
|
62
62
|
for item in items:
|
|
63
|
-
|
|
63
|
+
logger.info(
|
|
64
64
|
f"[BACKUP] File {item['file_name']}, url: {item['url']}, message: {item['message']}"
|
|
65
65
|
)
|
|
66
66
|
|
|
@@ -93,9 +93,5 @@ def calculate_percentage_uploaded(results: List[Dict], total_files: int) -> floa
|
|
|
93
93
|
return (uploaded_count / total_files) * 100 if total_files > 0 else 0
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
def
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def count_files_in_directory(path: str, folder_name: str) -> int:
|
|
101
|
-
return len(os.listdir(os.path.join(path, folder_name)))
|
|
96
|
+
async def count_files_in_directory(path: str, folder_name: str) -> int:
|
|
97
|
+
return len(await dir_client.listdir(dir_client.join_paths(path, folder_name)))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/api/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/common/__init__.py
RENAMED
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/general_types/error_types/common/common_types.py
RENAMED
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/files_client/files_client_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/ftp_client/types/ftp_client_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/sharepoint_client/sharepoint_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/libs/zero_dependency/utils/datetime_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/controllers/update_thies_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/use_cases/update_thies_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{saviialib-0.9.0 → saviialib-0.10.1}/src/saviialib/services/epii/utils/update_thies_data_utils.py
RENAMED
|
File without changes
|