data-sourcerer 0.2.1__py3-none-any.whl → 0.2.3__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.2.1.dist-info → data_sourcerer-0.2.3.dist-info}/METADATA +4 -1
- {data_sourcerer-0.2.1.dist-info → data_sourcerer-0.2.3.dist-info}/RECORD +39 -35
- sourcerer/__init__.py +1 -1
- sourcerer/domain/access_credentials/entities.py +4 -7
- sourcerer/domain/access_credentials/repositories.py +12 -0
- sourcerer/domain/access_credentials/services.py +2 -1
- sourcerer/domain/file_system/entities.py +5 -7
- sourcerer/domain/storage_provider/entities.py +7 -11
- sourcerer/infrastructure/access_credentials/registry.py +1 -1
- sourcerer/infrastructure/access_credentials/repositories.py +17 -0
- sourcerer/infrastructure/access_credentials/services.py +30 -14
- sourcerer/infrastructure/db/config.py +1 -1
- sourcerer/infrastructure/storage_provider/services/azure.py +5 -3
- sourcerer/infrastructure/utils.py +115 -1
- sourcerer/presentation/screens/critical_error/main.py +4 -4
- sourcerer/presentation/screens/file_system_finder/main.py +7 -3
- sourcerer/presentation/screens/file_system_finder/widgets/file_system_navigator.py +1 -1
- sourcerer/presentation/screens/main/main.py +37 -6
- sourcerer/presentation/screens/main/messages/refresh_storages_list_request.py +8 -0
- sourcerer/presentation/screens/main/widgets/gradient.py +3 -3
- sourcerer/presentation/screens/main/widgets/resizing_rule.py +3 -1
- sourcerer/presentation/screens/main/widgets/storage_content.py +43 -18
- sourcerer/presentation/screens/main/widgets/storage_list_sidebar.py +38 -6
- sourcerer/presentation/screens/preview_content/main.py +5 -5
- sourcerer/presentation/screens/provider_creds_list/main.py +44 -0
- sourcerer/presentation/screens/provider_creds_list/messages/__init__.py +0 -0
- sourcerer/presentation/screens/provider_creds_list/messages/reload_credentials_request.py +8 -0
- sourcerer/presentation/screens/provider_creds_list/styles.tcss +5 -5
- sourcerer/presentation/screens/provider_creds_registration/main.py +6 -2
- sourcerer/presentation/screens/question/main.py +4 -3
- sourcerer/presentation/screens/question/styles.tcss +2 -8
- sourcerer/presentation/screens/shared/widgets/button.py +1 -1
- sourcerer/presentation/screens/shared/widgets/labeled_input.py +5 -1
- sourcerer/presentation/screens/shared/widgets/loader.py +31 -0
- sourcerer/presentation/screens/storage_action_progress/main.py +29 -29
- sourcerer/utils.py +1 -1
- {data_sourcerer-0.2.1.dist-info → data_sourcerer-0.2.3.dist-info}/WHEEL +0 -0
- {data_sourcerer-0.2.1.dist-info → data_sourcerer-0.2.3.dist-info}/entry_points.txt +0 -0
- {data_sourcerer-0.2.1.dist-info → data_sourcerer-0.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -76,5 +76,9 @@ class LabeledInput(Container):
|
|
76
76
|
|
77
77
|
"""
|
78
78
|
input_area = self.query_one(".form_input")
|
79
|
-
text =
|
79
|
+
text = (
|
80
|
+
input_area.document.text
|
81
|
+
if isinstance(input_area, TextArea)
|
82
|
+
else input_area.value # type: ignore
|
83
|
+
)
|
80
84
|
return self.Value(name=self.key, value=text)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
from textual.app import ComposeResult
|
2
|
+
from textual.containers import Container
|
3
|
+
from textual.widgets import Static
|
4
|
+
|
5
|
+
|
6
|
+
class Loader(Container):
|
7
|
+
stops = "⣷⣯⣟⡿⢿⣻⣽⣾"
|
8
|
+
index = 0
|
9
|
+
|
10
|
+
DEFAULT_CSS = """
|
11
|
+
Loader {
|
12
|
+
color: #9E53E0;
|
13
|
+
}
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self, *args, **kwargs):
|
17
|
+
self.label = Static(self.stops[self.index])
|
18
|
+
super().__init__(*args, **kwargs)
|
19
|
+
|
20
|
+
def compose(self) -> ComposeResult:
|
21
|
+
yield self.label
|
22
|
+
|
23
|
+
def on_mount(self) -> None:
|
24
|
+
self.auto_refresh = 1 / 10
|
25
|
+
|
26
|
+
def automatic_refresh(self):
|
27
|
+
self.index += 1
|
28
|
+
if self.index >= len(self.stops):
|
29
|
+
self.index = 0
|
30
|
+
value = self.stops[self.index]
|
31
|
+
self.label.update(value)
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import contextlib
|
2
2
|
import os
|
3
3
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
4
|
-
from dataclasses import dataclass
|
5
4
|
from pathlib import Path
|
6
5
|
|
6
|
+
from msgspec._core import Struct
|
7
7
|
from rich.text import Text
|
8
8
|
from textual import on
|
9
9
|
from textual.app import ComposeResult
|
@@ -44,8 +44,7 @@ gradient2 = Gradient.from_colors(
|
|
44
44
|
)
|
45
45
|
|
46
46
|
|
47
|
-
|
48
|
-
class Key:
|
47
|
+
class Key(Struct):
|
49
48
|
"""
|
50
49
|
Base class for representing a key in storage operations.
|
51
50
|
|
@@ -76,7 +75,6 @@ class DeleteKey(Key):
|
|
76
75
|
"""
|
77
76
|
|
78
77
|
|
79
|
-
@dataclass
|
80
78
|
class UploadKey(Key):
|
81
79
|
"""
|
82
80
|
Represents a key for upload operations.
|
@@ -187,9 +185,9 @@ class StorageActionProgressScreen(ModalScreen):
|
|
187
185
|
Sets the border title and starts the appropriate worker thread based on the action type
|
188
186
|
(download, delete, or upload).
|
189
187
|
"""
|
190
|
-
self.query_one(
|
191
|
-
|
192
|
-
)
|
188
|
+
self.query_one(
|
189
|
+
"#StorageActionProgress"
|
190
|
+
).border_title = f"{self.action.capitalize()} {len(self.keys)} files from {self.storage_name}"
|
193
191
|
|
194
192
|
if self.action == "download":
|
195
193
|
self.active_worker = self.run_worker(self.download_files, thread=True)
|
@@ -245,7 +243,7 @@ class StorageActionProgressScreen(ModalScreen):
|
|
245
243
|
This method handles the download of multiple files, updating progress bars
|
246
244
|
and handling various error conditions that might occur during the process.
|
247
245
|
"""
|
248
|
-
main_progress_bar = self.query_one("#progress_bar")
|
246
|
+
main_progress_bar = self.query_one("#progress_bar", ProgressBar)
|
249
247
|
failed_downloads = []
|
250
248
|
|
251
249
|
with ThreadPoolExecutor(max_workers=MAX_PARALLEL_DOWNLOADS) as executor:
|
@@ -291,13 +289,13 @@ class StorageActionProgressScreen(ModalScreen):
|
|
291
289
|
def progress_callback(progress_bar, chunk):
|
292
290
|
progress_bar.advance(chunk)
|
293
291
|
|
294
|
-
progress_bar = self.query_one(f"#progress_bar_{uuid}")
|
292
|
+
progress_bar = self.query_one(f"#progress_bar_{uuid}", ProgressBar)
|
295
293
|
|
296
294
|
try:
|
297
295
|
# Step 1: Get file size
|
298
296
|
try:
|
299
297
|
file_size = self.provider_service.get_file_size(self.storage_name, key)
|
300
|
-
progress_bar.total = file_size
|
298
|
+
progress_bar.total = file_size
|
301
299
|
except Exception as ex:
|
302
300
|
self.notify(
|
303
301
|
f"Failed to get file size for {key}: {str(ex)}", severity="error"
|
@@ -318,9 +316,9 @@ class StorageActionProgressScreen(ModalScreen):
|
|
318
316
|
return
|
319
317
|
|
320
318
|
# Step 3: Ensure progress bar is complete
|
321
|
-
if progress_bar.progress != progress_bar.total:
|
319
|
+
if progress_bar.progress != progress_bar.total:
|
322
320
|
try:
|
323
|
-
progress_bar.progress = file_size
|
321
|
+
progress_bar.progress = file_size
|
324
322
|
except Exception as ex:
|
325
323
|
self.log.error(f"Error updating progress bar: {ex}")
|
326
324
|
# Non-critical error, continue execution
|
@@ -340,7 +338,7 @@ class StorageActionProgressScreen(ModalScreen):
|
|
340
338
|
This method handles the deletion of multiple files, updating progress bars
|
341
339
|
and handling various error conditions that might occur during the process.
|
342
340
|
"""
|
343
|
-
main_progress_bar = self.query_one("#progress_bar")
|
341
|
+
main_progress_bar = self.query_one("#progress_bar", ProgressBar)
|
344
342
|
failed_downloads = []
|
345
343
|
|
346
344
|
with ThreadPoolExecutor(max_workers=MAX_PARALLEL_DOWNLOADS) as executor:
|
@@ -379,11 +377,11 @@ class StorageActionProgressScreen(ModalScreen):
|
|
379
377
|
main_progress_bar.advance(1)
|
380
378
|
return
|
381
379
|
|
382
|
-
progress_bar = self.query_one(f"#progress_bar_{uuid}")
|
380
|
+
progress_bar = self.query_one(f"#progress_bar_{uuid}", ProgressBar)
|
383
381
|
try:
|
384
|
-
progress_bar.total = 1
|
382
|
+
progress_bar.total = 1
|
385
383
|
self.provider_service.delete_storage_item(self.storage_name, key)
|
386
|
-
progress_bar.advance(1)
|
384
|
+
progress_bar.advance(1)
|
387
385
|
except Exception:
|
388
386
|
self.notify(f"Failed to delete {key}", severity="error")
|
389
387
|
raise
|
@@ -397,7 +395,7 @@ class StorageActionProgressScreen(ModalScreen):
|
|
397
395
|
This method handles the upload of files, updating progress bars and
|
398
396
|
handling various error conditions that might occur during the process.
|
399
397
|
"""
|
400
|
-
main_progress_bar = self.query_one("#progress_bar")
|
398
|
+
main_progress_bar = self.query_one("#progress_bar", ProgressBar)
|
401
399
|
failed_downloads = []
|
402
400
|
if not self.provider_service:
|
403
401
|
self.notify("Failed to upload files", severity="error")
|
@@ -411,10 +409,12 @@ class StorageActionProgressScreen(ModalScreen):
|
|
411
409
|
storage=self.storage_name,
|
412
410
|
storage_path=self.path,
|
413
411
|
source_path=key.path,
|
414
|
-
dest_path=key.dest_path,
|
412
|
+
dest_path=key.dest_path,
|
413
|
+
)
|
414
|
+
progress_bar = self.query_one(
|
415
|
+
f"#progress_bar_{key.uuid}", ProgressBar
|
415
416
|
)
|
416
|
-
progress_bar
|
417
|
-
progress_bar.advance(1) # type: ignore
|
417
|
+
progress_bar.advance(1)
|
418
418
|
except UploadStorageItemsError as e:
|
419
419
|
self.notify(f"Failed to upload {key.path}: {e}", severity="error")
|
420
420
|
finally:
|
@@ -422,8 +422,8 @@ class StorageActionProgressScreen(ModalScreen):
|
|
422
422
|
elif source_path.is_dir():
|
423
423
|
|
424
424
|
files_n = len([i for i in source_path.rglob("*") if i.is_file()])
|
425
|
-
progress_bar = self.query_one(f"#progress_bar_{key.uuid}")
|
426
|
-
progress_bar.total = files_n
|
425
|
+
progress_bar = self.query_one(f"#progress_bar_{key.uuid}", ProgressBar)
|
426
|
+
progress_bar.total = files_n
|
427
427
|
with ThreadPoolExecutor(max_workers=MAX_PARALLEL_DOWNLOADS) as executor:
|
428
428
|
self.active_executor = executor
|
429
429
|
futures = [
|
@@ -447,10 +447,10 @@ class StorageActionProgressScreen(ModalScreen):
|
|
447
447
|
self.files_has_been_processed = True
|
448
448
|
self.active_executor = None
|
449
449
|
try:
|
450
|
-
self.query_one(f"#progress_file_details_{key.uuid}").remove()
|
451
|
-
except
|
450
|
+
self.query_one(f"#progress_file_details_{key.uuid}", Label).remove()
|
451
|
+
except NoMatches:
|
452
452
|
self.log(f"Failed to remove progress details for {key.uuid}")
|
453
|
-
main_progress_bar.advance(1)
|
453
|
+
main_progress_bar.advance(1)
|
454
454
|
|
455
455
|
def upload_file(self, source, rel_source, destination, uuid):
|
456
456
|
"""
|
@@ -467,12 +467,12 @@ class StorageActionProgressScreen(ModalScreen):
|
|
467
467
|
if not self.provider_service:
|
468
468
|
self.notify(f"Failed to upload {source}", severity="error")
|
469
469
|
return
|
470
|
-
progress_bar = self.query_one(f"#progress_bar_{uuid}")
|
470
|
+
progress_bar = self.query_one(f"#progress_bar_{uuid}", ProgressBar)
|
471
471
|
details_container = None
|
472
472
|
with contextlib.suppress(NoMatches):
|
473
|
-
details_container = self.query_one(f"#progress_file_details_{uuid}")
|
473
|
+
details_container = self.query_one(f"#progress_file_details_{uuid}", Label)
|
474
474
|
if details_container:
|
475
|
-
details_container.update(Text(f"({rel_source})", overflow="ellipsis"))
|
475
|
+
details_container.update(Text(f"({rel_source})", overflow="ellipsis"))
|
476
476
|
try:
|
477
477
|
self.provider_service.upload_storage_item(
|
478
478
|
storage=self.storage_name,
|
@@ -480,7 +480,7 @@ class StorageActionProgressScreen(ModalScreen):
|
|
480
480
|
source_path=source,
|
481
481
|
dest_path=destination,
|
482
482
|
)
|
483
|
-
progress_bar.advance(1)
|
483
|
+
progress_bar.advance(1)
|
484
484
|
except UploadStorageItemsError as e:
|
485
485
|
self.notify(f"Failed to upload {source}: {e}", severity="error")
|
486
486
|
|
sourcerer/utils.py
CHANGED
File without changes
|
File without changes
|
File without changes
|