data-sourcerer 0.1.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.
Files changed (95) hide show
  1. data_sourcerer-0.1.0.dist-info/METADATA +52 -0
  2. data_sourcerer-0.1.0.dist-info/RECORD +95 -0
  3. data_sourcerer-0.1.0.dist-info/WHEEL +5 -0
  4. data_sourcerer-0.1.0.dist-info/entry_points.txt +2 -0
  5. data_sourcerer-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. data_sourcerer-0.1.0.dist-info/top_level.txt +1 -0
  7. sourcerer/__init__.py +15 -0
  8. sourcerer/domain/__init__.py +13 -0
  9. sourcerer/domain/access_credentials/__init__.py +7 -0
  10. sourcerer/domain/access_credentials/entities.py +53 -0
  11. sourcerer/domain/access_credentials/exceptions.py +17 -0
  12. sourcerer/domain/access_credentials/repositories.py +84 -0
  13. sourcerer/domain/access_credentials/services.py +91 -0
  14. sourcerer/domain/file_system/__init__.py +7 -0
  15. sourcerer/domain/file_system/entities.py +70 -0
  16. sourcerer/domain/file_system/exceptions.py +17 -0
  17. sourcerer/domain/file_system/services.py +64 -0
  18. sourcerer/domain/shared/__init__.py +6 -0
  19. sourcerer/domain/shared/entities.py +18 -0
  20. sourcerer/domain/storage_provider/__init__.py +7 -0
  21. sourcerer/domain/storage_provider/entities.py +86 -0
  22. sourcerer/domain/storage_provider/exceptions.py +17 -0
  23. sourcerer/domain/storage_provider/services.py +130 -0
  24. sourcerer/infrastructure/__init__.py +13 -0
  25. sourcerer/infrastructure/access_credentials/__init__.py +7 -0
  26. sourcerer/infrastructure/access_credentials/exceptions.py +16 -0
  27. sourcerer/infrastructure/access_credentials/registry.py +120 -0
  28. sourcerer/infrastructure/access_credentials/repositories.py +119 -0
  29. sourcerer/infrastructure/access_credentials/services.py +396 -0
  30. sourcerer/infrastructure/db/__init__.py +6 -0
  31. sourcerer/infrastructure/db/config.py +73 -0
  32. sourcerer/infrastructure/db/models.py +47 -0
  33. sourcerer/infrastructure/file_system/__init__.py +7 -0
  34. sourcerer/infrastructure/file_system/exceptions.py +89 -0
  35. sourcerer/infrastructure/file_system/services.py +147 -0
  36. sourcerer/infrastructure/storage_provider/__init__.py +7 -0
  37. sourcerer/infrastructure/storage_provider/exceptions.py +78 -0
  38. sourcerer/infrastructure/storage_provider/registry.py +84 -0
  39. sourcerer/infrastructure/storage_provider/services.py +509 -0
  40. sourcerer/infrastructure/utils.py +106 -0
  41. sourcerer/presentation/__init__.py +12 -0
  42. sourcerer/presentation/app.py +36 -0
  43. sourcerer/presentation/di_container.py +46 -0
  44. sourcerer/presentation/screens/__init__.py +0 -0
  45. sourcerer/presentation/screens/critical_error/__init__.py +0 -0
  46. sourcerer/presentation/screens/critical_error/main.py +78 -0
  47. sourcerer/presentation/screens/critical_error/styles.tcss +41 -0
  48. sourcerer/presentation/screens/file_system_finder/main.py +248 -0
  49. sourcerer/presentation/screens/file_system_finder/styles.tcss +44 -0
  50. sourcerer/presentation/screens/file_system_finder/widgets/__init__.py +0 -0
  51. sourcerer/presentation/screens/file_system_finder/widgets/file_system_navigator.py +810 -0
  52. sourcerer/presentation/screens/main/__init__.py +0 -0
  53. sourcerer/presentation/screens/main/main.py +469 -0
  54. sourcerer/presentation/screens/main/messages/__init__.py +0 -0
  55. sourcerer/presentation/screens/main/messages/delete_request.py +12 -0
  56. sourcerer/presentation/screens/main/messages/download_request.py +12 -0
  57. sourcerer/presentation/screens/main/messages/preview_request.py +10 -0
  58. sourcerer/presentation/screens/main/messages/resizing_rule.py +21 -0
  59. sourcerer/presentation/screens/main/messages/select_storage_item.py +11 -0
  60. sourcerer/presentation/screens/main/messages/uncheck_files_request.py +8 -0
  61. sourcerer/presentation/screens/main/messages/upload_request.py +10 -0
  62. sourcerer/presentation/screens/main/mixins/__init__.py +0 -0
  63. sourcerer/presentation/screens/main/mixins/resize_containers_watcher_mixin.py +144 -0
  64. sourcerer/presentation/screens/main/styles.tcss +32 -0
  65. sourcerer/presentation/screens/main/widgets/__init__.py +0 -0
  66. sourcerer/presentation/screens/main/widgets/gradient.py +45 -0
  67. sourcerer/presentation/screens/main/widgets/resizing_rule.py +67 -0
  68. sourcerer/presentation/screens/main/widgets/storage_content.py +691 -0
  69. sourcerer/presentation/screens/main/widgets/storage_list_sidebar.py +143 -0
  70. sourcerer/presentation/screens/preview_content/__init__.py +0 -0
  71. sourcerer/presentation/screens/preview_content/main.py +59 -0
  72. sourcerer/presentation/screens/preview_content/styles.tcss +26 -0
  73. sourcerer/presentation/screens/provider_creds_list/__init__.py +0 -0
  74. sourcerer/presentation/screens/provider_creds_list/main.py +164 -0
  75. sourcerer/presentation/screens/provider_creds_list/styles.tcss +65 -0
  76. sourcerer/presentation/screens/provider_creds_registration/__init__.py +0 -0
  77. sourcerer/presentation/screens/provider_creds_registration/main.py +264 -0
  78. sourcerer/presentation/screens/provider_creds_registration/styles.tcss +42 -0
  79. sourcerer/presentation/screens/question/__init__.py +0 -0
  80. sourcerer/presentation/screens/question/main.py +31 -0
  81. sourcerer/presentation/screens/question/styles.tcss +33 -0
  82. sourcerer/presentation/screens/shared/__init__.py +0 -0
  83. sourcerer/presentation/screens/shared/containers.py +13 -0
  84. sourcerer/presentation/screens/shared/widgets/__init__.py +0 -0
  85. sourcerer/presentation/screens/shared/widgets/button.py +54 -0
  86. sourcerer/presentation/screens/shared/widgets/labeled_input.py +80 -0
  87. sourcerer/presentation/screens/storage_action_progress/__init__.py +0 -0
  88. sourcerer/presentation/screens/storage_action_progress/main.py +476 -0
  89. sourcerer/presentation/screens/storage_action_progress/styles.tcss +43 -0
  90. sourcerer/presentation/settings.py +31 -0
  91. sourcerer/presentation/themes/__init__.py +0 -0
  92. sourcerer/presentation/themes/github_dark.py +21 -0
  93. sourcerer/presentation/utils.py +69 -0
  94. sourcerer/settings.py +72 -0
  95. sourcerer/utils.py +32 -0
@@ -0,0 +1,144 @@
1
+ import time
2
+
3
+ from textual.events import MouseMove, MouseUp
4
+
5
+ from sourcerer.presentation.screens.main.messages.resizing_rule import (
6
+ ResizingRuleSelect,
7
+ ResizingRuleRelease,
8
+ ResizingRuleMove,
9
+ )
10
+ from sourcerer.presentation.screens.main.widgets.resizing_rule import (
11
+ ResizingRule,
12
+ MoveEvent,
13
+ )
14
+ from sourcerer.presentation.settings import MIN_SECTION_DIMENSION
15
+
16
+
17
+ class ResizeContainersWatcherMixin:
18
+ """
19
+ Watches and handles the resizing of containers in a user interface.
20
+
21
+ The ResizeContainersWatcher class provides functionality to manage and respond
22
+ to events related to resizing operations. It handles events for selecting,
23
+ moving, and releasing resizing rules, ensuring that the resizing operation is
24
+ properly executed and the state is consistently maintained. This class also
25
+ manages interactions like dragging and concludes resizing tasks when necessary.
26
+
27
+ Class should be used as a mixin in classes that require resizing functionality
28
+ and is inherited from textual App.
29
+ """
30
+
31
+ required_methods = ["query_one", "refresh"]
32
+
33
+ def __init_subclass__(cls, **kwargs):
34
+ super().__init_subclass__(**kwargs)
35
+
36
+ for method in cls.required_methods:
37
+ if not hasattr(cls, method) or not callable(getattr(cls, method)):
38
+ raise TypeError(f"Class {cls.__name__} must implement method {method}")
39
+
40
+ def __init__(self, *args, **kwargs):
41
+ self.active_resizing_rule: ResizingRule | None = None
42
+
43
+ def on_resizing_rule_select(self, event: ResizingRuleSelect) -> None:
44
+ """
45
+ Handle the selection of a resizing rule by updating the active resizing rule.
46
+ Called when the user press a resizing rule.
47
+
48
+ Arguments:
49
+ event (ResizingRuleSelect): The event containing the resizing rule id.
50
+ """
51
+ self.active_resizing_rule = self.query_one(f"#{event.id}") # type: ignore
52
+
53
+ def on_resizing_rule_release(self, _: ResizingRuleRelease) -> None:
54
+ """
55
+ Handle the release (completion) of the resizing rule.
56
+
57
+ This method is responsible for resetting the active resizing rule
58
+ back to None when a resizing operation is concluded. It ensures
59
+ that the system correctly cleans up and transitions out of the
60
+ resizing state.
61
+
62
+ Arguments:
63
+ _: The `ResizingRuleRelease` object that represents the
64
+ event or the logic related to ending the resizing operation.
65
+ """
66
+ self.active_resizing_rule = None
67
+
68
+ def on_resizing_rule_move(self, event: ResizingRuleMove) -> None:
69
+ """
70
+ Handles the resizing of components during a move event and updates their styles
71
+ accordingly. This method adjusts the width or height of the components involved
72
+ based on the orientation and the delta value from the event, ensuring minimum
73
+ dimensions are maintained. Refreshes the display after updating the styles.
74
+
75
+ Arguments:
76
+ event (ResizingRuleMove): The event containing the resizing rule details.
77
+ """
78
+
79
+ prev_component = self.query_one(f"#{event.previous_component_id}") # type: ignore
80
+ next_component = self.query_one(f"#{event.next_component_id}") # type: ignore
81
+
82
+ dimension = "width" if event.orientation == "vertical" else "height"
83
+
84
+ previous_component_dimension = (
85
+ getattr(prev_component.styles, dimension).value + event.delta
86
+ )
87
+ next_component_dimension = (
88
+ getattr(next_component.styles, dimension).value - event.delta
89
+ )
90
+
91
+ if (
92
+ previous_component_dimension < MIN_SECTION_DIMENSION
93
+ or next_component_dimension < MIN_SECTION_DIMENSION
94
+ ):
95
+ return
96
+
97
+ setattr(prev_component.styles, dimension, f"{previous_component_dimension}%")
98
+ setattr(next_component.styles, dimension, f"{next_component_dimension}%")
99
+
100
+ self.refresh() # type: ignore
101
+
102
+ def on_mouse_move(self, event: MouseMove) -> None:
103
+ """
104
+ Handles mouse movement events to manage resizing operations based on the active resizing
105
+ rule. The function determines the change in position (delta) either horizontally or
106
+ vertically, depending on the orientation of the active resizing rule. If the resizing
107
+ rule is active and dragging is occurring, it updates the position accordingly.
108
+
109
+ Arguments:
110
+ event (MouseMove): The event containing the mouse movement details.
111
+ """
112
+
113
+ if not self.active_resizing_rule or not self.active_resizing_rule.dragging:
114
+ return
115
+
116
+ try:
117
+ delta = (
118
+ event.delta_x
119
+ if self.active_resizing_rule.orientation == "vertical"
120
+ else event.delta_y
121
+ )
122
+ except AttributeError:
123
+ return # No delta
124
+
125
+ self.active_resizing_rule.position = MoveEvent(
126
+ timestamp=time.time(), delta=delta
127
+ )
128
+
129
+ def on_mouse_up(self, _: MouseUp) -> None:
130
+ """
131
+ Handles the mouse-up event during a resizing rule interaction.
132
+
133
+ This method is invoked when the mouse-up event is detected. It checks if
134
+ there is an active resizing rule in operation. If such a rule exists, the
135
+ method ensures proper cleanup activities are performed and then clears the
136
+ active resizing rule, resetting it to None.
137
+
138
+ Arguments:
139
+ _: The `MouseUp` object that represents the mouse-up event.
140
+ """
141
+ if not self.active_resizing_rule:
142
+ return
143
+ self.active_resizing_rule.cleanup()
144
+ self.active_resizing_rule = None
@@ -0,0 +1,32 @@
1
+
2
+ StorageListSidebar {
3
+ width: 20%;
4
+ }
5
+
6
+ StorageContent {
7
+ width: 80%;
8
+ }
9
+
10
+ #controls {
11
+ height: auto;
12
+ align-horizontal: center;
13
+
14
+ & > Button {
15
+ border: solid $primary;
16
+ width: 10;
17
+ content-align-horizontal: center;
18
+ }
19
+ }
20
+
21
+ #header {
22
+ height: 3;
23
+ width: 100%;
24
+ color: white;
25
+ padding: 1 1 0 1;
26
+ }
27
+
28
+ Rule {
29
+ color: $background-lighten-3;
30
+ padding: 0 0;
31
+ margin: 0 0;
32
+ }
@@ -0,0 +1,45 @@
1
+ from textual.widgets import Static
2
+ from rich.text import Text
3
+
4
+
5
+ def hex_to_rgb(hex_color: str):
6
+ """
7
+ Convert a hex color string to an RGB tuple.
8
+ """
9
+ hex_color = hex_color.lstrip("#")
10
+ return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
11
+
12
+
13
+ def generate_gradient_text(text: str, start_color: str, end_color: str) -> Text:
14
+ """
15
+ Generate a gradient text effect by blending two colors across the text.
16
+ """
17
+ start_rgb = hex_to_rgb(start_color)
18
+ end_rgb = hex_to_rgb(end_color)
19
+
20
+ gradient_text = Text()
21
+
22
+ for i, char in enumerate(text):
23
+ if len(text) > 1:
24
+ blend = i / (len(text) - 1)
25
+ else:
26
+ blend = 0
27
+
28
+ r = int(start_rgb[0] + (end_rgb[0] - start_rgb[0]) * blend)
29
+ g = int(start_rgb[1] + (end_rgb[1] - start_rgb[1]) * blend)
30
+ b = int(start_rgb[2] + (end_rgb[2] - start_rgb[2]) * blend)
31
+
32
+ color = f"#{r:02x}{g:02x}{b:02x}"
33
+ gradient_text.append(char, style=color)
34
+
35
+ return gradient_text
36
+
37
+
38
+ class GradientWidget(Static):
39
+
40
+ def on_mount(self):
41
+ """
42
+ Generate a gradient text effect for the widget's content.
43
+ """
44
+ gradient = generate_gradient_text(str(self.renderable), "#9E53E0", "#FFA656")
45
+ self.update(gradient)
@@ -0,0 +1,67 @@
1
+ from dataclasses import dataclass
2
+
3
+ from textual.events import MouseDown, MouseUp
4
+ from textual.reactive import reactive
5
+ from textual.widgets import Rule
6
+
7
+ from sourcerer.presentation.screens.main.messages.resizing_rule import (
8
+ ResizingRuleMove,
9
+ ResizingRuleSelect,
10
+ ResizingRuleRelease,
11
+ )
12
+
13
+
14
+ @dataclass
15
+ class MoveEvent:
16
+ timestamp: float
17
+ delta: int
18
+
19
+
20
+ class ResizingRule(Rule, can_focus=True):
21
+ dragging: reactive[bool] = reactive(False)
22
+ position: reactive[MoveEvent | None] = reactive(None)
23
+
24
+ def __init__(self, prev_component_id, next_component_id, *args, **kwargs):
25
+ super().__init__(*args, **kwargs)
26
+ if not kwargs.get("id"):
27
+ raise ValueError("ResizingRule must have an id")
28
+ self.prev_component_id = prev_component_id
29
+ self.next_component_id = next_component_id
30
+
31
+ def on_mouse_down(self, _: MouseDown) -> None:
32
+ """Start dragging when the separator is clicked."""
33
+ self.dragging = True
34
+ self.post_message(ResizingRuleSelect(id=self.id)) # type: ignore
35
+
36
+ def on_mouse_up(self, _: MouseUp) -> None:
37
+ """Stop dragging when mouse is released."""
38
+ self.cleanup()
39
+
40
+ def watch_position(self):
41
+ """
42
+ Watch for changes in the position and post a ResizingRuleMove message if dragging is active.
43
+ """
44
+ if not self.dragging:
45
+ return
46
+
47
+ if self.position is None:
48
+ return
49
+
50
+ self.post_message(
51
+ ResizingRuleMove(
52
+ delta=self.position.delta,
53
+ previous_component_id=self.prev_component_id,
54
+ next_component_id=self.next_component_id,
55
+ orientation=self.orientation,
56
+ )
57
+ )
58
+
59
+ def cleanup(self):
60
+ """
61
+ Resets the dragging state and position, and posts a ResizingRuleRelease message to signal the end of a resize
62
+ operation.
63
+ """
64
+ self.dragging = False
65
+ self.position = None
66
+
67
+ self.post_message(ResizingRuleRelease(id=self.id)) # type: ignore