saviialib 0.9.1__py3-none-any.whl → 0.10.1__py3-none-any.whl
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/general_types/api/epii_api_types.py +3 -0
- saviialib/libs/directory_client/__init__.py +4 -0
- saviialib/libs/directory_client/client/os_client.py +23 -0
- saviialib/libs/directory_client/directory_client.py +28 -0
- saviialib/libs/directory_client/directory_client_contract.py +19 -0
- saviialib/libs/directory_client/types/directory_client_types.py +6 -0
- saviialib/libs/files_client/__init__.py +2 -2
- saviialib/libs/files_client/clients/aiofiles_client.py +12 -3
- saviialib/libs/files_client/types/files_client_types.py +2 -1
- saviialib/services/epii/api.py +3 -1
- saviialib/services/epii/controllers/upload_backup_to_sharepoint.py +2 -1
- saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py +1 -0
- saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py +2 -0
- saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py +51 -36
- saviialib/services/epii/utils/upload_backup_to_sharepoint_utils.py +9 -14
- {saviialib-0.9.1.dist-info → saviialib-0.10.1.dist-info}/METADATA +1 -1
- {saviialib-0.9.1.dist-info → saviialib-0.10.1.dist-info}/RECORD +19 -14
- {saviialib-0.9.1.dist-info → saviialib-0.10.1.dist-info}/LICENSE +0 -0
- {saviialib-0.9.1.dist-info → saviialib-0.10.1.dist-info}/WHEEL +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"]
|
|
@@ -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)
|
saviialib/services/epii/api.py
CHANGED
|
@@ -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:
|
|
@@ -37,38 +41,47 @@ class UploadBackupToSharepointUsecase:
|
|
|
37
41
|
self.local_backup_source_path = input.local_backup_source_path
|
|
38
42
|
self.destination_folders = input.destination_folders
|
|
39
43
|
self.files_client = self._initialize_files_client()
|
|
44
|
+
self.dir_client = self._initialize_directory_client()
|
|
40
45
|
self.log_history = []
|
|
41
46
|
self.grouped_files_by_folder = None
|
|
42
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"))
|
|
43
52
|
|
|
44
53
|
def _initialize_files_client(self):
|
|
45
54
|
return FilesClient(FilesClientInitArgs(client_name="aiofiles_client"))
|
|
46
55
|
|
|
47
56
|
async def _extract_filesnames_by_folder(self) -> dict[str, list[str]]:
|
|
48
57
|
"""Groups files by their parent folder."""
|
|
49
|
-
backup_folder_exists = await
|
|
50
|
-
|
|
58
|
+
backup_folder_exists = await self.dir_client.path_exists(
|
|
59
|
+
self.local_backup_source_path
|
|
51
60
|
)
|
|
61
|
+
|
|
52
62
|
if not backup_folder_exists:
|
|
53
63
|
return {}
|
|
54
|
-
folder_names = await
|
|
55
|
-
os.listdir, self.local_backup_source_path
|
|
56
|
-
)
|
|
64
|
+
folder_names = await self.dir_client.listdir(self.local_backup_source_path)
|
|
57
65
|
return {
|
|
58
66
|
folder_name: [
|
|
59
67
|
file_name
|
|
60
|
-
for file_name in await
|
|
61
|
-
|
|
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
|
+
)
|
|
62
72
|
)
|
|
63
73
|
]
|
|
64
74
|
for folder_name in folder_names
|
|
65
75
|
}
|
|
66
76
|
|
|
67
|
-
def _save_log_history(self) -> None:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
+
)
|
|
72
85
|
|
|
73
86
|
async def export_file_to_sharepoint(
|
|
74
87
|
self, folder_name: str, file_name: str, file_content: bytes
|
|
@@ -105,20 +118,22 @@ class UploadBackupToSharepointUsecase:
|
|
|
105
118
|
|
|
106
119
|
return uploaded, error_message
|
|
107
120
|
|
|
108
|
-
async def
|
|
121
|
+
async def _upload_and_log_progress_task(self, folder_name, file_name) -> dict:
|
|
109
122
|
"""Task for uploads a file and logs progress."""
|
|
110
123
|
uploading_message = (
|
|
111
124
|
f"[BACKUP] Uploading file '{file_name}' from '{folder_name}' "
|
|
112
125
|
)
|
|
113
126
|
self.log_history.append(uploading_message)
|
|
114
|
-
|
|
115
|
-
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
|
+
)
|
|
116
131
|
file_content = await self.files_client.read(ReadArgs(file_path, mode="rb"))
|
|
117
132
|
uploaded, error_message = await self.export_file_to_sharepoint(
|
|
118
133
|
folder_name, file_name, file_content
|
|
119
134
|
)
|
|
120
135
|
result_message = show_upload_result(uploaded, file_name)
|
|
121
|
-
|
|
136
|
+
self.logger.debug(result_message)
|
|
122
137
|
self.log_history.append(result_message)
|
|
123
138
|
return {
|
|
124
139
|
"parent_folder": folder_name,
|
|
@@ -134,24 +149,26 @@ class UploadBackupToSharepointUsecase:
|
|
|
134
149
|
f"[BACKUP] Retrying upload for {len(failed_files)} failed files... 🚨"
|
|
135
150
|
)
|
|
136
151
|
self.log_history.append(retry_message)
|
|
137
|
-
|
|
152
|
+
self.logger.debug(retry_message)
|
|
138
153
|
for file in failed_files:
|
|
139
154
|
tasks.append(
|
|
140
|
-
self.
|
|
155
|
+
self._upload_and_log_progress_task(
|
|
141
156
|
file["parent_folder"], file["file_name"]
|
|
142
157
|
)
|
|
143
158
|
)
|
|
144
159
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
145
160
|
success = calculate_percentage_uploaded(results, self.total_files)
|
|
146
161
|
if success < 100.0:
|
|
147
|
-
raise BackupUploadError(
|
|
162
|
+
raise BackupUploadError(
|
|
163
|
+
reason=extract_error_message(self.logger, results, success)
|
|
164
|
+
)
|
|
148
165
|
else:
|
|
149
166
|
successful_upload_retry = (
|
|
150
167
|
"[BACKUP] All files uploaded successfully after retry."
|
|
151
168
|
)
|
|
152
169
|
self.log_history.append(successful_upload_retry)
|
|
153
|
-
|
|
154
|
-
self._save_log_history()
|
|
170
|
+
self.logger.debug(successful_upload_retry)
|
|
171
|
+
await self._save_log_history()
|
|
155
172
|
return parse_execute_response(results)
|
|
156
173
|
|
|
157
174
|
async def execute(self):
|
|
@@ -164,7 +181,7 @@ class UploadBackupToSharepointUsecase:
|
|
|
164
181
|
start_time = time()
|
|
165
182
|
|
|
166
183
|
# Check if the local path exists in the main directory
|
|
167
|
-
if not await
|
|
184
|
+
if not await self.dir_client.path_exists(self.local_backup_source_path):
|
|
168
185
|
raise BackupSourcePathError(
|
|
169
186
|
reason=f"'{self.local_backup_source_path}' doesn't exist."
|
|
170
187
|
)
|
|
@@ -172,14 +189,12 @@ class UploadBackupToSharepointUsecase:
|
|
|
172
189
|
# Check if the current folder only have files.
|
|
173
190
|
items = [
|
|
174
191
|
item
|
|
175
|
-
for item in await
|
|
176
|
-
os.listdir, self.local_backup_source_path
|
|
177
|
-
)
|
|
192
|
+
for item in await self.dir_client.listdir(self.local_backup_source_path)
|
|
178
193
|
]
|
|
179
194
|
for item in items:
|
|
180
195
|
folder_included = item in self.destination_folders.keys()
|
|
181
|
-
is_file = not await
|
|
182
|
-
|
|
196
|
+
is_file = not await self.dir_client.isdir(
|
|
197
|
+
self.dir_client.join_paths(self.local_backup_source_path, item)
|
|
183
198
|
)
|
|
184
199
|
|
|
185
200
|
if not folder_included and not is_file:
|
|
@@ -197,7 +212,7 @@ class UploadBackupToSharepointUsecase:
|
|
|
197
212
|
f"[BACKUP] {self.local_backup_source_path} has no files ⚠️"
|
|
198
213
|
)
|
|
199
214
|
self.log_history.append(no_files_message)
|
|
200
|
-
|
|
215
|
+
self.logger.debug(no_files_message)
|
|
201
216
|
raise BackupEmptyError
|
|
202
217
|
# Create task for each file stored in the the local backup folder.
|
|
203
218
|
for folder_name in self.grouped_files_by_folder:
|
|
@@ -208,16 +223,16 @@ class UploadBackupToSharepointUsecase:
|
|
|
208
223
|
== 0
|
|
209
224
|
):
|
|
210
225
|
empty_folder_message = f"[BACKUP] The folder '{folder_name}' is empty ⚠️"
|
|
211
|
-
|
|
226
|
+
self.logger.debug(empty_folder_message)
|
|
212
227
|
self.log_history.append(empty_folder_message)
|
|
213
228
|
continue
|
|
214
229
|
extracting_files_message = (
|
|
215
230
|
"[BACKUP]" + f" Extracting files from '{folder_name} ".center(15, "*")
|
|
216
231
|
)
|
|
217
232
|
self.log_history.append(extracting_files_message)
|
|
218
|
-
|
|
233
|
+
self.logger.debug(extracting_files_message)
|
|
219
234
|
for file_name in self.grouped_files_by_folder[folder_name]:
|
|
220
|
-
tasks.append(self.
|
|
235
|
+
tasks.append(self._upload_and_log_progress_task(folder_name, file_name))
|
|
221
236
|
|
|
222
237
|
# Execution of multiple asynchronous tasks for files migration.
|
|
223
238
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
@@ -237,5 +252,5 @@ class UploadBackupToSharepointUsecase:
|
|
|
237
252
|
)
|
|
238
253
|
self.log_history.append(finished_backup_message)
|
|
239
254
|
|
|
240
|
-
self._save_log_history()
|
|
255
|
+
await self._save_log_history()
|
|
241
256
|
return parse_execute_response(results)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import re
|
|
2
|
+
from logging import Logger
|
|
2
3
|
from typing import List, Dict, Optional
|
|
3
|
-
import asyncio
|
|
4
|
-
import os
|
|
5
4
|
from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
6
5
|
BackupSourcePathError,
|
|
7
6
|
)
|
|
8
|
-
from saviialib.
|
|
9
|
-
|
|
10
|
-
)
|
|
7
|
+
from saviialib.libs.directory_client import DirectoryClient, DirectoryClientArgs
|
|
8
|
+
|
|
9
|
+
dir_client = DirectoryClient(DirectoryClientArgs(client_name="os_client"))
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
def extract_error_information(error: str) -> Optional[Dict[str, str]]:
|
|
@@ -30,8 +29,8 @@ def explain_status_code(status_code: int) -> str:
|
|
|
30
29
|
return explanations.get(status_code, "Unknown error occurred.")
|
|
31
30
|
|
|
32
31
|
|
|
33
|
-
def extract_error_message(results: List[Dict], success: float) -> str:
|
|
34
|
-
|
|
32
|
+
def extract_error_message(logger: Logger, results: List[Dict], success: float) -> str:
|
|
33
|
+
logger.info(
|
|
35
34
|
"[BACKUP] Not all files uploaded ⚠️\n"
|
|
36
35
|
f"[BACKUP] Files failed to upload: {(1 - success):.2%}"
|
|
37
36
|
)
|
|
@@ -59,9 +58,9 @@ def extract_error_message(results: List[Dict], success: float) -> str:
|
|
|
59
58
|
|
|
60
59
|
# Summary
|
|
61
60
|
for code, items in grouped_errors.items():
|
|
62
|
-
|
|
61
|
+
logger.info(f"[BACKUP] Status code {code} - {explain_status_code(int(code))}")
|
|
63
62
|
for item in items:
|
|
64
|
-
|
|
63
|
+
logger.info(
|
|
65
64
|
f"[BACKUP] File {item['file_name']}, url: {item['url']}, message: {item['message']}"
|
|
66
65
|
)
|
|
67
66
|
|
|
@@ -94,9 +93,5 @@ def calculate_percentage_uploaded(results: List[Dict], total_files: int) -> floa
|
|
|
94
93
|
return (uploaded_count / total_files) * 100 if total_files > 0 else 0
|
|
95
94
|
|
|
96
95
|
|
|
97
|
-
async def directory_exists(path: str) -> bool:
|
|
98
|
-
return await asyncio.to_thread(os.path.exists, path)
|
|
99
|
-
|
|
100
|
-
|
|
101
96
|
async def count_files_in_directory(path: str, folder_name: str) -> int:
|
|
102
|
-
return len(await
|
|
97
|
+
return len(await dir_client.listdir(dir_client.join_paths(path, folder_name)))
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
saviialib/__init__.py,sha256=TMsEY8OOjo9KOz-0jf3QBh6WFOhCY07Rd7W2PK7C-1A,253
|
|
2
2
|
saviialib/general_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
saviialib/general_types/api/__init__.py,sha256=jXhoMlbSv7UCizW_Fm2mqR_3n99qkocVwg6CF7s3w7w,145
|
|
4
|
-
saviialib/general_types/api/epii_api_types.py,sha256=
|
|
4
|
+
saviialib/general_types/api/epii_api_types.py,sha256=H4oUMnkYnl75mdCO4kyOqOdJ5jIh-J9tgGU_ZK2m7V8,2389
|
|
5
5
|
saviialib/general_types/error_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
saviialib/general_types/error_types/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
saviialib/general_types/error_types/api/epii_api_error_types.py,sha256=j1b2gE8zRTlh4gCB4kf9-JNlBzcZ9AmMKxRiFVbSqQ0,2722
|
|
8
8
|
saviialib/general_types/error_types/common/__init__.py,sha256=yOBLZbt64Ki9Q0IJ0tMAubgq7PtrQ7XQ3RgtAzyOjiE,170
|
|
9
9
|
saviialib/general_types/error_types/common/common_types.py,sha256=n5yuw-gVtkrtNfmaZ83ZkYxYHGl4jynOLUB9C8Tr32w,474
|
|
10
|
-
saviialib/libs/
|
|
11
|
-
saviialib/libs/
|
|
10
|
+
saviialib/libs/directory_client/__init__.py,sha256=ys07nzp74fHew2mUkbGpntp5w4t_PnhZIS6D4_mJw2A,162
|
|
11
|
+
saviialib/libs/directory_client/client/os_client.py,sha256=cL1ocxfLu6csBg7RKhP7sbpgCUr6_Me5cMOs4wrXmhw,628
|
|
12
|
+
saviialib/libs/directory_client/directory_client.py,sha256=mcYA2AY0f44ae39ImsetVRU8YW7xI25xTFTY5HmWivY,984
|
|
13
|
+
saviialib/libs/directory_client/directory_client_contract.py,sha256=eRTKPkpArMSi7gEDoowJ15hupLB_gr4ztO1Zc1BoXpc,396
|
|
14
|
+
saviialib/libs/directory_client/types/directory_client_types.py,sha256=ncMwVs_o6EYMuypXXmVInsjVDKJsdxVkmwj1M-LEInA,109
|
|
15
|
+
saviialib/libs/files_client/__init__.py,sha256=sIi9ne7Z3EfxnqGTaSmH-cZ8QsKyu0hoOz61GyA3njs,192
|
|
16
|
+
saviialib/libs/files_client/clients/aiofiles_client.py,sha256=Mu5pSnnEa3dT3GONmt1O-lCQstuQNXHtJHM3D2L6TU8,1107
|
|
12
17
|
saviialib/libs/files_client/files_client.py,sha256=eoByr7ZzOJ3b4NWlrEH0jKO1i-Rv3hSJV2s2JLhaOJ0,1081
|
|
13
18
|
saviialib/libs/files_client/files_client_contract.py,sha256=fYvd68IMpc1OFkxbzNSmRUoTWVctf3hkNVQ7QZV0m6I,304
|
|
14
|
-
saviialib/libs/files_client/types/files_client_types.py,sha256=
|
|
19
|
+
saviialib/libs/files_client/types/files_client_types.py,sha256=8OHm4nvZTW9K3ryeIUvthE_Cj7wF4zVcqG0KCi_vQIU,718
|
|
15
20
|
saviialib/libs/ftp_client/__init__.py,sha256=dW2Yutgc7mJJJzgKLhWKXMgQ6KIWJYfFa1sGpjHH5xU,191
|
|
16
21
|
saviialib/libs/ftp_client/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
22
|
saviialib/libs/ftp_client/clients/aioftp_client.py,sha256=gcPhLX1EE8_iiAGQ1eTWxzJ-qd3yjP9Ug1LJPibqGn8,1613
|
|
@@ -26,24 +31,24 @@ saviialib/libs/sharepoint_client/sharepoint_client_contract.py,sha256=xqNHzCjp7G
|
|
|
26
31
|
saviialib/libs/sharepoint_client/types/sharepoint_client_types.py,sha256=OmPlCJ9rLrAFBeG6aDp5cxMiQ5BZlDyGVx5S4GN4aqg,414
|
|
27
32
|
saviialib/libs/zero_dependency/utils/datetime_utils.py,sha256=NFPHxOTuCtfkYjUnsbRqw9ZK87UGAK-Eira2CwG8rJ8,754
|
|
28
33
|
saviialib/services/epii/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
saviialib/services/epii/api.py,sha256=
|
|
34
|
+
saviialib/services/epii/api.py,sha256=ykS32tt2X3ocuHtEe8oyyg94a0l7IcMhxCMrqZ6Mc4U,3557
|
|
30
35
|
saviialib/services/epii/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
36
|
saviialib/services/epii/controllers/types/__init__.py,sha256=xzky-oTSojLNkWETp_k8a4dcXYvYSQY0VhWo23Yhb8U,195
|
|
32
37
|
saviialib/services/epii/controllers/types/update_thies_data_types.py,sha256=Id86QaFt6A2EJgHJvmm3rvWGUkT2SM8D5OTxZGS-aTs,380
|
|
33
38
|
saviialib/services/epii/controllers/types/upload_backup_to_sharepoint_types.py,sha256=k_vfqI4UfdSS62HY5pi8eq2PxYXRp4LexDgRB3V2lrc,400
|
|
34
39
|
saviialib/services/epii/controllers/update_thies_data.py,sha256=5vi-CEXV9maCTHgyZRnGs8zlc2xkEQ3TJMVza4xr-Qw,4334
|
|
35
|
-
saviialib/services/epii/controllers/upload_backup_to_sharepoint.py,sha256=
|
|
40
|
+
saviialib/services/epii/controllers/upload_backup_to_sharepoint.py,sha256=2op1yGEy9DNJW5ryzBNTniVQZqdc8twAs3VIsGsnidg,3799
|
|
36
41
|
saviialib/services/epii/use_cases/constants/update_thies_data_constants.py,sha256=38f2WKV-zBO9O-CV8mh3tW3MFMiaJrrv4_FfQiyHApc,275
|
|
37
|
-
saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py,sha256=
|
|
42
|
+
saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py,sha256=8JwqAU1KP-WMUcZ67oSQY1_5I47jlaJnOpwKyTKdN_Y,208
|
|
38
43
|
saviialib/services/epii/use_cases/types/__init__.py,sha256=u6fyodOEJE2j6FMqJux40Xf9ccYAi-UUYxqT-Kzc0kE,199
|
|
39
44
|
saviialib/services/epii/use_cases/types/update_thies_data_types.py,sha256=BoT6N9YoVw3f8Cyb88T7fJTCCnkVybOh1K1u2fJ3X7k,419
|
|
40
|
-
saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py,sha256=
|
|
45
|
+
saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py,sha256=v2CEvohTqkhKmmKn2upgaGWFbWrkL817Gt3T-bnlMcQ,313
|
|
41
46
|
saviialib/services/epii/use_cases/update_thies_data.py,sha256=WLBpdAUkxAL_XdDnc49scmst1xMjrdScjr6Cmgg3UEE,6494
|
|
42
|
-
saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py,sha256=
|
|
47
|
+
saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py,sha256=V-O4x2du-lvTJRarvXbt4NjSGJ2jYWGTRrodiKPYIOU,10039
|
|
43
48
|
saviialib/services/epii/utils/__init__.py,sha256=cYt2tvq65_OMjFaqb8-CCC7IGCQgFd4ziEUWJV7s1iY,98
|
|
44
49
|
saviialib/services/epii/utils/update_thies_data_utils.py,sha256=EpjYWXqyHxJ-dO3MHhdXp-rGV7WyUckeFko-nnfnNac,555
|
|
45
|
-
saviialib/services/epii/utils/upload_backup_to_sharepoint_utils.py,sha256=
|
|
46
|
-
saviialib-0.
|
|
47
|
-
saviialib-0.
|
|
48
|
-
saviialib-0.
|
|
49
|
-
saviialib-0.
|
|
50
|
+
saviialib/services/epii/utils/upload_backup_to_sharepoint_utils.py,sha256=p1LIEz_iSnNSv5SxebfiR5ry5HY83ttJ7vJ97TEw2mk,3456
|
|
51
|
+
saviialib-0.10.1.dist-info/LICENSE,sha256=NWpf6b38xgBWPBo5HZsCbdfp9hZSliEbRqWQgm0fkOo,1076
|
|
52
|
+
saviialib-0.10.1.dist-info/METADATA,sha256=7Ru4sGRBiK6gcfnKPTUSMQeqp-OvNfAtlJJ6LK-WsrI,4083
|
|
53
|
+
saviialib-0.10.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
54
|
+
saviialib-0.10.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|