Skip to content

Commit cdaacde

Browse files
committed
Small changes to TUI for AWS / GDrive PR (#583)
* Use local only mode as default. * Capitalise Google Drive. * Capitalise Rclone. * Additional newline in tooltip. * Uncapitalise datashuttle, rename AWS S3 label to AWS S3 Bucket. * Extend tooltips and add example placeholders. * Small fixes * Fix missed uppercase datashuttle. * Uncomment test parameterisation. * Fix tests.
1 parent 5a619aa commit cdaacde

11 files changed

Lines changed: 77 additions & 43 deletions

File tree

datashuttle/tui/interface.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ def get_rclone_message_for_gdrive_without_browser(
559559
return False, str(e)
560560

561561
def terminate_google_drive_setup(self) -> None:
562-
"""Terminate rclone setup for google drive by killing the rclone process."""
562+
"""Terminate rclone setup for Google Drive by killing the rclone process."""
563563
assert self.google_drive_rclone_setup_process is not None
564564

565565
process = self.google_drive_rclone_setup_process
@@ -572,7 +572,7 @@ def terminate_google_drive_setup(self) -> None:
572572
def await_successful_gdrive_connection_setup_raise_on_fail(
573573
self, process: subprocess.Popen
574574
):
575-
"""Wait for rclone setup for google drive to finish and verify successful connection.
575+
"""Wait for rclone setup for Google Drive to finish and verify successful connection.
576576
577577
The `self.gdrive_setup_process_killed` flag helps prevent raising errors in case the
578578
process was killed manually.

datashuttle/tui/screens/setup_gdrive.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def on_button_pressed(self, event: Button.Pressed) -> None:
138138
def ask_user_for_browser(self) -> None:
139139
"""Ask the user if their machine has access to a browser."""
140140
message = (
141-
"Are you running Datashuttle on a machine "
141+
"Are you running datashuttle on a machine "
142142
"that can open a web browser?"
143143
)
144144
self.update_message_box_message(message)
@@ -185,7 +185,7 @@ def open_browser_and_setup_gdrive_connection(
185185
The connection setup is asynchronous so that the user is able to
186186
cancel the setup if anything goes wrong without quitting datashuttle altogether.
187187
"""
188-
message = "Please authenticate through browser."
188+
message = "Please authenticate through browser (it should open automatically)."
189189
self.update_message_box_message(message)
190190

191191
asyncio.create_task(
@@ -241,7 +241,7 @@ async def setup_gdrive_connection_and_update_ui(
241241
242242
The setup is run in a worker thread to avoid blocking the UI so that
243243
the user can cancel the setup if needed. This function starts the worker
244-
thread for google drive setup, sets `self.setup_worker` to the worker and
244+
thread for Google Drive setup, sets `self.setup_worker` to the worker and
245245
awaits the worker to finish. After completion, it displays a
246246
success / failure screen. The setup on the lower level is a bit complicated.
247247
The worker thread runs the `setup_google_drive_connection` method of the

datashuttle/tui/shared/configs_content.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ def compose(self) -> ComposeResult:
129129
Label("Root Folder ID", id="configs_gdrive_root_folder_id_label"),
130130
ClickableInput(
131131
self.parent_class.mainwindow,
132-
placeholder="Google Drive Root Folder ID",
132+
placeholder="e.g. 1KAN9QLD2K2EANE",
133133
id="configs_gdrive_root_folder_id_input",
134134
),
135135
Label("Client ID (Optional)", id="configs_gdrive_client_id_label"),
136136
ClickableInput(
137137
self.parent_class.mainwindow,
138-
placeholder="Google Drive Client ID (Optional)",
138+
placeholder="e.g. 93412981629-2icf0ba09cks9.apps.googleusercontent.com",
139139
id="configs_gdrive_client_id_input",
140140
),
141141
]
@@ -144,7 +144,7 @@ def compose(self) -> ComposeResult:
144144
Label("AWS Access Key ID", id="configs_aws_access_key_id_label"),
145145
ClickableInput(
146146
self.parent_class.mainwindow,
147-
placeholder="AWS Access Key ID eg. EJIBCLSIP2K2PQK3CDON",
147+
placeholder="eg. EJIBCLSIP2K2PQK3CDON",
148148
id="configs_aws_access_key_id_input",
149149
),
150150
Label("AWS S3 Region", id="configs_aws_region_label"),
@@ -187,7 +187,7 @@ def compose(self) -> ComposeResult:
187187
id=self.radiobutton_id_from_connection_method("gdrive"),
188188
),
189189
RadioButton(
190-
"AWS S3",
190+
"AWS S3 Bucket",
191191
id=self.radiobutton_id_from_connection_method("aws"),
192192
),
193193
id="configs_connect_method_radioset",
@@ -231,7 +231,7 @@ def compose(self) -> ComposeResult:
231231
Horizontal(
232232
Static(
233233
"Set your configurations for a new project. For more "
234-
"details on each section,\nsee the Datashuttle "
234+
"details on each section,\nsee the datashuttle "
235235
"documentation. Once configs are set, you will "
236236
"be able\nto use the 'Create' and 'Transfer' tabs.",
237237
id="configs_info_label",
@@ -276,21 +276,18 @@ def on_mount(self) -> None:
276276
]
277277
)
278278
else:
279-
self.query_one(
280-
"#configs_local_filesystem_radiobutton"
281-
).value = True
279+
self.query_one("#configs_local_only_radiobutton").value = True
282280

283-
self.setup_widgets_to_display(connection_method="local_filesystem")
281+
self.setup_widgets_to_display(connection_method=None)
284282

285283
# Setup tooltips
286284
if not self.interface:
287285
id = "#configs_name_input"
288286
self.query_one(id).tooltip = get_tooltip(id)
289287

290-
# Assumes 'local_filesystem' is default if no project set.
288+
# Assumes local-only is default if no project set.
291289
assert (
292-
self.query_one("#configs_local_filesystem_radiobutton").value
293-
is True
290+
self.query_one("#configs_local_only_radiobutton").value is True
294291
)
295292

296293
for id in [
@@ -303,6 +300,8 @@ def on_mount(self) -> None:
303300
"#configs_central_host_id_input",
304301
"#configs_gdrive_client_id_input",
305302
"#configs_gdrive_root_folder_id_input",
303+
"#configs_aws_access_key_id_input",
304+
"#configs_aws_region_select",
306305
]:
307306
self.query_one(id).tooltip = get_tooltip(id)
308307

@@ -323,7 +322,7 @@ def on_radio_set_changed(self, event: RadioSet.Changed) -> None:
323322
"Local Filesystem",
324323
"No connection (local only)",
325324
"Google Drive",
326-
"AWS S3",
325+
"AWS S3 Bucket",
327326
], "Unexpected label."
328327

329328
connection_method = self.connection_method_from_radiobutton_id(
@@ -359,11 +358,9 @@ def connection_method_from_radiobutton_id(
359358
def set_central_path_input_tooltip(
360359
self, connection_method: str | None
361360
) -> None:
362-
"""Set tooltip depending on whether connection method is SSH or local filesystem."""
361+
"""Set tooltip depending on the connection method."""
363362
if connection_method is None:
364-
tooltip = get_tooltip(
365-
"config_central_path_input_mode-local_filesystem"
366-
)
363+
tooltip = get_tooltip("config_central_path_input_mode-local_only")
367364
else:
368365
tooltip = get_tooltip(
369366
f"config_central_path_input_mode-{connection_method}"
@@ -396,9 +393,10 @@ def get_platform_dependent_example_paths(
396393
):
397394
if connection_method == "ssh":
398395
example_path = "e.g. /nfs/path_on_server/myprojects/central"
399-
elif connection_method in ["aws", "gdrive"]:
396+
elif connection_method == "aws":
397+
example_path = "my-bucket-name/my-folder"
398+
elif connection_method == "gdrive":
400399
example_path = ""
401-
402400
else:
403401
if platform.system() == "Windows":
404402
example_path = rf"e.g. C:\path\to\{local_or_central}\my_projects\my_first_project"
@@ -799,7 +797,7 @@ def setup_widgets_to_display(self, connection_method: str | None) -> None:
799797

800798
# Central Path Label
801799
central_path_label = self.query_one("#configs_central_path_label")
802-
if connection_method in ["gdrive", "aws"]:
800+
if connection_method == "gdrive":
803801
central_path_label.update(content="Central Path (Optional)")
804802
else:
805803
central_path_label.update(content="Central Path")

datashuttle/tui/tooltips.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,20 @@ def get_tooltip(id: str) -> str:
6262
"to a project folder, possibly on a mounted drive.\n\n"
6363
)
6464

65+
elif id == "config_central_path_input_mode-local_only":
66+
tooltip = "Central Path is not required in local-only mode."
67+
6568
elif id == "config_central_path_input_mode-aws":
6669
tooltip = (
67-
"The path to the project folder within the aws bucket.\n"
68-
"Leave blank if the aws bucket is the project folder."
70+
"The path to the project folder within the AWS bucket.\n\n"
71+
"The first part must be the bucket name. To transfer directly "
72+
"into the bucket, use only the bucket name."
6973
)
7074

7175
elif id == "config_central_path_input_mode-gdrive":
7276
tooltip = (
73-
"The path to the project folder within the google drive folder.\n"
74-
"Leave blank if the google drive folder is the project folder."
77+
"The path to the project folder within the Google Drive folder.\n\n"
78+
"Leave blank if the Google Drive folder is the project folder."
7579
)
7680
# Google Drive configs
7781
# -------------------------------------------------------------------------
@@ -81,15 +85,28 @@ def get_tooltip(id: str) -> str:
8185
tooltip = (
8286
"The Google Drive Client ID to use for authentication.\n\n"
8387
"It can be obtained by creating an OAuth 2.0 client in the Google Cloud Console.\n\n"
84-
"Can be left empty to use rclone's default client (slower)"
88+
"Can be left empty to use Rclone's default client (may be slower)"
8589
)
8690

8791
elif id == "#configs_gdrive_root_folder_id_input":
8892
tooltip = (
8993
"The Google Drive root folder ID to use for transfer.\n\n"
90-
"It can be obtained by navigating to the folder in Google Drive and copying the ID from the URL.\n\n"
94+
"It can be obtained by navigating to the folder in Google Drive "
95+
"and copying the ID from the URL\n(the code after the /folders/ section).\n\n"
9196
)
9297

98+
# AWS configs
99+
# -------------------------------------------------------------------------
100+
101+
elif id == "#configs_aws_access_key_id_input":
102+
tooltip = (
103+
"The Amazon IAM Access Key ID.\n\n"
104+
"Manage or create one in the AWS Console under IAM settings."
105+
)
106+
107+
elif id == "#configs_aws_region_select":
108+
tooltip = "Select the region for the S3 Bucket you are connecting to."
109+
93110
# Settings
94111
# -------------------------------------------------------------------------
95112

datashuttle/utils/gdrive.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def preliminary_for_setup_without_browser(
8080

8181
def ask_user_for_browser(log: bool = True) -> bool:
8282
"""Ask the user if they have access to an internet browser, for Google Drive set up."""
83-
message = "Are you running Datashuttle on a machine with access to a web browser? (y/n): "
83+
message = "Are you running datashuttle on a machine with access to a web browser? (y/n): "
8484
input_ = utils.get_user_input(message).lower()
8585

8686
while input_ not in ["y", "n"]:

tests/tests_integration/test_configs.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,7 @@ def test_connection_method_required_args(
292292
assert no_cfg_project.cfg["central_path"] is None
293293

294294
@pytest.mark.parametrize(
295-
"connection_method",
296-
["aws"], # "local_filesystem", "ssh", "gdrive", "
295+
"connection_method", ["aws", "local_filesystem", "ssh", "gdrive"]
297296
)
298297
def test_get_base_folder(
299298
self, tmp_path, no_cfg_project, connection_method

tests/tests_tui/gdrive/test_tui_setup_gdrive.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ async def test_cancel_gdrive_connection_setup(self, setup_project_paths):
215215
# Setup connection and cancel midway
216216
await self.setup_gdrive_connection_via_tui(pilot)
217217
assert (
218-
"Please authenticate through browser."
218+
"Please authenticate through browser"
219219
in pilot.app.screen.query_one(
220220
"#gdrive_setup_messagebox_message"
221221
).renderable
@@ -227,7 +227,7 @@ async def test_cancel_gdrive_connection_setup(self, setup_project_paths):
227227
# Try setting up the connection again
228228
await self.setup_gdrive_connection_via_tui(pilot)
229229
assert (
230-
"Please authenticate through browser."
230+
"Please authenticate through browser"
231231
in pilot.app.screen.query_one(
232232
"#gdrive_setup_messagebox_message"
233233
).renderable
@@ -302,7 +302,7 @@ async def setup_gdrive_connection_via_tui(
302302
await self.scroll_to_click_pause(pilot, "#setup_gdrive_enter_button")
303303

304304
assert (
305-
"Are you running Datashuttle on a machine "
305+
"Are you running datashuttle on a machine "
306306
"that can open a web browser?"
307307
in pilot.app.screen.query_one(
308308
"#gdrive_setup_messagebox_message"

tests/tests_tui/test_local_only_project.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ async def setup_and_check_local_only_project(
205205
"#new_project_configs_content"
206206
)
207207

208+
await self.scroll_to_click_pause(
209+
pilot, "#configs_local_filesystem_radiobutton"
210+
)
211+
208212
# Input `local_path` and placeholder text in `central_path` which
209213
# will be deleted when the no-connection option is selected.
210214
await self.fill_input(pilot, "#configs_name_input", project_name)

tests/tests_tui/test_tui_configs.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class TestTuiConfigs(TuiConfigsBase):
2020

2121
@pytest.mark.asyncio
2222
@pytest.mark.parametrize("kwargs_set", [1, 2])
23-
async def test_make_new_project_configs(
23+
async def test_make_new_project_configs__(
2424
self,
2525
empty_project_paths,
2626
kwargs_set,
@@ -69,7 +69,9 @@ async def test_make_new_project_configs(
6969
pilot,
7070
project_name,
7171
tmp_config_path,
72-
connection_method_name="SSH" if kwargs_set == 2 else "",
72+
connection_method_name="SSH"
73+
if kwargs_set == 2
74+
else "Local Filesystem",
7375
config_kwargs=kwargs,
7476
)
7577

@@ -165,6 +167,10 @@ async def test_configs_select_path(self, monkeypatch):
165167
"#new_project_configs_content"
166168
)
167169

170+
await self.scroll_to_click_pause(
171+
pilot, "#configs_local_filesystem_radiobutton"
172+
)
173+
168174
local_path_button = pilot.app.screen.query_one(
169175
"#configs_local_path_select_button"
170176
)

tests/tests_tui/test_tui_widgets_and_defaults.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async def test_new_project_configs(self, empty_project_paths):
5252
assert (
5353
configs_content.query_one("#configs_info_label").renderable
5454
== "Set your configurations for a new project. For more details on "
55-
"each section,\nsee the Datashuttle documentation. Once configs "
55+
"each section,\nsee the datashuttle documentation. Once configs "
5656
"are set, you will be able\nto use the 'Create' and 'Transfer' tabs."
5757
)
5858

@@ -108,7 +108,11 @@ async def test_new_project_configs(self, empty_project_paths):
108108
configs_content.query_one(
109109
"#configs_connect_method_radioset"
110110
).pressed_button.label._text
111-
== "Local Filesystem"
111+
== "No connection (local only)"
112+
)
113+
114+
await self.scroll_to_click_pause(
115+
pilot, "#configs_local_filesystem_radiobutton"
112116
)
113117

114118
# Central Path (Local Filesystem) ------------------------------------------

0 commit comments

Comments
 (0)