data-sourcerer 0.1.1__py3-none-any.whl → 0.2.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.
- {data_sourcerer-0.1.1.dist-info → data_sourcerer-0.2.0.dist-info}/METADATA +24 -4
- {data_sourcerer-0.1.1.dist-info → data_sourcerer-0.2.0.dist-info}/RECORD +53 -50
- {data_sourcerer-0.1.1.dist-info → data_sourcerer-0.2.0.dist-info}/WHEEL +1 -1
- sourcerer/__init__.py +1 -1
- sourcerer/domain/access_credentials/entities.py +17 -0
- sourcerer/domain/access_credentials/exceptions.py +1 -1
- sourcerer/domain/access_credentials/repositories.py +1 -1
- sourcerer/domain/access_credentials/services.py +14 -2
- sourcerer/domain/file_system/exceptions.py +1 -1
- sourcerer/domain/file_system/services.py +2 -2
- sourcerer/domain/shared/entities.py +1 -0
- sourcerer/domain/storage_provider/entities.py +3 -4
- sourcerer/domain/storage_provider/exceptions.py +1 -1
- sourcerer/domain/storage_provider/services.py +13 -9
- sourcerer/infrastructure/access_credentials/exceptions.py +15 -2
- sourcerer/infrastructure/access_credentials/registry.py +3 -4
- sourcerer/infrastructure/access_credentials/services.py +141 -44
- sourcerer/infrastructure/db/models.py +1 -1
- sourcerer/infrastructure/file_system/exceptions.py +9 -9
- sourcerer/infrastructure/file_system/services.py +16 -16
- sourcerer/infrastructure/storage_provider/exceptions.py +28 -8
- sourcerer/infrastructure/storage_provider/registry.py +2 -3
- sourcerer/infrastructure/storage_provider/services/__init__.py +0 -0
- sourcerer/infrastructure/storage_provider/services/azure.py +261 -0
- sourcerer/infrastructure/storage_provider/services/gcp.py +277 -0
- sourcerer/infrastructure/storage_provider/services/s3.py +290 -0
- sourcerer/infrastructure/utils.py +2 -4
- sourcerer/presentation/screens/critical_error/main.py +3 -4
- sourcerer/presentation/screens/file_system_finder/main.py +4 -4
- sourcerer/presentation/screens/file_system_finder/widgets/file_system_navigator.py +12 -12
- sourcerer/presentation/screens/main/main.py +57 -33
- sourcerer/presentation/screens/main/messages/delete_request.py +1 -2
- sourcerer/presentation/screens/main/messages/download_request.py +1 -2
- sourcerer/presentation/screens/main/mixins/resize_containers_watcher_mixin.py +3 -3
- sourcerer/presentation/screens/main/widgets/gradient.py +2 -5
- sourcerer/presentation/screens/main/widgets/resizing_rule.py +1 -1
- sourcerer/presentation/screens/main/widgets/storage_content.py +12 -13
- sourcerer/presentation/screens/main/widgets/storage_list_sidebar.py +8 -6
- sourcerer/presentation/screens/preview_content/main.py +15 -4
- sourcerer/presentation/screens/preview_content/styles.tcss +2 -1
- sourcerer/presentation/screens/provider_creds_list/main.py +2 -2
- sourcerer/presentation/screens/provider_creds_registration/main.py +26 -11
- sourcerer/presentation/screens/question/main.py +1 -1
- sourcerer/presentation/screens/shared/containers.py +1 -1
- sourcerer/presentation/screens/shared/widgets/labeled_input.py +1 -1
- sourcerer/presentation/screens/storage_action_progress/main.py +34 -20
- sourcerer/presentation/screens/storage_action_progress/styles.tcss +11 -0
- sourcerer/presentation/utils.py +7 -3
- sourcerer/settings.py +4 -0
- sourcerer/utils.py +2 -2
- sourcerer/infrastructure/storage_provider/services.py +0 -509
- {data_sourcerer-0.1.1.dist-info → data_sourcerer-0.2.0.dist-info}/entry_points.txt +0 -0
- {data_sourcerer-0.1.1.dist-info → data_sourcerer-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {data_sourcerer-0.1.1.dist-info → data_sourcerer-0.2.0.dist-info}/top_level.txt +0 -0
@@ -9,20 +9,28 @@ import json
|
|
9
9
|
from abc import ABC
|
10
10
|
|
11
11
|
import boto3
|
12
|
+
from azure.identity import ClientSecretCredential
|
12
13
|
from dependency_injector.wiring import Provide
|
13
14
|
from google.cloud import storage
|
14
15
|
|
15
|
-
from sourcerer.domain.access_credentials.entities import
|
16
|
+
from sourcerer.domain.access_credentials.entities import (
|
17
|
+
AzureCredentials,
|
18
|
+
Boto3Credentials,
|
19
|
+
Credentials,
|
20
|
+
)
|
16
21
|
from sourcerer.domain.access_credentials.repositories import BaseCredentialsRepository
|
17
22
|
from sourcerer.domain.access_credentials.services import (
|
18
|
-
BaseAccessCredentialsService,
|
19
23
|
AuthField,
|
24
|
+
BaseAccessCredentialsService,
|
20
25
|
)
|
21
26
|
from sourcerer.domain.shared.entities import StorageProvider
|
22
|
-
from sourcerer.infrastructure.access_credentials.exceptions import
|
27
|
+
from sourcerer.infrastructure.access_credentials.exceptions import (
|
28
|
+
CredentialsAuthError,
|
29
|
+
MissingAuthFieldsError,
|
30
|
+
)
|
23
31
|
from sourcerer.infrastructure.access_credentials.registry import (
|
24
|
-
access_credentials_method,
|
25
32
|
AccessCredentialsMethod,
|
33
|
+
access_credentials_method,
|
26
34
|
)
|
27
35
|
from sourcerer.infrastructure.utils import generate_uuid
|
28
36
|
from sourcerer.presentation.di_container import DiContainer
|
@@ -116,6 +124,22 @@ class AccessCredentialsService(BaseAccessCredentialsService, ABC):
|
|
116
124
|
"""
|
117
125
|
super().__init__(credentials_repo)
|
118
126
|
|
127
|
+
@classmethod
|
128
|
+
def validate_auth_fields_values(cls, auth_fields: dict) -> None:
|
129
|
+
"""
|
130
|
+
Validate authentication fields.
|
131
|
+
|
132
|
+
Args:
|
133
|
+
auth_fields (dict): Dictionary containing authentication field,
|
134
|
+
where keys are field names and values are field values
|
135
|
+
|
136
|
+
Raises:
|
137
|
+
MissingAuthFieldsError: If any required authentication fields are missing
|
138
|
+
"""
|
139
|
+
for field in cls.auth_fields():
|
140
|
+
if field.required and field.key not in auth_fields:
|
141
|
+
raise MissingAuthFieldsError(f"Missing required field: {field.key}")
|
142
|
+
|
119
143
|
|
120
144
|
class S3AccessCredentialsService(AccessCredentialsService, ABC):
|
121
145
|
"""
|
@@ -176,23 +200,26 @@ class S3AccessKeySecretKeyPair(S3AccessCredentialsService):
|
|
176
200
|
Returns:
|
177
201
|
boto3.Session: Authenticated boto3 session
|
178
202
|
"""
|
179
|
-
|
203
|
+
try:
|
204
|
+
credentials: dict = json.loads(credentials)
|
180
205
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
206
|
+
session_args = {
|
207
|
+
"aws_access_key_id": credentials.get("aws_access_key_id"),
|
208
|
+
"aws_secret_access_key": credentials.get("aws_secret_access_key"),
|
209
|
+
}
|
185
210
|
|
186
|
-
|
187
|
-
|
211
|
+
if region := credentials.get("region"):
|
212
|
+
session_args["region_name"] = region
|
188
213
|
|
189
|
-
|
214
|
+
session = boto3.Session(**session_args)
|
190
215
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
216
|
+
return Boto3Credentials(
|
217
|
+
session=session,
|
218
|
+
endpoint_url=credentials.get("endpoint_url", None),
|
219
|
+
signature_version=credentials.get("signature_version", None),
|
220
|
+
)
|
221
|
+
except Exception as e:
|
222
|
+
raise CredentialsAuthError("Failed to authenticate") from e
|
196
223
|
|
197
224
|
@classmethod
|
198
225
|
def auth_fields(cls):
|
@@ -260,15 +287,18 @@ class S3ProfileName(S3AccessCredentialsService):
|
|
260
287
|
Returns:
|
261
288
|
boto3.Session: Authenticated boto3 session
|
262
289
|
"""
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
290
|
+
try:
|
291
|
+
credentials: dict = json.loads(credentials)
|
292
|
+
session = boto3.Session(profile_name=credentials.get("profile_name"))
|
293
|
+
return Boto3Credentials(
|
294
|
+
session=session,
|
295
|
+
endpoint_url=credentials.get("endpoint_url"),
|
296
|
+
)
|
297
|
+
except Exception as e:
|
298
|
+
raise CredentialsAuthError("Failed to authenticate") from e
|
269
299
|
|
270
300
|
@classmethod
|
271
|
-
def auth_fields(cls):
|
301
|
+
def auth_fields(cls) -> list[AuthField]:
|
272
302
|
"""
|
273
303
|
Get list of authentication fields.
|
274
304
|
|
@@ -286,15 +316,15 @@ class S3ProfileName(S3AccessCredentialsService):
|
|
286
316
|
)
|
287
317
|
class GCPCredentialsService(AccessCredentialsService):
|
288
318
|
"""
|
289
|
-
Google Cloud Platform
|
319
|
+
Google Cloud Platform json credentials service.
|
290
320
|
|
291
321
|
This class provides methods for storing, retrieving, and authenticating
|
292
|
-
with GCP using
|
322
|
+
with GCP using credentials.
|
293
323
|
"""
|
294
324
|
|
295
325
|
def store(self, name, credentials: dict):
|
296
326
|
"""
|
297
|
-
Store GCP
|
327
|
+
Store GCP json credentials.
|
298
328
|
|
299
329
|
Args:
|
300
330
|
name (str): Name identifier for the credentials
|
@@ -357,22 +387,6 @@ class GCPCredentialsService(AccessCredentialsService):
|
|
357
387
|
except json.JSONDecodeError as e:
|
358
388
|
raise ValueError("Invalid service account JSON format") from e
|
359
389
|
|
360
|
-
# Validate required fields for service account
|
361
|
-
required_fields = [
|
362
|
-
"type",
|
363
|
-
"project_id",
|
364
|
-
"private_key_id",
|
365
|
-
"private_key",
|
366
|
-
"client_email",
|
367
|
-
]
|
368
|
-
missing_fields = [
|
369
|
-
field for field in required_fields if field not in service_acc_info
|
370
|
-
]
|
371
|
-
if missing_fields:
|
372
|
-
raise ValueError(
|
373
|
-
f"Service account missing required fields: {', '.join(missing_fields)}"
|
374
|
-
)
|
375
|
-
|
376
390
|
# Create and return the authenticated client
|
377
391
|
return storage.Client.from_service_account_info(service_acc_info)
|
378
392
|
|
@@ -384,7 +398,7 @@ class GCPCredentialsService(AccessCredentialsService):
|
|
384
398
|
) from e
|
385
399
|
|
386
400
|
@classmethod
|
387
|
-
def auth_fields(cls):
|
401
|
+
def auth_fields(cls) -> list[AuthField]:
|
388
402
|
"""
|
389
403
|
Get list of authentication fields.
|
390
404
|
|
@@ -394,3 +408,86 @@ class GCPCredentialsService(AccessCredentialsService):
|
|
394
408
|
return [
|
395
409
|
AuthField("service_acc", "Service acc", True, True),
|
396
410
|
]
|
411
|
+
|
412
|
+
|
413
|
+
@access_credentials_method(
|
414
|
+
AccessCredentialsMethod(StorageProvider.AzureStorage, "Client Secret Credentials")
|
415
|
+
)
|
416
|
+
class AzureClientSecretCredentialsService(AccessCredentialsService):
|
417
|
+
|
418
|
+
def store(self, name, credentials: dict):
|
419
|
+
"""
|
420
|
+
Store Azure client_id and secret_key_pair credentials.
|
421
|
+
|
422
|
+
Args:
|
423
|
+
name (str): Name identifier for the credentials
|
424
|
+
credentials (dict): Dictionary containing Azure application credential information
|
425
|
+
"""
|
426
|
+
self.credentials_repo.create(
|
427
|
+
Credentials(
|
428
|
+
uuid=generate_uuid(),
|
429
|
+
name=name,
|
430
|
+
provider=StorageProvider.AzureStorage,
|
431
|
+
credentials_type="Client Secret Credentials",
|
432
|
+
credentials=json.dumps(credentials),
|
433
|
+
active=True,
|
434
|
+
)
|
435
|
+
)
|
436
|
+
|
437
|
+
def extract(self, uuid):
|
438
|
+
"""
|
439
|
+
Extract credentials by UUID.
|
440
|
+
|
441
|
+
Args:
|
442
|
+
uuid (str): UUID of the credentials to extract
|
443
|
+
|
444
|
+
Returns:
|
445
|
+
Credentials: The credentials object
|
446
|
+
"""
|
447
|
+
return self.credentials_repo.get(uuid)
|
448
|
+
|
449
|
+
def authenticate(self, credentials: str): # type: ignore
|
450
|
+
try:
|
451
|
+
# Parse the outer JSON structure
|
452
|
+
parsed_credentials = json.loads(credentials)
|
453
|
+
subscription_id = parsed_credentials.get("subscription_id")
|
454
|
+
cloud_suffix = (
|
455
|
+
parsed_credentials.get("cloud_suffix") or "blob.core.windows.net"
|
456
|
+
)
|
457
|
+
|
458
|
+
client_credentials = ClientSecretCredential(
|
459
|
+
tenant_id=parsed_credentials.get("tenant_id"),
|
460
|
+
client_id=parsed_credentials.get("client_id"),
|
461
|
+
client_secret=parsed_credentials.get("client_secret"),
|
462
|
+
)
|
463
|
+
|
464
|
+
return AzureCredentials(
|
465
|
+
credentials=client_credentials,
|
466
|
+
subscription_id=subscription_id,
|
467
|
+
cloud_suffix=cloud_suffix,
|
468
|
+
)
|
469
|
+
|
470
|
+
except json.JSONDecodeError as e:
|
471
|
+
raise CredentialsAuthError(f"Invalid credentials format: {str(e)}") from e
|
472
|
+
except Exception as e:
|
473
|
+
raise CredentialsAuthError(
|
474
|
+
f"Failed to authenticate with Azure: {str(e)}"
|
475
|
+
) from e
|
476
|
+
|
477
|
+
@classmethod
|
478
|
+
def auth_fields(cls) -> list[AuthField]:
|
479
|
+
"""
|
480
|
+
Get list of authentication fields.
|
481
|
+
|
482
|
+
Returns:
|
483
|
+
List[AuthField]: List of authentication field definitions
|
484
|
+
"""
|
485
|
+
return [
|
486
|
+
AuthField("subscription_id", "Subscription Id", True),
|
487
|
+
AuthField("tenant_id", "Tenant Id", True),
|
488
|
+
AuthField("client_id", "Client Id", True),
|
489
|
+
AuthField("client_secret", "Client Secret", True),
|
490
|
+
AuthField(
|
491
|
+
"cloud_suffix", "Cloud Suffix (default blob.core.windows.net)", False
|
492
|
+
),
|
493
|
+
]
|
@@ -7,7 +7,7 @@ and their relationships.
|
|
7
7
|
|
8
8
|
from datetime import datetime
|
9
9
|
|
10
|
-
from sqlalchemy import
|
10
|
+
from sqlalchemy import Boolean, Column, DateTime, Integer, String
|
11
11
|
from sqlalchemy.orm import declarative_base
|
12
12
|
from sqlalchemy_utils.types.encrypted.encrypted_type import EncryptedType
|
13
13
|
|
@@ -5,10 +5,10 @@ This module defines exception classes for handling errors that occur
|
|
5
5
|
during interactions with the local file system.
|
6
6
|
"""
|
7
7
|
|
8
|
-
from sourcerer.domain.file_system.exceptions import
|
8
|
+
from sourcerer.domain.file_system.exceptions import BaseFileSystemError
|
9
9
|
|
10
10
|
|
11
|
-
class
|
11
|
+
class FileSystemGrepError(BaseFileSystemError):
|
12
12
|
"""
|
13
13
|
Custom exception for errors occurring during a file system search operation.
|
14
14
|
|
@@ -18,7 +18,7 @@ class FileSystemGrepException(BaseFileSystemException):
|
|
18
18
|
"""
|
19
19
|
|
20
20
|
|
21
|
-
class
|
21
|
+
class ReadFileError(BaseFileSystemError):
|
22
22
|
"""
|
23
23
|
Custom exception for errors occurring during a file system read operation.
|
24
24
|
|
@@ -28,7 +28,7 @@ class ReadFileException(BaseFileSystemException):
|
|
28
28
|
"""
|
29
29
|
|
30
30
|
|
31
|
-
class
|
31
|
+
class CreateFileError(BaseFileSystemError):
|
32
32
|
"""
|
33
33
|
Custom exception for errors occurring during a file system create file operation.
|
34
34
|
|
@@ -38,7 +38,7 @@ class CreateFileException(BaseFileSystemException):
|
|
38
38
|
"""
|
39
39
|
|
40
40
|
|
41
|
-
class
|
41
|
+
class CreateDirError(BaseFileSystemError):
|
42
42
|
"""
|
43
43
|
Custom exception for errors occurring during a file system create directory operation.
|
44
44
|
|
@@ -48,7 +48,7 @@ class CreateDirException(BaseFileSystemException):
|
|
48
48
|
"""
|
49
49
|
|
50
50
|
|
51
|
-
class
|
51
|
+
class MoveFileError(BaseFileSystemError):
|
52
52
|
"""
|
53
53
|
Exception raised for errors during file move operation.
|
54
54
|
|
@@ -59,7 +59,7 @@ class MoveFileException(BaseFileSystemException):
|
|
59
59
|
"""
|
60
60
|
|
61
61
|
|
62
|
-
class
|
62
|
+
class ListDirError(BaseFileSystemError):
|
63
63
|
"""
|
64
64
|
Custom exception for errors occurring during a file system list directory operation.
|
65
65
|
|
@@ -69,7 +69,7 @@ class ListDirException(BaseFileSystemException):
|
|
69
69
|
"""
|
70
70
|
|
71
71
|
|
72
|
-
class
|
72
|
+
class DeleteFileError(BaseFileSystemError):
|
73
73
|
"""
|
74
74
|
Custom exception for errors occurring during a file system delete file operation.
|
75
75
|
|
@@ -79,7 +79,7 @@ class DeleteFileException(BaseFileSystemException):
|
|
79
79
|
"""
|
80
80
|
|
81
81
|
|
82
|
-
class
|
82
|
+
class DeleteDirError(BaseFileSystemError):
|
83
83
|
"""
|
84
84
|
Custom exception for errors occurring during a file system delete directory operation.
|
85
85
|
|
@@ -10,8 +10,8 @@ from pathlib import Path
|
|
10
10
|
from sourcerer.domain.file_system.entities import ListDirOutput
|
11
11
|
from sourcerer.domain.file_system.services import BaseFileSystemService
|
12
12
|
from sourcerer.infrastructure.file_system.exceptions import (
|
13
|
-
|
14
|
-
|
13
|
+
ListDirError,
|
14
|
+
ReadFileError,
|
15
15
|
)
|
16
16
|
from sourcerer.infrastructure.utils import custom_sort_key
|
17
17
|
|
@@ -56,18 +56,18 @@ class FileSystemService(BaseFileSystemService):
|
|
56
56
|
str: The processed data extracted from the file.
|
57
57
|
|
58
58
|
Raises:
|
59
|
-
|
59
|
+
ReadFileError: An error occurred during the file read operation.
|
60
60
|
"""
|
61
61
|
|
62
62
|
if not isinstance(path, Path):
|
63
|
-
raise
|
63
|
+
raise ReadFileError("file_path must be a Path object")
|
64
64
|
if not path.exists():
|
65
|
-
raise
|
66
|
-
self.validate_path_within_work_dir(path,
|
65
|
+
raise ReadFileError(f"File not found: {path}")
|
66
|
+
self.validate_path_within_work_dir(path, ReadFileError)
|
67
67
|
try:
|
68
68
|
return path.read_text()
|
69
69
|
except Exception as e:
|
70
|
-
raise
|
70
|
+
raise ReadFileError(f"Error reading file: {e}") from e
|
71
71
|
|
72
72
|
def list_dir(
|
73
73
|
self,
|
@@ -91,19 +91,19 @@ class FileSystemService(BaseFileSystemService):
|
|
91
91
|
- directories (list[Path]): Sorted list of directory paths
|
92
92
|
|
93
93
|
Raises:
|
94
|
-
|
94
|
+
ListDirError: If the path is invalid, directory doesn't exist, or path is not a directory.
|
95
95
|
|
96
96
|
"""
|
97
97
|
if not isinstance(path, Path):
|
98
|
-
raise
|
98
|
+
raise ListDirError("Path must be a Path object")
|
99
99
|
if not path.exists():
|
100
|
-
raise
|
100
|
+
raise ListDirError(f"Directory not found: {path}")
|
101
101
|
if not path.is_dir():
|
102
|
-
raise
|
102
|
+
raise ListDirError(f"Path is not a directory: {path}")
|
103
103
|
try:
|
104
104
|
path.relative_to(self.work_dir)
|
105
105
|
except ValueError as e:
|
106
|
-
raise
|
106
|
+
raise ListDirError("Access denied: Path outside work directory") from e
|
107
107
|
try:
|
108
108
|
files = []
|
109
109
|
directories = []
|
@@ -112,10 +112,10 @@ class FileSystemService(BaseFileSystemService):
|
|
112
112
|
items = 0
|
113
113
|
for entry in entries:
|
114
114
|
if max_items and items > max_items:
|
115
|
-
raise
|
115
|
+
raise ListDirError(
|
116
116
|
f"Too many items, max processable dir size: {max_items}"
|
117
117
|
)
|
118
|
-
items += 1
|
118
|
+
items += 1 # noqa SIM103
|
119
119
|
target = files if entry.is_file() else directories
|
120
120
|
target.append(entry.relative_to(path) if relative_paths else entry)
|
121
121
|
return ListDirOutput(
|
@@ -123,9 +123,9 @@ class FileSystemService(BaseFileSystemService):
|
|
123
123
|
directories=sorted(directories, key=custom_sort_key),
|
124
124
|
)
|
125
125
|
except PermissionError as e:
|
126
|
-
raise
|
126
|
+
raise ListDirError(f"Access denied: {e}") from e
|
127
127
|
except Exception as e:
|
128
|
-
raise
|
128
|
+
raise ListDirError(f"Error listing directory: {e}") from e
|
129
129
|
|
130
130
|
def validate_path_within_work_dir(self, path: Path, exception_class: type) -> None:
|
131
131
|
"""
|
@@ -5,10 +5,10 @@ This module defines exception classes for handling errors that occur
|
|
5
5
|
during interactions with cloud storage providers.
|
6
6
|
"""
|
7
7
|
|
8
|
-
from sourcerer.domain.storage_provider.exceptions import
|
8
|
+
from sourcerer.domain.storage_provider.exceptions import BaseStorageProviderError
|
9
9
|
|
10
10
|
|
11
|
-
class
|
11
|
+
class CredentialsNotFoundError(BaseStorageProviderError):
|
12
12
|
"""
|
13
13
|
Exception raised when credentials are not found for a cloud storage provider.
|
14
14
|
|
@@ -18,7 +18,7 @@ class CredentialsNotFoundException(BaseStorageProviderException):
|
|
18
18
|
"""
|
19
19
|
|
20
20
|
|
21
|
-
class
|
21
|
+
class ListStoragesError(BaseStorageProviderError):
|
22
22
|
"""
|
23
23
|
Exception raised for errors that occur during the listing of cloud storage services.
|
24
24
|
|
@@ -28,7 +28,7 @@ class ListStoragesException(BaseStorageProviderException):
|
|
28
28
|
"""
|
29
29
|
|
30
30
|
|
31
|
-
class
|
31
|
+
class StoragePermissionError(BaseStorageProviderError):
|
32
32
|
"""
|
33
33
|
Exception raised for permission-related errors in cloud storage operations.
|
34
34
|
|
@@ -37,7 +37,7 @@ class StoragePermissionException(BaseStorageProviderException):
|
|
37
37
|
"""
|
38
38
|
|
39
39
|
|
40
|
-
class
|
40
|
+
class ListStorageItemsError(BaseStorageProviderError):
|
41
41
|
"""
|
42
42
|
Exception raised when an error occurs while listing items in cloud storage.
|
43
43
|
|
@@ -47,7 +47,17 @@ class ListStorageItemsException(BaseStorageProviderException):
|
|
47
47
|
"""
|
48
48
|
|
49
49
|
|
50
|
-
class
|
50
|
+
class BlobNotFoundError(BaseStorageProviderError):
|
51
|
+
"""
|
52
|
+
Exception raised when a blob (file) is not found in cloud storage.
|
53
|
+
|
54
|
+
This exception is a specific case of BaseStorageProviderException
|
55
|
+
and should be used to indicate that the requested blob could not
|
56
|
+
be located in the specified cloud storage service.
|
57
|
+
"""
|
58
|
+
|
59
|
+
|
60
|
+
class ReadStorageItemsError(BaseStorageProviderError):
|
51
61
|
"""
|
52
62
|
Exception raised for errors encountered while reading items from cloud storage.
|
53
63
|
|
@@ -57,7 +67,7 @@ class ReadStorageItemsException(BaseStorageProviderException):
|
|
57
67
|
"""
|
58
68
|
|
59
69
|
|
60
|
-
class
|
70
|
+
class DeleteStorageItemsError(BaseStorageProviderError):
|
61
71
|
"""
|
62
72
|
Exception raised for errors that occur during the deletion of storage items.
|
63
73
|
|
@@ -67,7 +77,7 @@ class DeleteStorageItemsException(BaseStorageProviderException):
|
|
67
77
|
"""
|
68
78
|
|
69
79
|
|
70
|
-
class
|
80
|
+
class UploadStorageItemsError(BaseStorageProviderError):
|
71
81
|
"""
|
72
82
|
Exception raised for errors that occur during the upload of items
|
73
83
|
to cloud storage.
|
@@ -76,3 +86,13 @@ class UploadStorageItemsException(BaseStorageProviderException):
|
|
76
86
|
and is used to signal issues encountered while uploading data to
|
77
87
|
cloud storage services.
|
78
88
|
"""
|
89
|
+
|
90
|
+
|
91
|
+
class AzureMissingContainerError(BaseStorageProviderError):
|
92
|
+
"""
|
93
|
+
Exception raised when a container is not found in Azure cloud storage.
|
94
|
+
|
95
|
+
This exception is a specific case of BaseStorageProviderException
|
96
|
+
and should be used to indicate that the requested container could not
|
97
|
+
be located in the specified Azure cloud storage service.
|
98
|
+
"""
|
@@ -6,7 +6,6 @@ storage provider services.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
import functools
|
9
|
-
from typing import Type, Dict
|
10
9
|
|
11
10
|
from sourcerer.domain.storage_provider.services import BaseStorageProviderService
|
12
11
|
from sourcerer.infrastructure.utils import Singleton
|
@@ -23,9 +22,9 @@ class StorageProviderRegistry(metaclass=Singleton):
|
|
23
22
|
def __init__(self, *args, **kwargs):
|
24
23
|
"""Initialize the registry with an empty dictionary."""
|
25
24
|
super().__init__(*args, **kwargs)
|
26
|
-
self._items_:
|
25
|
+
self._items_: dict[str, type] = {}
|
27
26
|
|
28
|
-
def register(self, storage_provider: str, cls:
|
27
|
+
def register(self, storage_provider: str, cls: type[BaseStorageProviderService]):
|
29
28
|
"""
|
30
29
|
Register a storage provider service implementation.
|
31
30
|
|
File without changes
|