data-sourcerer 0.1.0__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.0.dist-info → data_sourcerer-0.2.0.dist-info}/METADATA +25 -4
- {data_sourcerer-0.1.0.dist-info → data_sourcerer-0.2.0.dist-info}/RECORD +53 -50
- {data_sourcerer-0.1.0.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.0.dist-info → data_sourcerer-0.2.0.dist-info}/entry_points.txt +0 -0
- {data_sourcerer-0.1.0.dist-info → data_sourcerer-0.2.0.dist-info}/licenses/LICENSE +0 -0
- {data_sourcerer-0.1.0.dist-info → data_sourcerer-0.2.0.dist-info}/top_level.txt +0 -0
@@ -1,509 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Implementation of storage provider services.
|
3
|
-
|
4
|
-
This module provides concrete implementations of the BaseStorageProviderService
|
5
|
-
interface for various cloud storage providers.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from itertools import groupby
|
9
|
-
from pathlib import Path
|
10
|
-
from typing import List, Any, Callable
|
11
|
-
|
12
|
-
import humanize
|
13
|
-
from platformdirs import user_downloads_dir
|
14
|
-
|
15
|
-
from sourcerer.domain.shared.entities import StorageProvider
|
16
|
-
from sourcerer.domain.storage_provider.entities import (
|
17
|
-
StoragePermissions,
|
18
|
-
StorageContent,
|
19
|
-
Folder,
|
20
|
-
File,
|
21
|
-
Storage,
|
22
|
-
)
|
23
|
-
from sourcerer.domain.storage_provider.services import BaseStorageProviderService
|
24
|
-
from sourcerer.infrastructure.storage_provider.exceptions import (
|
25
|
-
ListStoragesException,
|
26
|
-
StoragePermissionException,
|
27
|
-
ListStorageItemsException,
|
28
|
-
ReadStorageItemsException,
|
29
|
-
DeleteStorageItemsException,
|
30
|
-
UploadStorageItemsException,
|
31
|
-
CredentialsNotFoundException,
|
32
|
-
)
|
33
|
-
from sourcerer.infrastructure.storage_provider.registry import storage_provider
|
34
|
-
from sourcerer.infrastructure.utils import generate_uuid, is_text_file
|
35
|
-
from sourcerer.settings import PATH_DELIMITER, PAGE_SIZE
|
36
|
-
|
37
|
-
|
38
|
-
@storage_provider(StorageProvider.S3)
|
39
|
-
class S3ProviderService(BaseStorageProviderService):
|
40
|
-
"""
|
41
|
-
AWS S3 storage provider service implementation.
|
42
|
-
|
43
|
-
This class provides methods for interacting with AWS S3 storage,
|
44
|
-
implementing the BaseStorageProviderService interface.
|
45
|
-
"""
|
46
|
-
|
47
|
-
def __init__(self, credentials: Any):
|
48
|
-
"""
|
49
|
-
Initialize the service with AWS credentials.
|
50
|
-
|
51
|
-
Args:
|
52
|
-
credentials (Any): AWS session or credentials object
|
53
|
-
"""
|
54
|
-
self.credentials = credentials
|
55
|
-
|
56
|
-
@property
|
57
|
-
def client(self):
|
58
|
-
"""
|
59
|
-
Get the S3 client.
|
60
|
-
|
61
|
-
Returns:
|
62
|
-
boto3.client: S3 client object
|
63
|
-
"""
|
64
|
-
if not self.credentials:
|
65
|
-
raise CredentialsNotFoundException()
|
66
|
-
|
67
|
-
session = self.credentials.session
|
68
|
-
|
69
|
-
client_args = {}
|
70
|
-
if self.credentials.endpoint_url:
|
71
|
-
client_args["endpoint_url"] = self.credentials.endpoint_url
|
72
|
-
|
73
|
-
return session.client("s3", **client_args)
|
74
|
-
|
75
|
-
@property
|
76
|
-
def resource(self):
|
77
|
-
"""
|
78
|
-
Get the S3 resource.
|
79
|
-
|
80
|
-
Returns:
|
81
|
-
boto3.resource: S3 resource object
|
82
|
-
"""
|
83
|
-
if not self.credentials:
|
84
|
-
raise CredentialsNotFoundException()
|
85
|
-
|
86
|
-
session = self.credentials.session
|
87
|
-
|
88
|
-
client_args = {}
|
89
|
-
if self.credentials.endpoint_url:
|
90
|
-
client_args["endpoint_url"] = self.credentials.endpoint_url
|
91
|
-
return session.resource("s3", **client_args)
|
92
|
-
|
93
|
-
def list_storages(self) -> List[Storage]:
|
94
|
-
"""
|
95
|
-
Return a list of available S3 buckets.
|
96
|
-
|
97
|
-
Returns:
|
98
|
-
List[Storage]: List of storage objects representing S3 buckets
|
99
|
-
|
100
|
-
Raises:
|
101
|
-
ListStoragesException: If an error occurs while listing buckets
|
102
|
-
"""
|
103
|
-
try:
|
104
|
-
response = self.client.list_buckets()
|
105
|
-
except Exception as ex:
|
106
|
-
raise ListStoragesException(str(ex)) from ex
|
107
|
-
return [
|
108
|
-
Storage(StorageProvider.S3, i.get("Name"), i.get("CreationDate"))
|
109
|
-
for i in response.get("Buckets")
|
110
|
-
]
|
111
|
-
|
112
|
-
def get_storage_permissions(self, storage: str) -> List[StoragePermissions]:
|
113
|
-
"""
|
114
|
-
Return the permissions for the specified S3 bucket.
|
115
|
-
|
116
|
-
Args:
|
117
|
-
storage (str): The bucket name
|
118
|
-
|
119
|
-
Returns:
|
120
|
-
List[StoragePermissions]: List of permission objects for the bucket
|
121
|
-
|
122
|
-
Raises:
|
123
|
-
StoragePermissionException: If an error occurs while getting permissions
|
124
|
-
"""
|
125
|
-
try:
|
126
|
-
permissions = self.client.get_bucket_acl(Bucket=storage)
|
127
|
-
except Exception as ex:
|
128
|
-
raise StoragePermissionException(str(ex)) from ex
|
129
|
-
return [
|
130
|
-
StoragePermissions(name, [i["Permission"] for i in items])
|
131
|
-
for name, items in groupby(
|
132
|
-
permissions["Grants"],
|
133
|
-
key=lambda x: x["Grantee"]["DisplayName"] or x["Grantee"]["ID"],
|
134
|
-
)
|
135
|
-
]
|
136
|
-
|
137
|
-
def list_storage_items(
|
138
|
-
self, storage: str, path: str = "", prefix: str = ""
|
139
|
-
) -> StorageContent:
|
140
|
-
"""
|
141
|
-
List items in the specified S3 bucket path with the given prefix.
|
142
|
-
|
143
|
-
Args:
|
144
|
-
storage (str): The bucket name
|
145
|
-
path (str, optional): The path within the bucket. Defaults to ''.
|
146
|
-
prefix (str, optional): Filter items by this prefix. Defaults to ''.
|
147
|
-
|
148
|
-
Returns:
|
149
|
-
StorageContent: Object containing files and folders at the specified location
|
150
|
-
|
151
|
-
Raises:
|
152
|
-
ListStorageItemsException: If an error occurs while listing items
|
153
|
-
"""
|
154
|
-
if path and not path.endswith("/"):
|
155
|
-
path += "/"
|
156
|
-
try:
|
157
|
-
result = self.client.list_objects_v2(
|
158
|
-
Bucket=storage,
|
159
|
-
Prefix=path + prefix,
|
160
|
-
Delimiter=PATH_DELIMITER,
|
161
|
-
MaxKeys=PAGE_SIZE,
|
162
|
-
)
|
163
|
-
except Exception as ex:
|
164
|
-
raise ListStorageItemsException(str(ex)) from ex
|
165
|
-
|
166
|
-
folders = [
|
167
|
-
Folder(i.get("Prefix").replace(path, ""))
|
168
|
-
for i in result.get("CommonPrefixes", [])
|
169
|
-
if i.get("Prefix")
|
170
|
-
]
|
171
|
-
files = [
|
172
|
-
File(
|
173
|
-
generate_uuid(),
|
174
|
-
i.get("Key").replace(path, ""),
|
175
|
-
humanize.naturalsize(i.get("Size")),
|
176
|
-
is_text_file(i.get("Key")),
|
177
|
-
i.get("LastModified"),
|
178
|
-
)
|
179
|
-
for i in result.get("Contents", [])
|
180
|
-
if i.get("Key").replace(path, "")
|
181
|
-
]
|
182
|
-
return StorageContent(files=files, folders=folders)
|
183
|
-
|
184
|
-
def read_storage_item(self, storage: str, key: str) -> str:
|
185
|
-
"""
|
186
|
-
Read and return the content of the specified S3 object.
|
187
|
-
|
188
|
-
Args:
|
189
|
-
storage (str): The bucket name
|
190
|
-
key (str): The key/path of the item to read
|
191
|
-
|
192
|
-
Returns:
|
193
|
-
bytes: The content of the S3 object
|
194
|
-
|
195
|
-
Raises:
|
196
|
-
ReadStorageItemsException: If an error occurs while reading the item
|
197
|
-
"""
|
198
|
-
try:
|
199
|
-
content_object = self.resource.Object(storage, key)
|
200
|
-
return content_object.get()["Body"].read().decode("utf-8")
|
201
|
-
except Exception as ex:
|
202
|
-
raise ReadStorageItemsException(str(ex)) from ex
|
203
|
-
|
204
|
-
def delete_storage_item(self, storage: str, key: str) -> None:
|
205
|
-
"""
|
206
|
-
Delete the specified S3 object.
|
207
|
-
|
208
|
-
Args:
|
209
|
-
storage (str): The bucket name
|
210
|
-
key (str): The key/path of the item to delete
|
211
|
-
|
212
|
-
Raises:
|
213
|
-
DeleteStorageItemsException: If an error occurs while deleting the item
|
214
|
-
"""
|
215
|
-
try:
|
216
|
-
return self.resource.Object(storage, key).delete()
|
217
|
-
except Exception as ex:
|
218
|
-
raise DeleteStorageItemsException(str(ex)) from ex
|
219
|
-
|
220
|
-
def upload_storage_item(
|
221
|
-
self, storage: str, source_path: Path, dest_path: str | None = None
|
222
|
-
) -> None:
|
223
|
-
"""
|
224
|
-
Upload a file to the specified S3 bucket path.
|
225
|
-
|
226
|
-
Args:
|
227
|
-
storage (str): The bucket name
|
228
|
-
source_path (Path): Local file path to upload
|
229
|
-
dest_path (str, optional): Destination path in S3. Defaults to None.
|
230
|
-
|
231
|
-
Raises:
|
232
|
-
UploadStorageItemsException: If an error occurs while uploading the item
|
233
|
-
"""
|
234
|
-
try:
|
235
|
-
self.client.upload_file(source_path, storage, dest_path or source_path.name)
|
236
|
-
except Exception as ex:
|
237
|
-
raise UploadStorageItemsException(str(ex)) from ex
|
238
|
-
|
239
|
-
def download_storage_item(
|
240
|
-
self, storage: str, key: str, progress_callback: Callable | None = None
|
241
|
-
) -> str:
|
242
|
-
"""
|
243
|
-
Download a file from S3 to local filesystem.
|
244
|
-
|
245
|
-
Args:
|
246
|
-
storage (str): The bucket name
|
247
|
-
key (str): The key/path of the item to download
|
248
|
-
progress_callback (Callable, optional): Callback function for progress updates. Defaults to None.
|
249
|
-
|
250
|
-
Returns:
|
251
|
-
str: Path to the downloaded file
|
252
|
-
|
253
|
-
Raises:
|
254
|
-
ReadStorageItemsException: If an error occurs while downloading the item
|
255
|
-
"""
|
256
|
-
try:
|
257
|
-
download_path = Path(user_downloads_dir()) / Path(key).name
|
258
|
-
self.client.download_file(
|
259
|
-
storage, key, download_path, Callback=progress_callback
|
260
|
-
)
|
261
|
-
return str(download_path)
|
262
|
-
except Exception as ex:
|
263
|
-
raise ReadStorageItemsException(str(ex)) from ex
|
264
|
-
|
265
|
-
def get_file_size(self, storage: str, key: str) -> dict:
|
266
|
-
"""
|
267
|
-
Get metadata for an S3 object without downloading content.
|
268
|
-
|
269
|
-
Args:
|
270
|
-
storage (str): The bucket name
|
271
|
-
key (str): The key/path of the item
|
272
|
-
|
273
|
-
Returns:
|
274
|
-
dict: Metadata for the specified S3 object
|
275
|
-
|
276
|
-
Raises:
|
277
|
-
ReadStorageItemsException: If an error occurs while getting metadata
|
278
|
-
"""
|
279
|
-
try:
|
280
|
-
metadata = self.client.head_object(Bucket=storage, Key=key)
|
281
|
-
return metadata.get("ContentLength")
|
282
|
-
except Exception as ex:
|
283
|
-
raise ReadStorageItemsException(str(ex)) from ex
|
284
|
-
|
285
|
-
|
286
|
-
@storage_provider(StorageProvider.GoogleCloudStorage)
|
287
|
-
class GCPStorageProviderService(BaseStorageProviderService):
|
288
|
-
"""
|
289
|
-
Google Cloud Platform storage provider service implementation.
|
290
|
-
|
291
|
-
This class provides methods for interacting with GCP Cloud Storage,
|
292
|
-
implementing the BaseStorageProviderService interface.
|
293
|
-
"""
|
294
|
-
|
295
|
-
def __init__(self, credentials: Any):
|
296
|
-
"""
|
297
|
-
Initialize the service with GCP credentials.
|
298
|
-
|
299
|
-
Args:
|
300
|
-
credentials (Any): GCP client or credentials object
|
301
|
-
"""
|
302
|
-
self.client = credentials
|
303
|
-
|
304
|
-
def list_storages(self) -> List[Storage]:
|
305
|
-
"""
|
306
|
-
Return a list of available GCP buckets.
|
307
|
-
|
308
|
-
Returns:
|
309
|
-
List[Storage]: List of storage objects representing GCP buckets
|
310
|
-
|
311
|
-
Raises:
|
312
|
-
ListStoragesException: If an error occurs while listing buckets
|
313
|
-
"""
|
314
|
-
try:
|
315
|
-
return [
|
316
|
-
Storage(StorageProvider.GoogleCloudStorage, i.name, i.time_created)
|
317
|
-
for i in self.client.list_buckets()
|
318
|
-
]
|
319
|
-
except Exception as ex:
|
320
|
-
raise ListStoragesException(str(ex)) from ex
|
321
|
-
|
322
|
-
def get_storage_permissions(self, storage: str) -> List[StoragePermissions]:
|
323
|
-
"""
|
324
|
-
Return the permissions for the specified GCP bucket.
|
325
|
-
|
326
|
-
Args:
|
327
|
-
storage (str): The bucket name
|
328
|
-
|
329
|
-
Returns:
|
330
|
-
List[StoragePermissions]: List of permission objects for the bucket
|
331
|
-
|
332
|
-
Raises:
|
333
|
-
StoragePermissionException: If an error occurs while getting permissions
|
334
|
-
"""
|
335
|
-
try:
|
336
|
-
bucket = self.client.get_bucket(storage)
|
337
|
-
policy = bucket.get_iam_policy()
|
338
|
-
|
339
|
-
result = {}
|
340
|
-
for role, members in policy.items():
|
341
|
-
for member in members:
|
342
|
-
member = member.split(":")[-1]
|
343
|
-
if member not in result:
|
344
|
-
result[member] = set()
|
345
|
-
result[member].add(role)
|
346
|
-
return [
|
347
|
-
StoragePermissions(member, roles) for member, roles in result.items()
|
348
|
-
]
|
349
|
-
except Exception as ex:
|
350
|
-
raise StoragePermissionException(str(ex)) from ex
|
351
|
-
|
352
|
-
def list_storage_items(
|
353
|
-
self, storage: str, path: str = "", prefix: str = ""
|
354
|
-
) -> StorageContent:
|
355
|
-
"""
|
356
|
-
List items in the specified GCP bucket path with the given prefix.
|
357
|
-
|
358
|
-
Args:
|
359
|
-
storage (str): The bucket name
|
360
|
-
path (str, optional): The path within the bucket. Defaults to ''.
|
361
|
-
prefix (str, optional): Filter items by this prefix. Defaults to ''.
|
362
|
-
|
363
|
-
Returns:
|
364
|
-
StorageContent: Object containing files and folders at the specified location
|
365
|
-
|
366
|
-
Raises:
|
367
|
-
ListStorageItemsException: If an error occurs while listing items
|
368
|
-
"""
|
369
|
-
try:
|
370
|
-
|
371
|
-
files = []
|
372
|
-
folders = []
|
373
|
-
if path and not path.endswith("/"):
|
374
|
-
path += "/"
|
375
|
-
|
376
|
-
bucket = self.client.bucket(storage)
|
377
|
-
|
378
|
-
blobs = bucket.list_blobs(
|
379
|
-
prefix=path + prefix, delimiter=PATH_DELIMITER, max_results=PAGE_SIZE
|
380
|
-
)
|
381
|
-
|
382
|
-
for blob in blobs:
|
383
|
-
files.append(
|
384
|
-
File(
|
385
|
-
generate_uuid(),
|
386
|
-
blob.name[len(path) :],
|
387
|
-
size=humanize.naturalsize(blob.size),
|
388
|
-
date_modified=blob.updated.date(),
|
389
|
-
is_text=is_text_file(blob.name),
|
390
|
-
)
|
391
|
-
)
|
392
|
-
|
393
|
-
for folder in blobs.prefixes:
|
394
|
-
relative_path = folder[len(path) :]
|
395
|
-
folders.append(Folder(relative_path))
|
396
|
-
|
397
|
-
return StorageContent(files=files, folders=folders)
|
398
|
-
|
399
|
-
except Exception as ex:
|
400
|
-
raise ListStorageItemsException(
|
401
|
-
f"Failed to list items in {storage}: {str(ex)}"
|
402
|
-
) from ex
|
403
|
-
|
404
|
-
def read_storage_item(self, storage: str, key: str) -> str:
|
405
|
-
"""
|
406
|
-
Read and return the content of the specified GCP object.
|
407
|
-
|
408
|
-
Args:
|
409
|
-
storage (str): The bucket name
|
410
|
-
key (str): The key/path of the item to read
|
411
|
-
|
412
|
-
Returns:
|
413
|
-
bytes: The content of the GCP object
|
414
|
-
|
415
|
-
Raises:
|
416
|
-
ReadStorageItemsException: If an error occurs while reading the item
|
417
|
-
"""
|
418
|
-
try:
|
419
|
-
bucket = self.client.bucket(storage)
|
420
|
-
blob = bucket.get_blob(key)
|
421
|
-
content = blob.download_as_bytes()
|
422
|
-
return content.decode("utf-8")
|
423
|
-
except Exception as ex:
|
424
|
-
raise ReadStorageItemsException(str(ex)) from ex
|
425
|
-
|
426
|
-
def delete_storage_item(self, storage: str, key: str) -> None:
|
427
|
-
"""
|
428
|
-
Delete the specified GCP object.
|
429
|
-
|
430
|
-
Args:
|
431
|
-
storage (str): The bucket name
|
432
|
-
key (str): The key/path of the item to delete
|
433
|
-
|
434
|
-
Raises:
|
435
|
-
DeleteStorageItemsException: If an error occurs while deleting the item
|
436
|
-
"""
|
437
|
-
try:
|
438
|
-
bucket = self.client.bucket(storage)
|
439
|
-
blob = bucket.get_blob(key)
|
440
|
-
blob.delete()
|
441
|
-
except Exception as ex:
|
442
|
-
raise DeleteStorageItemsException(str(ex)) from ex
|
443
|
-
|
444
|
-
def upload_storage_item(
|
445
|
-
self, storage: str, source_path: Path, dest_path: str | None = None
|
446
|
-
) -> None:
|
447
|
-
"""
|
448
|
-
Upload a file to the specified GCP bucket path.
|
449
|
-
|
450
|
-
Args:
|
451
|
-
storage (str): The bucket name
|
452
|
-
source_path (Path): Local file path to upload
|
453
|
-
dest_path (str, optional): Destination path in GCP. Defaults to None.
|
454
|
-
|
455
|
-
Raises:
|
456
|
-
UploadStorageItemsException: If an error occurs while uploading the item
|
457
|
-
"""
|
458
|
-
try:
|
459
|
-
bucket = self.client.bucket(storage)
|
460
|
-
bucket.blob(dest_path or source_path.name).upload_from_filename(source_path)
|
461
|
-
except Exception as ex:
|
462
|
-
raise UploadStorageItemsException(str(ex)) from ex
|
463
|
-
|
464
|
-
def download_storage_item(
|
465
|
-
self, storage: str, key: str, progress_callback: Callable | None = None
|
466
|
-
) -> str:
|
467
|
-
"""
|
468
|
-
Download a file from GCP to the local filesystem.
|
469
|
-
|
470
|
-
Args:
|
471
|
-
storage (str): The bucket name
|
472
|
-
key (str): The key/path of the item to download
|
473
|
-
progress_callback (Callable, optional): Callback function for progress updates. Defaults to None.
|
474
|
-
|
475
|
-
Returns:
|
476
|
-
str: Path to the downloaded file
|
477
|
-
|
478
|
-
Raises:
|
479
|
-
ReadStorageItemsException: If an error occurs while downloading the item
|
480
|
-
"""
|
481
|
-
try:
|
482
|
-
bucket = self.client.bucket(storage)
|
483
|
-
blob = bucket.get_blob(key)
|
484
|
-
download_path = Path(user_downloads_dir()) / Path(key).name
|
485
|
-
blob.download_to_filename(str(download_path))
|
486
|
-
return str(download_path)
|
487
|
-
except Exception as ex:
|
488
|
-
raise ReadStorageItemsException(str(ex)) from ex
|
489
|
-
|
490
|
-
def get_file_size(self, storage: str, key: str) -> dict:
|
491
|
-
"""
|
492
|
-
Get metadata for a GCP object without downloading content.
|
493
|
-
|
494
|
-
Args:
|
495
|
-
storage (str): The bucket name
|
496
|
-
key (str): The key/path of the item
|
497
|
-
|
498
|
-
Returns:
|
499
|
-
dict: Metadata for the specified GCP object
|
500
|
-
|
501
|
-
Raises:
|
502
|
-
ReadStorageItemsException: If an error occurs while getting metadata
|
503
|
-
"""
|
504
|
-
try:
|
505
|
-
bucket = self.client.bucket(storage)
|
506
|
-
blob = bucket.get_blob(key)
|
507
|
-
return blob.size
|
508
|
-
except Exception as ex:
|
509
|
-
raise ReadStorageItemsException(str(ex)) from ex
|
File without changes
|
File without changes
|
File without changes
|