saviialib 1.0.0__tar.gz → 1.0.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-1.0.0 → saviialib-1.0.1}/PKG-INFO +1 -1
- {saviialib-1.0.0 → saviialib-1.0.1}/pyproject.toml +1 -1
- saviialib-1.0.1/src/saviialib/libs/ftp_client/clients/ftplib_client.py +58 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/ftp_client.py +4 -1
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/sharepoint_client/__init__.py +2 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/sharepoint_client/clients/sharepoint_rest_api.py +21 -1
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/sharepoint_client/sharepoint_client.py +4 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/sharepoint_client/sharepoint_client_contract.py +5 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/sharepoint_client/types/sharepoint_client_types.py +5 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/zero_dependency/utils/datetime_utils.py +1 -1
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/update_thies_data.py +1 -1
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/upload_backup_to_sharepoint.py +37 -13
- {saviialib-1.0.0 → saviialib-1.0.1}/LICENSE +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/README.md +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/api/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/api/epii_api_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/api/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/api/epii_api_error_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/common/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/common/common_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/directory_client/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/directory_client/client/os_client.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/directory_client/directory_client.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/directory_client/directory_client_contract.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/directory_client/types/directory_client_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/clients/aiofiles_client.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/files_client.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/files_client_contract.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/types/files_client_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/clients/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/clients/aioftp_client.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/ftp_client_contract.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/types/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/ftp_client/types/ftp_client_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/api.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/types/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/types/update_thies_data_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/types/upload_backup_to_sharepoint_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/update_thies_data.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/upload_backup_to_sharepoint.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/constants/upload_backup_to_sharepoint_constants.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/types/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/types/update_thies_data_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/types/upload_backup_to_sharepoint_types.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/utils/__init__.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/utils/update_thies_data_utils.py +0 -0
- {saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/utils/upload_backup_to_sharepoint_utils.py +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import ftplib
|
|
2
|
+
import asyncio
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
from saviialib.libs.ftp_client.ftp_client_contract import (
|
|
5
|
+
FTPClientContract,
|
|
6
|
+
)
|
|
7
|
+
from saviialib.libs.ftp_client.types.ftp_client_types import (
|
|
8
|
+
FtpClientInitArgs,
|
|
9
|
+
FtpListFilesArgs,
|
|
10
|
+
FtpReadFileArgs,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FtplibClient(FTPClientContract):
|
|
15
|
+
def __init__(self, args: FtpClientInitArgs) -> None:
|
|
16
|
+
self.host = args.config.ftp_host
|
|
17
|
+
self.port = args.config.ftp_port
|
|
18
|
+
self.password = args.config.ftp_password
|
|
19
|
+
self.user = args.config.ftp_user
|
|
20
|
+
self.client = ftplib.FTP(host=self.host, user=self.user, passwd=self.password)
|
|
21
|
+
|
|
22
|
+
async def _async_start(self) -> None:
|
|
23
|
+
try:
|
|
24
|
+
await asyncio.to_thread(self.client.login, self.user, self.password)
|
|
25
|
+
except OSError:
|
|
26
|
+
raise ConnectionRefusedError(
|
|
27
|
+
f"{self.host}:{self.port} isn't active. "
|
|
28
|
+
"Please ensure the server is running and accessible."
|
|
29
|
+
)
|
|
30
|
+
except Exception as error:
|
|
31
|
+
raise ConnectionError(
|
|
32
|
+
f"General connection for {self.host}:{self.port}.", error.__str__()
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
async def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
36
|
+
try:
|
|
37
|
+
EXCLUDED_NAMES = [".", ".."]
|
|
38
|
+
await self._async_start()
|
|
39
|
+
await asyncio.to_thread(self.client.cwd, args.path)
|
|
40
|
+
filenames = await asyncio.to_thread(self.client.nlst, args.path)
|
|
41
|
+
return [
|
|
42
|
+
filename for filename in filenames if filename not in EXCLUDED_NAMES
|
|
43
|
+
]
|
|
44
|
+
except Exception as error:
|
|
45
|
+
raise ConnectionAbortedError(error)
|
|
46
|
+
|
|
47
|
+
async def read_file(self, args: FtpReadFileArgs) -> bytes:
|
|
48
|
+
await self._async_start()
|
|
49
|
+
try:
|
|
50
|
+
file_content = BytesIO()
|
|
51
|
+
await asyncio.to_thread(
|
|
52
|
+
self.client.retrbinary, "RETR " + args.file_path, file_content.write
|
|
53
|
+
)
|
|
54
|
+
await asyncio.to_thread(file_content.seek, 0)
|
|
55
|
+
file_bytes = await asyncio.to_thread(file_content.read)
|
|
56
|
+
return file_bytes
|
|
57
|
+
except Exception as error:
|
|
58
|
+
raise FileNotFoundError(f"File not found: {args.file_path}") from error
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from .clients.aioftp_client import AioFTPClient
|
|
2
|
+
from .clients.ftplib_client import FtplibClient
|
|
2
3
|
from .ftp_client_contract import FTPClientContract
|
|
3
4
|
from .types.ftp_client_types import FtpClientInitArgs, FtpListFilesArgs, FtpReadFileArgs
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class FTPClient(FTPClientContract):
|
|
7
|
-
CLIENTS = {"aioftp_client"}
|
|
8
|
+
CLIENTS = {"aioftp_client", "ftplib_client"}
|
|
8
9
|
|
|
9
10
|
def __init__(self, args: FtpClientInitArgs) -> None:
|
|
10
11
|
if args.client_name not in FTPClient.CLIENTS:
|
|
@@ -13,6 +14,8 @@ class FTPClient(FTPClientContract):
|
|
|
13
14
|
|
|
14
15
|
if args.client_name == "aioftp_client":
|
|
15
16
|
self.client_obj = AioFTPClient(args)
|
|
17
|
+
elif args.client_name == "ftplib_client":
|
|
18
|
+
self.client_obj = FtplibClient(args)
|
|
16
19
|
self.client_name = args.client_name
|
|
17
20
|
|
|
18
21
|
async def list_files(self, args: FtpListFilesArgs) -> list[str]:
|
|
@@ -4,6 +4,7 @@ from .types.sharepoint_client_types import (
|
|
|
4
4
|
SpListFilesArgs,
|
|
5
5
|
SpListFoldersArgs,
|
|
6
6
|
SpUploadFileArgs,
|
|
7
|
+
SpCreateFolderArgs,
|
|
7
8
|
)
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
@@ -12,4 +13,5 @@ __all__ = [
|
|
|
12
13
|
"SpListFilesArgs",
|
|
13
14
|
"SpListFoldersArgs",
|
|
14
15
|
"SpUploadFileArgs",
|
|
16
|
+
"SpCreateFolderArgs",
|
|
15
17
|
]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Any
|
|
2
|
-
|
|
2
|
+
import json
|
|
3
3
|
from aiohttp import ClientError, ClientSession
|
|
4
4
|
from dotenv import load_dotenv
|
|
5
5
|
|
|
@@ -10,6 +10,7 @@ from saviialib.libs.sharepoint_client.types.sharepoint_client_types import (
|
|
|
10
10
|
SpListFilesArgs,
|
|
11
11
|
SpListFoldersArgs,
|
|
12
12
|
SpUploadFileArgs,
|
|
13
|
+
SpCreateFolderArgs,
|
|
13
14
|
SharepointClientInitArgs,
|
|
14
15
|
)
|
|
15
16
|
|
|
@@ -134,3 +135,22 @@ class SharepointRestAPI(SharepointClientContract):
|
|
|
134
135
|
return await response.json()
|
|
135
136
|
except ClientError as error:
|
|
136
137
|
raise ConnectionError(error) from error
|
|
138
|
+
|
|
139
|
+
async def create_folder(self, args: SpCreateFolderArgs):
|
|
140
|
+
try:
|
|
141
|
+
# Load form digest value
|
|
142
|
+
form_digest_value = await self._load_form_digest_value()
|
|
143
|
+
headers = {
|
|
144
|
+
**self.base_headers,
|
|
145
|
+
"X-RequestDigest": form_digest_value,
|
|
146
|
+
}
|
|
147
|
+
body = {"ServerRelativeUrl": f"{args.folder_relative_url}"}
|
|
148
|
+
endpoint = "web/folders"
|
|
149
|
+
response = await self.session.post(
|
|
150
|
+
endpoint.lstrip("/"), data=json.dumps(body), headers=headers
|
|
151
|
+
)
|
|
152
|
+
response.raise_for_status()
|
|
153
|
+
response_json = await response.json()
|
|
154
|
+
return response_json
|
|
155
|
+
except ClientError as error:
|
|
156
|
+
raise ConnectionError(error) from error
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/sharepoint_client/sharepoint_client.py
RENAMED
|
@@ -5,6 +5,7 @@ from .types.sharepoint_client_types import (
|
|
|
5
5
|
SpListFilesArgs,
|
|
6
6
|
SpListFoldersArgs,
|
|
7
7
|
SpUploadFileArgs,
|
|
8
|
+
SpCreateFolderArgs,
|
|
8
9
|
)
|
|
9
10
|
|
|
10
11
|
|
|
@@ -52,3 +53,6 @@ class SharepointClient(SharepointClientContract):
|
|
|
52
53
|
|
|
53
54
|
async def upload_file(self, args: SpUploadFileArgs) -> dict:
|
|
54
55
|
return await self.client_obj.upload_file(args)
|
|
56
|
+
|
|
57
|
+
async def create_folder(self, args: SpCreateFolderArgs) -> dict:
|
|
58
|
+
return await self.client_obj.create_folder(args)
|
|
@@ -4,6 +4,7 @@ from .types.sharepoint_client_types import (
|
|
|
4
4
|
SpListFilesArgs,
|
|
5
5
|
SpListFoldersArgs,
|
|
6
6
|
SpUploadFileArgs,
|
|
7
|
+
SpCreateFolderArgs,
|
|
7
8
|
)
|
|
8
9
|
|
|
9
10
|
|
|
@@ -19,3 +20,7 @@ class SharepointClientContract(ABC):
|
|
|
19
20
|
@abstractmethod
|
|
20
21
|
async def upload_file(self, args: SpUploadFileArgs) -> dict:
|
|
21
22
|
pass
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
async def create_folder(self, args: SpCreateFolderArgs) -> dict:
|
|
26
|
+
pass
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/use_cases/update_thies_data.py
RENAMED
|
@@ -59,7 +59,7 @@ class UpdateThiesDataUseCase:
|
|
|
59
59
|
def _initialize_thies_ftp_client(self, config: FtpClientConfig) -> FTPClient:
|
|
60
60
|
"""Initialize the FTP client."""
|
|
61
61
|
try:
|
|
62
|
-
return FTPClient(FtpClientInitArgs(config, client_name="
|
|
62
|
+
return FTPClient(FtpClientInitArgs(config, client_name="ftplib_client"))
|
|
63
63
|
except RuntimeError as error:
|
|
64
64
|
raise FtpClientError(error)
|
|
65
65
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from time import time
|
|
3
|
+
from saviialib.libs.zero_dependency.utils.datetime_utils import today, datetime_to_str
|
|
3
4
|
from logging import Logger
|
|
4
5
|
from saviialib.general_types.error_types.api.epii_api_error_types import (
|
|
5
6
|
BackupEmptyError,
|
|
@@ -20,7 +21,7 @@ from saviialib.libs.sharepoint_client import (
|
|
|
20
21
|
SharepointClient,
|
|
21
22
|
SharepointClientInitArgs,
|
|
22
23
|
SpUploadFileArgs,
|
|
23
|
-
|
|
24
|
+
SpCreateFolderArgs,
|
|
24
25
|
)
|
|
25
26
|
from saviialib.services.epii.utils.upload_backup_to_sharepoint_utils import (
|
|
26
27
|
calculate_percentage_uploaded,
|
|
@@ -40,6 +41,7 @@ class UploadBackupToSharepointUsecase:
|
|
|
40
41
|
self.sharepoint_config = input.sharepoint_config
|
|
41
42
|
self.local_backup_source_path = input.local_backup_source_path
|
|
42
43
|
self.sharepoint_destination_path = input.sharepoint_destination_path
|
|
44
|
+
|
|
43
45
|
self.files_client = self._initialize_files_client()
|
|
44
46
|
self.dir_client = self._initialize_directory_client()
|
|
45
47
|
self.log_history = []
|
|
@@ -61,7 +63,28 @@ class UploadBackupToSharepointUsecase:
|
|
|
61
63
|
def _initialize_files_client(self):
|
|
62
64
|
return FilesClient(FilesClientInitArgs(client_name="aiofiles_client"))
|
|
63
65
|
|
|
66
|
+
async def _initialize_backup_base_folder(self):
|
|
67
|
+
local_backup_name = (
|
|
68
|
+
f"/local-backup-{datetime_to_str(today(), date_format='%m-%d-%Y')}"
|
|
69
|
+
)
|
|
70
|
+
local_backup_destination_path = (
|
|
71
|
+
self.sharepoint_destination_path + local_backup_name
|
|
72
|
+
)
|
|
73
|
+
async with self.sharepoint_client:
|
|
74
|
+
await self.sharepoint_client.create_folder(
|
|
75
|
+
SpCreateFolderArgs(folder_relative_url=local_backup_destination_path)
|
|
76
|
+
)
|
|
77
|
+
self.sharepoint_destination_path = local_backup_destination_path
|
|
78
|
+
base_folder_message = (
|
|
79
|
+
"[local_backup_lib] Creating base folder" + local_backup_name
|
|
80
|
+
)
|
|
81
|
+
self.logger.info(base_folder_message)
|
|
82
|
+
self.log_history.append(base_folder_message)
|
|
83
|
+
|
|
64
84
|
async def _validate_backup_structure(self):
|
|
85
|
+
# Initialize the backup folder
|
|
86
|
+
await self._initialize_backup_base_folder()
|
|
87
|
+
|
|
65
88
|
# Check if the local path exists in the main directory
|
|
66
89
|
if not await self.dir_client.path_exists(self.local_backup_source_path):
|
|
67
90
|
raise BackupSourcePathError(
|
|
@@ -74,20 +97,21 @@ class UploadBackupToSharepointUsecase:
|
|
|
74
97
|
else []
|
|
75
98
|
)
|
|
76
99
|
async with self.sharepoint_client: # type: ignore
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
100
|
+
for local_dir in local_directories:
|
|
101
|
+
create_message = (
|
|
102
|
+
f"[local_backup_lib] Creating a new directory '{local_dir}'."
|
|
103
|
+
)
|
|
81
104
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
reason=f"Folder '{local_dir}' does not exist in SharePoint destination path '{self.sharepoint_destination_path}'."
|
|
105
|
+
self.log_history.append(create_message)
|
|
106
|
+
await self.sharepoint_client.create_folder(
|
|
107
|
+
SpCreateFolderArgs(
|
|
108
|
+
folder_relative_url=self.sharepoint_destination_path
|
|
109
|
+
+ "/"
|
|
110
|
+
+ local_dir
|
|
111
|
+
)
|
|
90
112
|
)
|
|
113
|
+
self.logger.info("[local_backup_lib] %s", create_message)
|
|
114
|
+
self.log_history.append(f"[local_backup_lib] {create_message}")
|
|
91
115
|
|
|
92
116
|
# Check if the current folder only have files and each folder exist in Microsoft Sharepoint.
|
|
93
117
|
if self.total_files == 0:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/common/__init__.py
RENAMED
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/general_types/error_types/common/common_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/directory_client/directory_client_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/clients/aiofiles_client.py
RENAMED
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/files_client_contract.py
RENAMED
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/libs/files_client/types/files_client_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/types/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/controllers/update_thies_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{saviialib-1.0.0 → saviialib-1.0.1}/src/saviialib/services/epii/utils/update_thies_data_utils.py
RENAMED
|
File without changes
|
|
File without changes
|