data-sourcerer 0.2.3__py3-none-any.whl → 0.3.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.2.3.dist-info → data_sourcerer-0.3.0.dist-info}/METADATA +1 -1
- {data_sourcerer-0.2.3.dist-info → data_sourcerer-0.3.0.dist-info}/RECORD +42 -28
- sourcerer/__init__.py +1 -1
- sourcerer/domain/access_credentials/entities.py +3 -1
- sourcerer/domain/access_credentials/repositories.py +1 -1
- sourcerer/domain/storage/__init__.py +0 -0
- sourcerer/domain/storage/entities.py +27 -0
- sourcerer/domain/storage/repositories.py +31 -0
- sourcerer/infrastructure/access_credentials/repositories.py +3 -2
- sourcerer/infrastructure/access_credentials/services.py +9 -25
- sourcerer/infrastructure/db/models.py +33 -2
- sourcerer/infrastructure/storage/__init__.py +0 -0
- sourcerer/infrastructure/storage/repositories.py +72 -0
- sourcerer/infrastructure/storage/services.py +37 -0
- sourcerer/infrastructure/storage_provider/services/gcp.py +1 -1
- sourcerer/infrastructure/utils.py +2 -1
- sourcerer/presentation/di_container.py +15 -0
- sourcerer/presentation/screens/file_system_finder/main.py +5 -4
- sourcerer/presentation/screens/file_system_finder/widgets/file_system_navigator.py +16 -13
- sourcerer/presentation/screens/main/main.py +63 -8
- sourcerer/presentation/screens/main/messages/select_storage_item.py +1 -0
- sourcerer/presentation/screens/main/mixins/resize_containers_watcher_mixin.py +2 -1
- sourcerer/presentation/screens/main/widgets/storage_content.py +187 -77
- sourcerer/presentation/screens/main/widgets/storage_list_sidebar.py +99 -31
- sourcerer/presentation/screens/preview_content/main.py +15 -3
- sourcerer/presentation/screens/provider_creds_list/main.py +29 -8
- sourcerer/presentation/screens/provider_creds_registration/main.py +7 -4
- sourcerer/presentation/screens/shared/widgets/spinner.py +57 -0
- sourcerer/presentation/screens/storage_action_progress/main.py +3 -5
- sourcerer/presentation/screens/storages_list/__init__.py +0 -0
- sourcerer/presentation/screens/storages_list/main.py +180 -0
- sourcerer/presentation/screens/storages_list/messages/__init__.py +0 -0
- sourcerer/presentation/screens/storages_list/messages/reload_storages_request.py +8 -0
- sourcerer/presentation/screens/storages_list/styles.tcss +55 -0
- sourcerer/presentation/screens/storages_registration/__init__.py +0 -0
- sourcerer/presentation/screens/storages_registration/main.py +100 -0
- sourcerer/presentation/screens/storages_registration/styles.tcss +41 -0
- sourcerer/presentation/settings.py +29 -16
- sourcerer/presentation/utils.py +9 -1
- sourcerer/presentation/screens/shared/widgets/loader.py +0 -31
- {data_sourcerer-0.2.3.dist-info → data_sourcerer-0.3.0.dist-info}/WHEEL +0 -0
- {data_sourcerer-0.2.3.dist-info → data_sourcerer-0.3.0.dist-info}/entry_points.txt +0 -0
- {data_sourcerer-0.2.3.dist-info → data_sourcerer-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
Container {
|
3
|
+
height: auto;
|
4
|
+
}
|
5
|
+
|
6
|
+
Label {
|
7
|
+
padding-left: 1;
|
8
|
+
}
|
9
|
+
|
10
|
+
StoragesListScreen {
|
11
|
+
align: center middle;
|
12
|
+
content-align: center top;
|
13
|
+
|
14
|
+
& > #StoragesListScreen {
|
15
|
+
padding: 1 2 0 2;
|
16
|
+
margin: 0 0;
|
17
|
+
width: 60%;
|
18
|
+
height: 60%;
|
19
|
+
border: solid $secondary-background;
|
20
|
+
|
21
|
+
#right-top {
|
22
|
+
align: right top;
|
23
|
+
|
24
|
+
.add_storage_button {
|
25
|
+
color: $success-darken-2;
|
26
|
+
}
|
27
|
+
|
28
|
+
margin-bottom: 1;
|
29
|
+
}
|
30
|
+
|
31
|
+
ProviderCredentialsRow.active {
|
32
|
+
background: $primary-lighten-2;
|
33
|
+
}
|
34
|
+
|
35
|
+
ProviderCredentialsRow, Horizontal {
|
36
|
+
height: auto;
|
37
|
+
}
|
38
|
+
|
39
|
+
.storage_name {
|
40
|
+
width: 45%;
|
41
|
+
}
|
42
|
+
|
43
|
+
.credentials_name {
|
44
|
+
width: 35%;
|
45
|
+
}
|
46
|
+
|
47
|
+
.storage_delete {
|
48
|
+
width: 20%;
|
49
|
+
}
|
50
|
+
|
51
|
+
& > Select {
|
52
|
+
margin-bottom: 1;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
File without changes
|
@@ -0,0 +1,100 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from enum import Enum
|
3
|
+
|
4
|
+
from dependency_injector.wiring import Provide
|
5
|
+
from textual import on
|
6
|
+
from textual.app import ComposeResult
|
7
|
+
from textual.containers import Container, Horizontal, VerticalScroll
|
8
|
+
from textual.screen import ModalScreen
|
9
|
+
from textual.widgets import Label, Select
|
10
|
+
|
11
|
+
from sourcerer.infrastructure.access_credentials.services import CredentialsService
|
12
|
+
from sourcerer.presentation.di_container import DiContainer
|
13
|
+
from sourcerer.presentation.screens.shared.widgets.button import Button
|
14
|
+
from sourcerer.presentation.screens.shared.widgets.labeled_input import LabeledInput
|
15
|
+
|
16
|
+
|
17
|
+
class ControlsEnum(Enum):
|
18
|
+
CANCEL = "Cancel"
|
19
|
+
CREATE = "Create"
|
20
|
+
|
21
|
+
|
22
|
+
@dataclass
|
23
|
+
class StorageEntry:
|
24
|
+
name: str
|
25
|
+
credentials_uuid: str
|
26
|
+
|
27
|
+
|
28
|
+
class StoragesRegistrationScreen(ModalScreen):
|
29
|
+
CSS_PATH = "styles.tcss"
|
30
|
+
|
31
|
+
MAIN_CONTAINER_ID = "StoragesRegistrationScreen"
|
32
|
+
SETTINGS_CONTAINER_ID = "settings"
|
33
|
+
CREDENTIALS_SELECTOR_ID = "credentials_selector"
|
34
|
+
|
35
|
+
PROVIDERS_NAME = "credentials"
|
36
|
+
|
37
|
+
def __init__(
|
38
|
+
self,
|
39
|
+
credentials_service: CredentialsService = Provide[
|
40
|
+
DiContainer.credentials_repository
|
41
|
+
],
|
42
|
+
*args,
|
43
|
+
**kwargs,
|
44
|
+
):
|
45
|
+
super().__init__(*args, **kwargs)
|
46
|
+
self.credentials = credentials_service.list()
|
47
|
+
self.auth_method = None
|
48
|
+
|
49
|
+
def compose(self) -> ComposeResult:
|
50
|
+
with Container(id=self.MAIN_CONTAINER_ID):
|
51
|
+
with VerticalScroll(id=self.SETTINGS_CONTAINER_ID):
|
52
|
+
yield LabeledInput(
|
53
|
+
"storage_name",
|
54
|
+
"Name:",
|
55
|
+
True,
|
56
|
+
multiline=False,
|
57
|
+
id="storage_name",
|
58
|
+
)
|
59
|
+
yield Label("* Credentials:", classes="form_label")
|
60
|
+
yield Select(
|
61
|
+
options=((item.name, item.uuid) for item in self.credentials),
|
62
|
+
name=self.PROVIDERS_NAME,
|
63
|
+
id=self.CREDENTIALS_SELECTOR_ID,
|
64
|
+
)
|
65
|
+
with Horizontal(id="controls"):
|
66
|
+
yield Button(ControlsEnum.CANCEL.value, name=ControlsEnum.CANCEL.name)
|
67
|
+
yield Button(ControlsEnum.CREATE.value, name=ControlsEnum.CREATE.name)
|
68
|
+
|
69
|
+
@on(Button.Click)
|
70
|
+
def on_control_button_click(self, event: Button.Click):
|
71
|
+
"""
|
72
|
+
Handle click events for control buttons on the registration screen.
|
73
|
+
|
74
|
+
Depending on the action associated with the button click event, either dismiss
|
75
|
+
the screen or gather authentication fields and then dismiss the screen with
|
76
|
+
the collected data.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
event (Button.Click): The click event containing the action to be performed.
|
80
|
+
|
81
|
+
Flow:
|
82
|
+
1. Check if the event.action is ControlsEnum.cancel.name. If true, dismiss the screen.
|
83
|
+
2. If event.action is ControlsEnum.create.name, gather authentication fields. Dismiss the screen with the
|
84
|
+
collected authentication fields.
|
85
|
+
"""
|
86
|
+
if event.action == ControlsEnum.CANCEL.name:
|
87
|
+
self.dismiss()
|
88
|
+
elif event.action == ControlsEnum.CREATE.name:
|
89
|
+
storage_name = self.query_one("#storage_name", LabeledInput).get().value
|
90
|
+
if not storage_name:
|
91
|
+
self.notify("Storage name is required", severity="error")
|
92
|
+
return
|
93
|
+
credentials_uuid = self.query_one(
|
94
|
+
f"#{self.CREDENTIALS_SELECTOR_ID}", Select
|
95
|
+
).value
|
96
|
+
if not credentials_uuid or credentials_uuid == Select.BLANK:
|
97
|
+
self.notify("Credentials are required", severity="error")
|
98
|
+
return
|
99
|
+
|
100
|
+
self.dismiss(StorageEntry(storage_name, credentials_uuid)) # type: ignore
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
Container {
|
3
|
+
height: auto;
|
4
|
+
}
|
5
|
+
|
6
|
+
Label {
|
7
|
+
padding-left: 1;
|
8
|
+
}
|
9
|
+
|
10
|
+
StoragesRegistrationScreen {
|
11
|
+
align: center middle;
|
12
|
+
content-align: center top;
|
13
|
+
|
14
|
+
& > #StoragesRegistrationScreen {
|
15
|
+
padding: 1 2 0 2;
|
16
|
+
margin: 0 0;
|
17
|
+
width: 70;
|
18
|
+
height: 17;
|
19
|
+
border: solid $secondary-background;
|
20
|
+
|
21
|
+
& > #settings {
|
22
|
+
width: 100%;
|
23
|
+
height: 11;
|
24
|
+
|
25
|
+
& > .form_label {
|
26
|
+
padding-left: 1;
|
27
|
+
margin-bottom: 1;
|
28
|
+
|
29
|
+
}
|
30
|
+
|
31
|
+
& > #credentials_fields_container {
|
32
|
+
margin-top: 2;
|
33
|
+
padding-left: 2;
|
34
|
+
}
|
35
|
+
|
36
|
+
& > Select {
|
37
|
+
margin-bottom: 1;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
@@ -3,29 +3,42 @@
|
|
3
3
|
This module contains various configuration constants and settings used throughout
|
4
4
|
the application, including UI elements and display configurations.
|
5
5
|
"""
|
6
|
+
from enum import Enum
|
6
7
|
|
7
8
|
NO_DATA_LOGO = """
|
8
|
-
### ###
|
9
|
-
### ###
|
10
|
-
#### ####
|
11
|
-
#### ####
|
12
|
-
#######################
|
13
|
-
###### ######### ######
|
14
|
-
###### ######### ######
|
9
|
+
### ###
|
10
|
+
### ###
|
11
|
+
#### ####
|
12
|
+
#### ####
|
13
|
+
#######################
|
14
|
+
###### ######### ######
|
15
|
+
###### ######### ######
|
15
16
|
###################################
|
16
17
|
###################################
|
17
18
|
### ####################### ###
|
18
19
|
### ####################### ###
|
19
20
|
### ### ### ###
|
20
|
-
####### #######
|
21
|
-
####### #######
|
22
|
-
|
23
|
-
|
24
|
-
### ## ## #
|
25
|
-
#### ## #### ###### #### #### #####
|
26
|
-
## ## ## ## ## ## ## #### # ####
|
27
|
-
## #### ## ## ## ## ## ## # ## ##
|
28
|
-
## ## #### ##### ###### ### ### #
|
21
|
+
####### #######
|
22
|
+
####### #######
|
23
|
+
|
24
|
+
|
25
|
+
### ## ## #
|
26
|
+
#### ## #### ###### #### #### #####
|
27
|
+
## ## ## ## ## ## ## #### # ####
|
28
|
+
## #### ## ## ## ## ## ## # ## ##
|
29
|
+
## ## #### ##### ###### ### ### #
|
29
30
|
"""
|
30
31
|
|
31
32
|
MIN_SECTION_DIMENSION = 10
|
33
|
+
|
34
|
+
|
35
|
+
class KeyBindings(Enum):
|
36
|
+
"""Enum representing key bindings for various actions in the application."""
|
37
|
+
|
38
|
+
ARROW_DOWN = "down"
|
39
|
+
ARROW_UP = "up"
|
40
|
+
ARROW_RIGHT = "right"
|
41
|
+
ARROW_LEFT = "left"
|
42
|
+
ENTER = "enter"
|
43
|
+
BACKSPACE = "backspace"
|
44
|
+
CTRL = "ctrl"
|
sourcerer/presentation/utils.py
CHANGED
@@ -4,13 +4,16 @@ Utility functions for the presentation layer.
|
|
4
4
|
This module provides helper functions for the presentation layer,
|
5
5
|
particularly for retrieving and initializing storage provider services.
|
6
6
|
"""
|
7
|
+
from dependency_injector.wiring import Provide
|
7
8
|
|
9
|
+
from sourcerer.domain.access_credentials.repositories import BaseCredentialsRepository
|
8
10
|
from sourcerer.domain.storage_provider.services import BaseStorageProviderService
|
9
11
|
from sourcerer.infrastructure.access_credentials.exceptions import CredentialsAuthError
|
10
12
|
from sourcerer.infrastructure.access_credentials.registry import (
|
11
13
|
access_credential_method_registry,
|
12
14
|
)
|
13
15
|
from sourcerer.infrastructure.storage_provider.registry import storage_provider_registry
|
16
|
+
from sourcerer.presentation.di_container import DiContainer
|
14
17
|
|
15
18
|
|
16
19
|
def get_provider_service_by_access_uuid(
|
@@ -32,6 +35,9 @@ def get_provider_service_by_access_uuid(
|
|
32
35
|
|
33
36
|
def get_provider_service_by_access_credentials(
|
34
37
|
credentials,
|
38
|
+
credentials_repo: BaseCredentialsRepository = Provide[
|
39
|
+
DiContainer.credentials_repository
|
40
|
+
],
|
35
41
|
) -> BaseStorageProviderService | None:
|
36
42
|
"""
|
37
43
|
Retrieves a storage provider service instance using the given access credentials.
|
@@ -67,7 +73,9 @@ def get_provider_service_by_access_credentials(
|
|
67
73
|
return None
|
68
74
|
|
69
75
|
try:
|
70
|
-
auth_credentials = credentials_service().authenticate(
|
76
|
+
auth_credentials = credentials_service(credentials_repo).authenticate(
|
77
|
+
credentials.credentials
|
78
|
+
)
|
71
79
|
except CredentialsAuthError:
|
72
80
|
return None
|
73
81
|
return provider_service_class(auth_credentials)
|
@@ -1,31 +0,0 @@
|
|
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)
|
File without changes
|
File without changes
|
File without changes
|