saviialib 0.10.2__py3-none-any.whl → 0.11.0__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 +0 -2
- saviialib/general_types/error_types/api/epii_api_error_types.py +12 -0
- saviialib/libs/ftp_client/clients/aioftp_client.py +9 -5
- saviialib/libs/ftp_client/ftp_client.py +4 -4
- saviialib/libs/ftp_client/ftp_client_contract.py +2 -2
- saviialib/libs/sharepoint_client/clients/sharepoint_rest_api.py +3 -2
- saviialib/libs/sharepoint_client/sharepoint_client.py +21 -1
- saviialib/services/epii/api.py +21 -11
- saviialib/services/epii/controllers/types/update_thies_data_types.py +2 -0
- saviialib/services/epii/controllers/types/upload_backup_to_sharepoint_types.py +2 -0
- saviialib/services/epii/controllers/update_thies_data.py +12 -2
- saviialib/services/epii/controllers/upload_backup_to_sharepoint.py +3 -3
- saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py +0 -1
- saviialib/services/epii/use_cases/types/update_thies_data_types.py +3 -1
- saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py +1 -1
- saviialib/services/epii/use_cases/update_thies_data.py +63 -28
- saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py +98 -81
- {saviialib-0.10.2.dist-info → saviialib-0.11.0.dist-info}/METADATA +1 -1
- {saviialib-0.10.2.dist-info → saviialib-0.11.0.dist-info}/RECORD +21 -22
- saviialib/services/epii/use_cases/constants/update_thies_data_constants.py +0 -5
- {saviialib-0.10.2.dist-info → saviialib-0.11.0.dist-info}/LICENSE +0 -0
- {saviialib-0.10.2.dist-info → saviialib-0.11.0.dist-info}/WHEEL +0 -0
|
@@ -43,6 +43,18 @@ class SharePointFetchingError(Exception):
|
|
|
43
43
|
return self.reason.__str__()
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
class SharePointDirectoryError(Exception):
|
|
47
|
+
def __init__(self, *args, reason):
|
|
48
|
+
super().__init__(*args, reason)
|
|
49
|
+
self.reason = reason
|
|
50
|
+
|
|
51
|
+
def __str__(self):
|
|
52
|
+
return (
|
|
53
|
+
"An error occurred while fetching the folders from Microsoft SharePoint. "
|
|
54
|
+
+ self.reason.__str__()
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
46
58
|
class SharePointUploadError(Exception):
|
|
47
59
|
"""Raised when there is an error uploading files to the Microsoft SharePoint folder."""
|
|
48
60
|
|
|
@@ -34,12 +34,16 @@ class AioFTPClient(FTPClientContract):
|
|
|
34
34
|
)
|
|
35
35
|
|
|
36
36
|
async def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
try:
|
|
38
|
+
await self._async_start()
|
|
39
|
+
return [
|
|
40
|
+
path.name
|
|
41
|
+
async for path, _ in self.client.list(args.path, recursive=False) # type: ignore
|
|
42
|
+
]
|
|
43
|
+
except StatusCodeError as error:
|
|
44
|
+
raise ConnectionAbortedError(error)
|
|
41
45
|
|
|
42
46
|
async def read_file(self, args: FtpReadFileArgs) -> bytes:
|
|
43
47
|
await self._async_start()
|
|
44
|
-
async with self.client.download_stream(args.file_path) as stream:
|
|
48
|
+
async with self.client.download_stream(args.file_path) as stream: # type: ignore
|
|
45
49
|
return await stream.read()
|
|
@@ -15,8 +15,8 @@ class FTPClient(FTPClientContract):
|
|
|
15
15
|
self.client_obj = AioFTPClient(args)
|
|
16
16
|
self.client_name = args.client_name
|
|
17
17
|
|
|
18
|
-
def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
19
|
-
return self.client_obj.list_files(args)
|
|
18
|
+
async def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
19
|
+
return await self.client_obj.list_files(args)
|
|
20
20
|
|
|
21
|
-
def read_file(self, args: FtpReadFileArgs) -> bytes:
|
|
22
|
-
return self.client_obj.read_file(args)
|
|
21
|
+
async def read_file(self, args: FtpReadFileArgs) -> bytes:
|
|
22
|
+
return await self.client_obj.read_file(args)
|
|
@@ -5,9 +5,9 @@ from .types.ftp_client_types import FtpListFilesArgs, FtpReadFileArgs
|
|
|
5
5
|
|
|
6
6
|
class FTPClientContract(ABC):
|
|
7
7
|
@abstractmethod
|
|
8
|
-
def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
8
|
+
async def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
9
9
|
pass
|
|
10
10
|
|
|
11
11
|
@abstractmethod
|
|
12
|
-
def read_file(self, args: FtpReadFileArgs) -> bytes:
|
|
12
|
+
async def read_file(self, args: FtpReadFileArgs) -> bytes:
|
|
13
13
|
pass
|
|
@@ -104,10 +104,11 @@ class SharepointRestAPI(SharepointClientContract):
|
|
|
104
104
|
folder_relative_url = (
|
|
105
105
|
f"GetFolderByServerRelativeUrl('{args.folder_relative_url}')"
|
|
106
106
|
)
|
|
107
|
-
endpoint = f"web/{folder_relative_url}/
|
|
107
|
+
endpoint = f"web/{folder_relative_url}/Folders"
|
|
108
108
|
response = await self.session.get(endpoint.lstrip("/"))
|
|
109
109
|
response.raise_for_status()
|
|
110
|
-
|
|
110
|
+
response_json = await response.json()
|
|
111
|
+
return response_json
|
|
111
112
|
except ClientError as error:
|
|
112
113
|
raise ConnectionError(error) from error
|
|
113
114
|
|
|
@@ -18,6 +18,26 @@ class SharepointClient(SharepointClientContract):
|
|
|
18
18
|
elif args.client_name == "sharepoint_rest_api":
|
|
19
19
|
self.client_obj = SharepointRestAPI(args)
|
|
20
20
|
|
|
21
|
+
@property
|
|
22
|
+
def tenant_id(self):
|
|
23
|
+
return self.client_obj.tenant_id
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def tenant_name(self):
|
|
27
|
+
return self.client_obj.tenant_name
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def site_name(self):
|
|
31
|
+
return self.client_obj.site_name
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def client_id(self):
|
|
35
|
+
return self.client_obj.client_id
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def client_secret(self):
|
|
39
|
+
return self.client_obj.client_secret
|
|
40
|
+
|
|
21
41
|
async def __aenter__(self):
|
|
22
42
|
return await self.client_obj.__aenter__()
|
|
23
43
|
|
|
@@ -28,7 +48,7 @@ class SharepointClient(SharepointClientContract):
|
|
|
28
48
|
return await self.client_obj.list_files(args)
|
|
29
49
|
|
|
30
50
|
async def list_folders(self, args: SpListFoldersArgs) -> list:
|
|
31
|
-
return await self.client_obj.
|
|
51
|
+
return await self.client_obj.list_folders(args)
|
|
32
52
|
|
|
33
53
|
async def upload_file(self, args: SpUploadFileArgs) -> dict:
|
|
34
54
|
return await self.client_obj.upload_file(args)
|
saviialib/services/epii/api.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Dict
|
|
1
|
+
from typing import Any, Dict, List
|
|
2
2
|
|
|
3
3
|
from .controllers.types.update_thies_data_types import UpdateThiesDataControllerInput
|
|
4
4
|
from .controllers.types.upload_backup_to_sharepoint_types import (
|
|
@@ -28,15 +28,21 @@ 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
|
+
|
|
31
32
|
self.logger = config.logger
|
|
32
33
|
|
|
33
|
-
async def update_thies_data(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
async def update_thies_data(
|
|
35
|
+
self, sharepoint_folders_path: List[str], ftp_server_folders_path: List[str]
|
|
36
|
+
) -> Dict[str, Any]:
|
|
37
|
+
"""Updates data from a THIES Data Logger by connecting to an FTP server
|
|
38
|
+
and transferring data to specified Sharepoint folders.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
sharepoint_folders_path (list): List of Sharepoint folder paths for AVG and EXT data.
|
|
42
|
+
ftp_server_folders_path (list): List of FTP server folder paths for AVG and EXT data.
|
|
37
43
|
|
|
38
44
|
Returns:
|
|
39
|
-
|
|
45
|
+
dict: A dictionary representation of the API response.
|
|
40
46
|
"""
|
|
41
47
|
config = EpiiUpdateThiesConfig(
|
|
42
48
|
ftp_port=self.ftp_port,
|
|
@@ -49,12 +55,16 @@ class EpiiAPI:
|
|
|
49
55
|
sharepoint_tenant_id=self.sharepoint_tenant_id,
|
|
50
56
|
sharepoint_tenant_name=self.sharepoint_tenant_name,
|
|
51
57
|
)
|
|
52
|
-
controller = UpdateThiesDataController(
|
|
58
|
+
controller = UpdateThiesDataController(
|
|
59
|
+
UpdateThiesDataControllerInput(
|
|
60
|
+
config, sharepoint_folders_path, ftp_server_folders_path
|
|
61
|
+
)
|
|
62
|
+
)
|
|
53
63
|
response = await controller.execute()
|
|
54
64
|
return response.__dict__
|
|
55
65
|
|
|
56
66
|
async def upload_backup_to_sharepoint(
|
|
57
|
-
self, local_backup_source_path: str,
|
|
67
|
+
self, local_backup_source_path: str, sharepoint_destination_path: str
|
|
58
68
|
) -> Dict[str, Any]:
|
|
59
69
|
"""Migrate a backup folder from Home assistant to Sharepoint directory.
|
|
60
70
|
Args:
|
|
@@ -70,13 +80,13 @@ class EpiiAPI:
|
|
|
70
80
|
sharepoint_site_name=self.sharepoint_site_name,
|
|
71
81
|
sharepoint_tenant_id=self.sharepoint_tenant_id,
|
|
72
82
|
sharepoint_tenant_name=self.sharepoint_tenant_name,
|
|
73
|
-
local_backup_source_path=local_backup_source_path,
|
|
74
|
-
destination_folders=destination_folders,
|
|
75
83
|
logger=self.logger,
|
|
76
84
|
)
|
|
77
85
|
|
|
78
86
|
controller = UploadBackupToSharepointController(
|
|
79
|
-
UploadBackupToSharepointControllerInput(
|
|
87
|
+
UploadBackupToSharepointControllerInput(
|
|
88
|
+
config, local_backup_source_path, sharepoint_destination_path
|
|
89
|
+
)
|
|
80
90
|
)
|
|
81
91
|
response = await controller.execute()
|
|
82
92
|
return response.__dict__
|
|
@@ -7,6 +7,8 @@ from saviialib.general_types.api.epii_api_types import EpiiSharepointBackupConfi
|
|
|
7
7
|
@dataclass
|
|
8
8
|
class UploadBackupToSharepointControllerInput:
|
|
9
9
|
config: EpiiSharepointBackupConfig
|
|
10
|
+
local_backup_source_path: str
|
|
11
|
+
sharepoint_destination_path: str
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
@dataclass
|
|
@@ -5,6 +5,7 @@ from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
|
5
5
|
ThiesConnectionError,
|
|
6
6
|
ThiesFetchingError,
|
|
7
7
|
SharePointUploadError,
|
|
8
|
+
SharePointDirectoryError,
|
|
8
9
|
)
|
|
9
10
|
from saviialib.general_types.error_types.common.common_types import (
|
|
10
11
|
EmptyDataError,
|
|
@@ -42,6 +43,8 @@ class UpdateThiesDataController:
|
|
|
42
43
|
sharepoint_tenant_name=input.config.sharepoint_tenant_name,
|
|
43
44
|
sharepoint_tenant_id=input.config.sharepoint_tenant_id,
|
|
44
45
|
),
|
|
46
|
+
sharepoint_folders_path=input.sharepoint_folders_path,
|
|
47
|
+
ftp_server_folders_path=input.ftp_server_folders_path,
|
|
45
48
|
)
|
|
46
49
|
)
|
|
47
50
|
|
|
@@ -51,7 +54,7 @@ class UpdateThiesDataController:
|
|
|
51
54
|
return UpdateThiesDataControllerOutput(
|
|
52
55
|
message="THIES was synced successfully",
|
|
53
56
|
status=HTTPStatus.OK.value,
|
|
54
|
-
metadata={"data": data},
|
|
57
|
+
metadata={"data": data}, # type: ignore
|
|
55
58
|
)
|
|
56
59
|
except EmptyDataError:
|
|
57
60
|
return UpdateThiesDataControllerOutput(
|
|
@@ -87,7 +90,14 @@ class UpdateThiesDataController:
|
|
|
87
90
|
|
|
88
91
|
except SharePointUploadError as error:
|
|
89
92
|
return UpdateThiesDataControllerOutput(
|
|
90
|
-
message="An error
|
|
93
|
+
message="An error ocurred while uploading files to RCER Cloud",
|
|
94
|
+
status=HTTPStatus.BAD_REQUEST.value,
|
|
95
|
+
metadata={"error": error.__str__()},
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
except SharePointDirectoryError as error:
|
|
99
|
+
return UpdateThiesDataControllerOutput(
|
|
100
|
+
message="An error ocurred while extracting folders from Microsoft Sharepoint",
|
|
91
101
|
status=HTTPStatus.BAD_REQUEST.value,
|
|
92
102
|
metadata={"error": error.__str__()},
|
|
93
103
|
)
|
|
@@ -33,8 +33,8 @@ class UploadBackupToSharepointController:
|
|
|
33
33
|
sharepoint_tenant_name=input.config.sharepoint_tenant_name,
|
|
34
34
|
sharepoint_tenant_id=input.config.sharepoint_tenant_id,
|
|
35
35
|
),
|
|
36
|
-
local_backup_source_path=input.
|
|
37
|
-
|
|
36
|
+
local_backup_source_path=input.local_backup_source_path,
|
|
37
|
+
sharepoint_destination_path=input.sharepoint_destination_path,
|
|
38
38
|
logger=input.config.logger,
|
|
39
39
|
)
|
|
40
40
|
)
|
|
@@ -45,7 +45,7 @@ class UploadBackupToSharepointController:
|
|
|
45
45
|
return UploadBackupToSharepointControllerOutput(
|
|
46
46
|
message="Local backup was migrated successfully",
|
|
47
47
|
status=HTTPStatus.OK.value,
|
|
48
|
-
metadata={"data": data},
|
|
48
|
+
metadata={"data": data}, # type: ignore
|
|
49
49
|
)
|
|
50
50
|
except EmptyDataError:
|
|
51
51
|
return UploadBackupToSharepointControllerOutput(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from typing import Dict
|
|
2
|
+
from typing import Dict, List
|
|
3
3
|
from saviialib.general_types.api.epii_api_types import FtpClientConfig, SharepointConfig
|
|
4
4
|
|
|
5
5
|
|
|
@@ -7,6 +7,8 @@ from saviialib.general_types.api.epii_api_types import FtpClientConfig, Sharepoi
|
|
|
7
7
|
class UpdateThiesDataUseCaseInput:
|
|
8
8
|
ftp_config: FtpClientConfig
|
|
9
9
|
sharepoint_config: SharepointConfig
|
|
10
|
+
sharepoint_folders_path: List
|
|
11
|
+
ftp_server_folders_path: List
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
@dataclass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import saviialib.services.epii.use_cases.constants.update_thies_data_constants as c
|
|
2
1
|
from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
3
2
|
SharePointFetchingError,
|
|
3
|
+
SharePointDirectoryError,
|
|
4
4
|
SharePointUploadError,
|
|
5
5
|
ThiesConnectionError,
|
|
6
6
|
ThiesFetchingError,
|
|
@@ -20,6 +20,7 @@ from saviialib.libs.sharepoint_client import (
|
|
|
20
20
|
SharepointClient,
|
|
21
21
|
SharepointClientInitArgs,
|
|
22
22
|
SpListFilesArgs,
|
|
23
|
+
SpListFoldersArgs,
|
|
23
24
|
SpUploadFileArgs,
|
|
24
25
|
)
|
|
25
26
|
from saviialib.services.epii.use_cases.types import (
|
|
@@ -38,6 +39,9 @@ class UpdateThiesDataUseCase:
|
|
|
38
39
|
input.sharepoint_config
|
|
39
40
|
)
|
|
40
41
|
self.thies_ftp_client = self._initialize_thies_ftp_client(input.ftp_config)
|
|
42
|
+
self.sharepoint_folders_path = input.sharepoint_folders_path
|
|
43
|
+
self.ftp_server_folders_path = input.ftp_server_folders_path
|
|
44
|
+
self.sharepoint_base_url = f"/sites/{self.sharepoint_client.site_name}"
|
|
41
45
|
self.uploading = set()
|
|
42
46
|
|
|
43
47
|
def _initialize_sharepoint_client(
|
|
@@ -58,36 +62,56 @@ class UpdateThiesDataUseCase:
|
|
|
58
62
|
except RuntimeError as error:
|
|
59
63
|
raise FtpClientError(error)
|
|
60
64
|
|
|
65
|
+
async def _validate_sharepoint_current_folders(self):
|
|
66
|
+
async with self.sharepoint_client:
|
|
67
|
+
folder_base_path = "/".join(
|
|
68
|
+
self.sharepoint_folders_path[0].split("/")[0:-1]
|
|
69
|
+
)
|
|
70
|
+
relative_url = f"{self.sharepoint_base_url}/{folder_base_path}"
|
|
71
|
+
response = await self.sharepoint_client.list_folders(
|
|
72
|
+
SpListFoldersArgs(relative_url)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
current_folders = [item["Name"] for item in response["value"]] # type: ignore
|
|
76
|
+
|
|
77
|
+
for folder_path in self.sharepoint_folders_path:
|
|
78
|
+
folder_name = folder_path.split("/")[-1]
|
|
79
|
+
if folder_name not in current_folders:
|
|
80
|
+
raise SharePointDirectoryError(
|
|
81
|
+
reason=f"The current folder '{folder_name}' doesn't exist."
|
|
82
|
+
)
|
|
83
|
+
|
|
61
84
|
async def fetch_cloud_file_names(self) -> set[str]:
|
|
62
85
|
"""Fetch file names from the RCER cloud."""
|
|
63
|
-
|
|
86
|
+
await self._validate_sharepoint_current_folders()
|
|
64
87
|
try:
|
|
65
88
|
cloud_files = set()
|
|
66
89
|
async with self.sharepoint_client:
|
|
67
|
-
for
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
)
|
|
90
|
+
for folder_path in self.sharepoint_folders_path:
|
|
91
|
+
folder_name = folder_path.split("/")[-1]
|
|
92
|
+
relative_url = f"{self.sharepoint_base_url}/{folder_path}"
|
|
93
|
+
args = SpListFilesArgs(folder_relative_url=relative_url)
|
|
71
94
|
response = await self.sharepoint_client.list_files(args)
|
|
72
95
|
cloud_files.update(
|
|
73
|
-
{f"{
|
|
96
|
+
{f"{folder_name}_{item['Name']}" for item in response["value"]} # type: ignore
|
|
74
97
|
)
|
|
75
98
|
return cloud_files
|
|
76
|
-
except
|
|
99
|
+
except Exception as error:
|
|
77
100
|
raise SharePointFetchingError(reason=error)
|
|
78
101
|
|
|
79
102
|
async def fetch_thies_file_names(self) -> set[str]:
|
|
80
103
|
"""Fetch file names from the THIES FTP server."""
|
|
81
104
|
try:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
f"
|
|
90
|
-
|
|
105
|
+
thies_files = set()
|
|
106
|
+
for folder_path in self.ftp_server_folders_path:
|
|
107
|
+
# AV for average, and EXT for extreme.
|
|
108
|
+
prefix = "AVG" if "AV" in folder_path else "EXT"
|
|
109
|
+
files = await self.thies_ftp_client.list_files(
|
|
110
|
+
FtpListFilesArgs(path=folder_path)
|
|
111
|
+
)
|
|
112
|
+
files_names = {f"{prefix}_{name}" for name in files}
|
|
113
|
+
thies_files.update(files_names)
|
|
114
|
+
return thies_files
|
|
91
115
|
except ConnectionRefusedError as error:
|
|
92
116
|
raise ThiesConnectionError(reason=error)
|
|
93
117
|
except ConnectionAbortedError as error:
|
|
@@ -98,16 +122,19 @@ class UpdateThiesDataUseCase:
|
|
|
98
122
|
try:
|
|
99
123
|
content_files = {}
|
|
100
124
|
for file in self.uploading:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if
|
|
105
|
-
else
|
|
125
|
+
_, filename = file.split("_", 1)
|
|
126
|
+
folder_path = (
|
|
127
|
+
self.ftp_server_folders_path[0]
|
|
128
|
+
if "AV" in self.ftp_server_folders_path[0] # Folder with AVG prefix
|
|
129
|
+
else self.ftp_server_folders_path[1] # Folder with EXT prefix
|
|
106
130
|
)
|
|
131
|
+
file_path = f"{folder_path}/{filename}"
|
|
107
132
|
content = await self.thies_ftp_client.read_file(
|
|
108
133
|
FtpReadFileArgs(file_path)
|
|
109
134
|
)
|
|
110
|
-
content_files[file] =
|
|
135
|
+
content_files[file] = (
|
|
136
|
+
content # Save file content with its original name.
|
|
137
|
+
)
|
|
111
138
|
return content_files
|
|
112
139
|
except ConnectionRefusedError as error:
|
|
113
140
|
raise ThiesConnectionError(reason=error)
|
|
@@ -123,9 +150,16 @@ class UpdateThiesDataUseCase:
|
|
|
123
150
|
async with self.sharepoint_client:
|
|
124
151
|
for file, file_content in files.items():
|
|
125
152
|
try:
|
|
126
|
-
|
|
153
|
+
_, file_name = file.split("_", 1)
|
|
154
|
+
# Could be AVG or EXT.
|
|
155
|
+
if file_name in self.sharepoint_folders_path[0]:
|
|
156
|
+
folder_path = self.sharepoint_folders_path[0]
|
|
157
|
+
else:
|
|
158
|
+
folder_path = self.sharepoint_folders_path[1]
|
|
159
|
+
relative_url = f"{self.sharepoint_base_url}/{folder_path}"
|
|
160
|
+
|
|
127
161
|
args = SpUploadFileArgs(
|
|
128
|
-
folder_relative_url=
|
|
162
|
+
folder_relative_url=relative_url,
|
|
129
163
|
file_content=file_content,
|
|
130
164
|
file_name=file_name,
|
|
131
165
|
)
|
|
@@ -145,16 +179,17 @@ class UpdateThiesDataUseCase:
|
|
|
145
179
|
|
|
146
180
|
return upload_results
|
|
147
181
|
|
|
148
|
-
async def execute(self)
|
|
182
|
+
async def execute(self):
|
|
149
183
|
"""Synchronize data from the THIES Center to the cloud."""
|
|
150
184
|
try:
|
|
151
185
|
thies_files = await self.fetch_thies_file_names()
|
|
152
186
|
except RuntimeError as error:
|
|
153
187
|
raise FtpClientError(error)
|
|
188
|
+
|
|
154
189
|
try:
|
|
155
190
|
cloud_files = await self.fetch_cloud_file_names()
|
|
156
191
|
except RuntimeError as error:
|
|
157
|
-
raise SharepointClient(error)
|
|
192
|
+
raise SharepointClient(error) # type: ignore
|
|
158
193
|
|
|
159
194
|
self.uploading = thies_files - cloud_files
|
|
160
195
|
if not self.uploading:
|
|
@@ -168,4 +203,4 @@ class UpdateThiesDataUseCase:
|
|
|
168
203
|
thies_fetched_files
|
|
169
204
|
)
|
|
170
205
|
|
|
171
|
-
return parse_execute_response(thies_fetched_files, upload_statistics)
|
|
206
|
+
return parse_execute_response(thies_fetched_files, upload_statistics) # type: ignore
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from time import time
|
|
3
3
|
from logging import Logger
|
|
4
|
-
import saviialib.services.epii.use_cases.constants.upload_backup_to_sharepoint_constants as c
|
|
5
4
|
from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
6
5
|
BackupEmptyError,
|
|
7
6
|
BackupSourcePathError,
|
|
@@ -21,6 +20,7 @@ from saviialib.libs.sharepoint_client import (
|
|
|
21
20
|
SharepointClient,
|
|
22
21
|
SharepointClientInitArgs,
|
|
23
22
|
SpUploadFileArgs,
|
|
23
|
+
SpListFoldersArgs,
|
|
24
24
|
)
|
|
25
25
|
from saviialib.services.epii.utils.upload_backup_to_sharepoint_utils import (
|
|
26
26
|
calculate_percentage_uploaded,
|
|
@@ -39,13 +39,21 @@ class UploadBackupToSharepointUsecase:
|
|
|
39
39
|
def __init__(self, input: UploadBackupToSharepointUseCaseInput):
|
|
40
40
|
self.sharepoint_config = input.sharepoint_config
|
|
41
41
|
self.local_backup_source_path = input.local_backup_source_path
|
|
42
|
-
self.
|
|
42
|
+
self.sharepoint_destination_path = input.sharepoint_destination_path
|
|
43
43
|
self.files_client = self._initialize_files_client()
|
|
44
44
|
self.dir_client = self._initialize_directory_client()
|
|
45
45
|
self.log_history = []
|
|
46
46
|
self.grouped_files_by_folder = None
|
|
47
47
|
self.total_files = None
|
|
48
48
|
self.logger: Logger = input.logger
|
|
49
|
+
self.sharepoint_client = self._initalize_sharepoint_client()
|
|
50
|
+
|
|
51
|
+
def _initalize_sharepoint_client(self):
|
|
52
|
+
return SharepointClient(
|
|
53
|
+
SharepointClientInitArgs(
|
|
54
|
+
self.sharepoint_config, client_name="sharepoint_rest_api"
|
|
55
|
+
)
|
|
56
|
+
)
|
|
49
57
|
|
|
50
58
|
def _initialize_directory_client(self):
|
|
51
59
|
return DirectoryClient(DirectoryClientArgs(client_name="os_client"))
|
|
@@ -53,7 +61,44 @@ class UploadBackupToSharepointUsecase:
|
|
|
53
61
|
def _initialize_files_client(self):
|
|
54
62
|
return FilesClient(FilesClientInitArgs(client_name="aiofiles_client"))
|
|
55
63
|
|
|
56
|
-
async def
|
|
64
|
+
async def _validate_backup_structure(self):
|
|
65
|
+
# Check if the local path exists in the main directory
|
|
66
|
+
if not await self.dir_client.path_exists(self.local_backup_source_path):
|
|
67
|
+
raise BackupSourcePathError(
|
|
68
|
+
reason=f"'{self.local_backup_source_path}' doesn't exist."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
local_directories = (
|
|
72
|
+
list(self.grouped_files_by_folder.keys())
|
|
73
|
+
if self.grouped_files_by_folder
|
|
74
|
+
else []
|
|
75
|
+
)
|
|
76
|
+
async with self.sharepoint_client: # type: ignore
|
|
77
|
+
response = await self.sharepoint_client.list_folders(
|
|
78
|
+
SpListFoldersArgs(folder_relative_url=self.sharepoint_destination_path)
|
|
79
|
+
)
|
|
80
|
+
sharepoint_directories = [x["Name"] for x in response["value"]] # type: ignore
|
|
81
|
+
|
|
82
|
+
# Verify that all local directories exist in SharePoint
|
|
83
|
+
for local_dir in local_directories:
|
|
84
|
+
if local_dir not in sharepoint_directories:
|
|
85
|
+
error_message = f"Folder '{local_dir}' does not exist in SharePoint destination path '{self.sharepoint_destination_path}'."
|
|
86
|
+
self.log_history.append(error_message)
|
|
87
|
+
self.logger.error("[local_backup_lib] %s", error_message)
|
|
88
|
+
raise BackupSourcePathError(
|
|
89
|
+
reason=f"Folder '{local_dir}' does not exist in SharePoint destination path '{self.sharepoint_destination_path}'."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Check if the current folder only have files and each folder exist in Microsoft Sharepoint.
|
|
93
|
+
if self.total_files == 0:
|
|
94
|
+
no_files_message = (
|
|
95
|
+
f"[local_backup_lib] {self.local_backup_source_path} has no files ⚠️"
|
|
96
|
+
)
|
|
97
|
+
self.log_history.append(no_files_message)
|
|
98
|
+
self.logger.debug(no_files_message)
|
|
99
|
+
raise BackupEmptyError
|
|
100
|
+
|
|
101
|
+
async def _group_files_by_folder(self) -> dict[str, list[str]]:
|
|
57
102
|
"""Groups files by their parent folder."""
|
|
58
103
|
backup_folder_exists = await self.dir_client.path_exists(
|
|
59
104
|
self.local_backup_source_path
|
|
@@ -62,17 +107,17 @@ class UploadBackupToSharepointUsecase:
|
|
|
62
107
|
if not backup_folder_exists:
|
|
63
108
|
return {}
|
|
64
109
|
folder_names = await self.dir_client.listdir(self.local_backup_source_path)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
110
|
+
grouped = {}
|
|
111
|
+
for folder_name in folder_names:
|
|
112
|
+
is_folder = await self.dir_client.isdir(
|
|
113
|
+
self.dir_client.join_paths(self.local_backup_source_path, folder_name)
|
|
114
|
+
)
|
|
115
|
+
if not is_folder:
|
|
116
|
+
continue
|
|
117
|
+
grouped[folder_name] = await self.dir_client.listdir(
|
|
118
|
+
self.dir_client.join_paths(self.local_backup_source_path, folder_name)
|
|
119
|
+
)
|
|
120
|
+
return grouped
|
|
76
121
|
|
|
77
122
|
async def _save_log_history(self) -> None:
|
|
78
123
|
await self.files_client.write(
|
|
@@ -83,6 +128,30 @@ class UploadBackupToSharepointUsecase:
|
|
|
83
128
|
)
|
|
84
129
|
)
|
|
85
130
|
|
|
131
|
+
async def _generate_tasks(self) -> list:
|
|
132
|
+
tasks = []
|
|
133
|
+
for folder_name in self.grouped_files_by_folder: # type: ignore
|
|
134
|
+
count_files_in_dir = await count_files_in_directory(
|
|
135
|
+
self.local_backup_source_path, folder_name
|
|
136
|
+
)
|
|
137
|
+
if count_files_in_dir == 0:
|
|
138
|
+
empty_folder_message = (
|
|
139
|
+
f"[local_backup_lib] The folder '{folder_name}' is empty ⚠️"
|
|
140
|
+
)
|
|
141
|
+
self.logger.debug(empty_folder_message)
|
|
142
|
+
self.log_history.append(empty_folder_message)
|
|
143
|
+
continue
|
|
144
|
+
extracting_files_message = (
|
|
145
|
+
"[local_backup_lib]"
|
|
146
|
+
+ f" Extracting files from '{folder_name} ".center(15, "*")
|
|
147
|
+
)
|
|
148
|
+
self.log_history.append(extracting_files_message)
|
|
149
|
+
self.logger.debug(extracting_files_message)
|
|
150
|
+
for file_name in self.grouped_files_by_folder[folder_name]: # type: ignore
|
|
151
|
+
tasks.append(self._upload_and_log_progress_task(folder_name, file_name))
|
|
152
|
+
|
|
153
|
+
return tasks
|
|
154
|
+
|
|
86
155
|
async def export_file_to_sharepoint(
|
|
87
156
|
self, folder_name: str, file_name: str, file_content: bytes
|
|
88
157
|
) -> tuple[bool, str]:
|
|
@@ -101,10 +170,7 @@ class UploadBackupToSharepointUsecase:
|
|
|
101
170
|
|
|
102
171
|
async with sharepoint_client:
|
|
103
172
|
try:
|
|
104
|
-
|
|
105
|
-
folder_name, folder_name
|
|
106
|
-
)
|
|
107
|
-
folder_url = f"{c.SHAREPOINT_BASE_URL}/{destination_folder}"
|
|
173
|
+
folder_url = f"{self.sharepoint_destination_path}/{folder_name}"
|
|
108
174
|
args = SpUploadFileArgs(
|
|
109
175
|
folder_relative_url=folder_url,
|
|
110
176
|
file_content=file_content,
|
|
@@ -130,7 +196,9 @@ class UploadBackupToSharepointUsecase:
|
|
|
130
196
|
)
|
|
131
197
|
file_content = await self.files_client.read(ReadArgs(file_path, mode="rb"))
|
|
132
198
|
uploaded, error_message = await self.export_file_to_sharepoint(
|
|
133
|
-
folder_name,
|
|
199
|
+
folder_name,
|
|
200
|
+
file_name,
|
|
201
|
+
file_content, # type: ignore
|
|
134
202
|
)
|
|
135
203
|
result_message = show_upload_result(uploaded, file_name)
|
|
136
204
|
self.logger.debug(result_message)
|
|
@@ -155,10 +223,10 @@ class UploadBackupToSharepointUsecase:
|
|
|
155
223
|
)
|
|
156
224
|
)
|
|
157
225
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
158
|
-
success = calculate_percentage_uploaded(results, self.total_files)
|
|
226
|
+
success = calculate_percentage_uploaded(results, self.total_files) # type: ignore
|
|
159
227
|
if success < 100.0:
|
|
160
228
|
raise BackupUploadError(
|
|
161
|
-
reason=extract_error_message(self.logger, results, success)
|
|
229
|
+
reason=extract_error_message(self.logger, results, success) # type: ignore
|
|
162
230
|
)
|
|
163
231
|
else:
|
|
164
232
|
successful_upload_retry = (
|
|
@@ -167,77 +235,26 @@ class UploadBackupToSharepointUsecase:
|
|
|
167
235
|
self.log_history.append(successful_upload_retry)
|
|
168
236
|
self.logger.debug(successful_upload_retry)
|
|
169
237
|
await self._save_log_history()
|
|
170
|
-
return parse_execute_response(results)
|
|
238
|
+
return parse_execute_response(results) # type: ignore
|
|
171
239
|
|
|
172
240
|
async def execute(self):
|
|
173
241
|
"""Exports all files from the local backup folder to SharePoint cloud."""
|
|
174
|
-
|
|
242
|
+
start_time = time()
|
|
243
|
+
self.grouped_files_by_folder = await self._group_files_by_folder()
|
|
175
244
|
self.total_files = sum(
|
|
176
245
|
len(files) for files in self.grouped_files_by_folder.values()
|
|
177
246
|
)
|
|
178
|
-
tasks = []
|
|
179
|
-
start_time = time()
|
|
180
247
|
|
|
181
|
-
# Check if the
|
|
182
|
-
|
|
183
|
-
raise BackupSourcePathError(
|
|
184
|
-
reason=f"'{self.local_backup_source_path}' doesn't exist."
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
# Check if the current folder only have files.
|
|
188
|
-
items = [
|
|
189
|
-
item
|
|
190
|
-
for item in await self.dir_client.listdir(self.local_backup_source_path)
|
|
191
|
-
]
|
|
192
|
-
for item in items:
|
|
193
|
-
folder_included = item in self.destination_folders.keys()
|
|
194
|
-
is_file = not await self.dir_client.isdir(
|
|
195
|
-
self.dir_client.join_paths(self.local_backup_source_path, item)
|
|
196
|
-
)
|
|
248
|
+
# Check if the current folder only have files and each folder exist in Microsoft Sharepoint.
|
|
249
|
+
await self._validate_backup_structure()
|
|
197
250
|
|
|
198
|
-
if not folder_included and not is_file:
|
|
199
|
-
raise BackupSourcePathError(
|
|
200
|
-
reason=(
|
|
201
|
-
f"'{item}' must be included in the destination folders dictionary",
|
|
202
|
-
)
|
|
203
|
-
)
|
|
204
|
-
elif folder_included and is_file:
|
|
205
|
-
print(folder_included, is_file)
|
|
206
|
-
raise BackupSourcePathError(reason=(f"'{item}' must be a directory.",))
|
|
207
|
-
|
|
208
|
-
if self.total_files == 0:
|
|
209
|
-
no_files_message = (
|
|
210
|
-
f"[local_backup_lib] {self.local_backup_source_path} has no files ⚠️"
|
|
211
|
-
)
|
|
212
|
-
self.log_history.append(no_files_message)
|
|
213
|
-
self.logger.debug(no_files_message)
|
|
214
|
-
raise BackupEmptyError
|
|
215
251
|
# Create task for each file stored in the the local backup folder.
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
await count_files_in_directory(
|
|
219
|
-
self.local_backup_source_path, folder_name
|
|
220
|
-
)
|
|
221
|
-
== 0
|
|
222
|
-
):
|
|
223
|
-
empty_folder_message = (
|
|
224
|
-
f"[local_backup_lib] The folder '{folder_name}' is empty ⚠️"
|
|
225
|
-
)
|
|
226
|
-
self.logger.debug(empty_folder_message)
|
|
227
|
-
self.log_history.append(empty_folder_message)
|
|
228
|
-
continue
|
|
229
|
-
extracting_files_message = (
|
|
230
|
-
"[local_backup_lib]"
|
|
231
|
-
+ f" Extracting files from '{folder_name} ".center(15, "*")
|
|
232
|
-
)
|
|
233
|
-
self.log_history.append(extracting_files_message)
|
|
234
|
-
self.logger.debug(extracting_files_message)
|
|
235
|
-
for file_name in self.grouped_files_by_folder[folder_name]:
|
|
236
|
-
tasks.append(self._upload_and_log_progress_task(folder_name, file_name))
|
|
252
|
+
tasks = await self._generate_tasks()
|
|
237
253
|
|
|
238
254
|
# Execution of multiple asynchronous tasks for files migration.
|
|
239
255
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
240
|
-
success = calculate_percentage_uploaded(results, self.total_files)
|
|
256
|
+
success = calculate_percentage_uploaded(results, self.total_files) # type: ignore
|
|
257
|
+
|
|
241
258
|
if success < 100.0:
|
|
242
259
|
await self.retry_upload_failed_files(results)
|
|
243
260
|
else:
|
|
@@ -254,4 +271,4 @@ class UploadBackupToSharepointUsecase:
|
|
|
254
271
|
self.log_history.append(finished_backup_message)
|
|
255
272
|
|
|
256
273
|
await self._save_log_history()
|
|
257
|
-
return parse_execute_response(results)
|
|
274
|
+
return parse_execute_response(results) # type: ignore
|
|
@@ -1,10 +1,10 @@
|
|
|
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=0_YzFLvv7asSZJ_K4FFqLeJsCFMMHRpHTQehmUok8b8,2326
|
|
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
|
-
saviialib/general_types/error_types/api/epii_api_error_types.py,sha256=
|
|
7
|
+
saviialib/general_types/error_types/api/epii_api_error_types.py,sha256=iprpNvVoNA3vakMm7-dQdjCv7ZrRs6tRiXK1uaV3DNU,3049
|
|
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
10
|
saviialib/libs/directory_client/__init__.py,sha256=ys07nzp74fHew2mUkbGpntp5w4t_PnhZIS6D4_mJw2A,162
|
|
@@ -19,36 +19,35 @@ saviialib/libs/files_client/files_client_contract.py,sha256=fYvd68IMpc1OFkxbzNSm
|
|
|
19
19
|
saviialib/libs/files_client/types/files_client_types.py,sha256=8OHm4nvZTW9K3ryeIUvthE_Cj7wF4zVcqG0KCi_vQIU,718
|
|
20
20
|
saviialib/libs/ftp_client/__init__.py,sha256=dW2Yutgc7mJJJzgKLhWKXMgQ6KIWJYfFa1sGpjHH5xU,191
|
|
21
21
|
saviialib/libs/ftp_client/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
-
saviialib/libs/ftp_client/clients/aioftp_client.py,sha256=
|
|
23
|
-
saviialib/libs/ftp_client/ftp_client.py,sha256=
|
|
24
|
-
saviialib/libs/ftp_client/ftp_client_contract.py,sha256=
|
|
22
|
+
saviialib/libs/ftp_client/clients/aioftp_client.py,sha256=npkB2IBTTcHg-_zXTv1OlRagxR6irT33TvFVSvtPqXU,1779
|
|
23
|
+
saviialib/libs/ftp_client/ftp_client.py,sha256=UWpuIrfO27A1M40YaBvAUdkdwPYJ4Ty4q55x7H4y1F8,844
|
|
24
|
+
saviialib/libs/ftp_client/ftp_client_contract.py,sha256=tymkugDzsJ5PzUXIaSkwX1h7T0naR15qAkjrqswqDyM,338
|
|
25
25
|
saviialib/libs/ftp_client/types/__init__.py,sha256=syfwf9feP4QK7fkCTfl4j8l11ic-jHtfi1DE2chaWbs,155
|
|
26
26
|
saviialib/libs/ftp_client/types/ftp_client_types.py,sha256=e4SmYkewldulaD8ms2q75zVgLFXyBxBqoa_L-IQOmso,256
|
|
27
27
|
saviialib/libs/sharepoint_client/__init__.py,sha256=v7h-cNsK-BaPp-hTU3NWRNXYRD9ztU-hsCk0eNRPIKA,334
|
|
28
|
-
saviialib/libs/sharepoint_client/clients/sharepoint_rest_api.py,sha256=
|
|
29
|
-
saviialib/libs/sharepoint_client/sharepoint_client.py,sha256=
|
|
28
|
+
saviialib/libs/sharepoint_client/clients/sharepoint_rest_api.py,sha256=oGqNQcPL0HX-WYqO26JuIi9PDYPIZAoyDYMl965L_0c,5295
|
|
29
|
+
saviialib/libs/sharepoint_client/sharepoint_client.py,sha256=LMQFti0Ulc4FCPQy17mrTLNJkO2Qp3i-KR0VbjPyPG4,1665
|
|
30
30
|
saviialib/libs/sharepoint_client/sharepoint_client_contract.py,sha256=xqNHzCjp7GvUGGUox9YTJj2QJgTc5819t2etOk8X26o,485
|
|
31
31
|
saviialib/libs/sharepoint_client/types/sharepoint_client_types.py,sha256=OmPlCJ9rLrAFBeG6aDp5cxMiQ5BZlDyGVx5S4GN4aqg,414
|
|
32
32
|
saviialib/libs/zero_dependency/utils/datetime_utils.py,sha256=NFPHxOTuCtfkYjUnsbRqw9ZK87UGAK-Eira2CwG8rJ8,754
|
|
33
33
|
saviialib/services/epii/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
-
saviialib/services/epii/api.py,sha256=
|
|
34
|
+
saviialib/services/epii/api.py,sha256=kd4kL475C8CtEj0Yg8Eg1ig8J90GbIbdl9A8pqPtc58,3901
|
|
35
35
|
saviialib/services/epii/controllers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
36
|
saviialib/services/epii/controllers/types/__init__.py,sha256=xzky-oTSojLNkWETp_k8a4dcXYvYSQY0VhWo23Yhb8U,195
|
|
37
|
-
saviialib/services/epii/controllers/types/update_thies_data_types.py,sha256=
|
|
38
|
-
saviialib/services/epii/controllers/types/upload_backup_to_sharepoint_types.py,sha256=
|
|
39
|
-
saviialib/services/epii/controllers/update_thies_data.py,sha256=
|
|
40
|
-
saviialib/services/epii/controllers/upload_backup_to_sharepoint.py,sha256=
|
|
41
|
-
saviialib/services/epii/use_cases/constants/
|
|
42
|
-
saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py,sha256=8JwqAU1KP-WMUcZ67oSQY1_5I47jlaJnOpwKyTKdN_Y,208
|
|
37
|
+
saviialib/services/epii/controllers/types/update_thies_data_types.py,sha256=kmt18vq7RLEAfIJj9MYz62fJH9etuU1WqZJ5MYmjiIg,448
|
|
38
|
+
saviialib/services/epii/controllers/types/upload_backup_to_sharepoint_types.py,sha256=5mDMLy3J5grACl1ezBGYZPOyhIkWYeIWWBOklaP2IlQ,471
|
|
39
|
+
saviialib/services/epii/controllers/update_thies_data.py,sha256=Bq00uqcu26Ro1gCpFGqNys88kzMTnnJvEmxOBitLUks,4840
|
|
40
|
+
saviialib/services/epii/controllers/upload_backup_to_sharepoint.py,sha256=7-ABo89yXhrWv-iOFjCkBGX-y_I62eFaOi1LtO5Gb4k,3817
|
|
41
|
+
saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py,sha256=erkn-3E8YwBMFs25o7exXoK7s73NdgP9IYDXeWzALcI,98
|
|
43
42
|
saviialib/services/epii/use_cases/types/__init__.py,sha256=u6fyodOEJE2j6FMqJux40Xf9ccYAi-UUYxqT-Kzc0kE,199
|
|
44
|
-
saviialib/services/epii/use_cases/types/update_thies_data_types.py,sha256=
|
|
45
|
-
saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py,sha256=
|
|
46
|
-
saviialib/services/epii/use_cases/update_thies_data.py,sha256=
|
|
47
|
-
saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py,sha256=
|
|
43
|
+
saviialib/services/epii/use_cases/types/update_thies_data_types.py,sha256=VQM8oJxrwvmH7NeBpJ6JYZtDV_MujMRWwFazsSgHY_M,493
|
|
44
|
+
saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py,sha256=J_sGhqSaPoMZA0GIrzCx6pmgSKgIkGi0uyrsltU_H8w,320
|
|
45
|
+
saviialib/services/epii/use_cases/update_thies_data.py,sha256=EPzRCo4X7khTp7afX3jCpHdQTCjk7a-PmYnm4Br2vTI,8246
|
|
46
|
+
saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py,sha256=UZ2Pe_mavdquYG00_GYtANY4nn0wHjT_Z0HLUvtfW2c,11143
|
|
48
47
|
saviialib/services/epii/utils/__init__.py,sha256=cYt2tvq65_OMjFaqb8-CCC7IGCQgFd4ziEUWJV7s1iY,98
|
|
49
48
|
saviialib/services/epii/utils/update_thies_data_utils.py,sha256=EpjYWXqyHxJ-dO3MHhdXp-rGV7WyUckeFko-nnfnNac,555
|
|
50
49
|
saviialib/services/epii/utils/upload_backup_to_sharepoint_utils.py,sha256=hEeV4_kcG8YL6t_3V8AlhgDHtHiUNsdYpilfgTLaQMc,3528
|
|
51
|
-
saviialib-0.
|
|
52
|
-
saviialib-0.
|
|
53
|
-
saviialib-0.
|
|
54
|
-
saviialib-0.
|
|
50
|
+
saviialib-0.11.0.dist-info/LICENSE,sha256=NWpf6b38xgBWPBo5HZsCbdfp9hZSliEbRqWQgm0fkOo,1076
|
|
51
|
+
saviialib-0.11.0.dist-info/METADATA,sha256=diHGwoPOT3vsY78ni4-ON6Aom5jTnWgQwO3QPY3E-z4,4083
|
|
52
|
+
saviialib-0.11.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
53
|
+
saviialib-0.11.0.dist-info/RECORD,,
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
SHAREPOINT_BASE_URL = "/sites/uc365_CentrosyEstacionesRegionalesUC/Shared%20Documents/General/Test_Raspberry/THIES"
|
|
2
|
-
SHAREPOINT_THIES_FOLDERS = ["AVG", "EXT"]
|
|
3
|
-
|
|
4
|
-
FTP_SERVER_PATH_AVG_FILES = "ftp/thies/BINFILES/ARCH_AV1"
|
|
5
|
-
FTP_SERVER_PATH_EXT_FILES = "ftp/thies/BINFILES/ARCH_EX1"
|
|
File without changes
|
|
File without changes
|