Skip to content

Commit 60fb926

Browse files
sumana-2705pre-commit-ci[bot]JoeZiminski
authored
[ENH] Added dropdown to select drives and to select files from the tree view while selecting location of new project (#475)
* Added dropdown to select drives in new project Signed-off-by: sumana sree <sumanasree2705@gmail.com> * updated UI of the Tree for clean view * made changes as per suggestions * used psutil replacing win32api * checked functionality in Mac and adjusted code * wrote code for linux and mac combinely * included suggested changes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added tests for SelectDirectoryTree Modal screen * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * corrected tests * updated tests for SelectDirectoryTreeScreen * corrected tests for SelectDirectoryTreeScreen * Added dropdown to select drives in new project Signed-off-by: sumana sree <sumanasree2705@gmail.com> * checked functionality in Mac and adjusted code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * corrected id in the modal_dialogs.py file * Add `psutil` to `pyproject.toml` * Refactor get_selected_drive and update test to use monkeypatching * Fix tests. * Use base dir on macos. * Small changes. * Use psutil disk_partitions(all=True) --------- Signed-off-by: sumana sree <sumanasree2705@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Joe Ziminski <55797454+JoeZiminski@users.noreply.github.com> Co-authored-by: JoeZiminski <joseph.j.ziminski@gmail.com>
1 parent d0ed5c8 commit 60fb926

3 files changed

Lines changed: 118 additions & 2 deletions

File tree

datashuttle/tui/screens/modal_dialogs.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,20 @@
1313
from datashuttle.tui.app import TuiApp
1414
from datashuttle.utils.custom_types import InterfaceOutput, Prefix
1515

16+
import platform
1617
from pathlib import Path
1718

19+
import psutil
1820
from textual.containers import Container, Horizontal
1921
from textual.screen import ModalScreen
20-
from textual.widgets import Button, Input, Label, LoadingIndicator, Static
22+
from textual.widgets import (
23+
Button,
24+
Input,
25+
Label,
26+
LoadingIndicator,
27+
Select,
28+
Static,
29+
)
2130

2231
from datashuttle.tui.custom_widgets import CustomDirectoryTree
2332
from datashuttle.tui.utils.tui_decorators import (
@@ -201,6 +210,12 @@ def compose(self) -> ComposeResult:
201210

202211
yield Container(
203212
Static(label_message, id="select_directory_tree_screen_label"),
213+
Select(
214+
[(drive, drive) for drive in self.get_drives()],
215+
value=self.get_selected_drive(),
216+
allow_blank=False,
217+
id="select_directory_tree_drive_select",
218+
),
204219
CustomDirectoryTree(
205220
self.mainwindow,
206221
self.path_,
@@ -210,6 +225,48 @@ def compose(self) -> ComposeResult:
210225
id="select_directory_tree_container",
211226
)
212227

228+
@staticmethod
229+
def get_drives():
230+
"""
231+
Get drives available on the machine to switch between.
232+
For Windows, use `psutil` to get the list of drives.
233+
Otherwise, assume root is "/" and take all folders from that level.
234+
"""
235+
operating_system = platform.system()
236+
237+
assert operating_system in [
238+
"Windows",
239+
"Darwin",
240+
"Linux",
241+
], f"Unexpected operating system: {operating_system} encountered."
242+
243+
if platform.system() == "Windows":
244+
return [disk.device for disk in psutil.disk_partitions(all=True)]
245+
246+
else:
247+
return ["/"] + [
248+
f"/{dir.name}" for dir in Path("/").iterdir() if dir.is_dir()
249+
]
250+
251+
def get_selected_drive(self):
252+
"""
253+
Get the default drive which the select starts on. For windows,
254+
use the .drive attribute but for macOS and Linux this is blank.
255+
On these Os use the first folder (e.g. /Users) as the default drive.
256+
"""
257+
if platform.system() == "Windows":
258+
selected_drive = f"{self.path_.drive}\\"
259+
else:
260+
selected_drive = f"/{self.path_.parts[1]}"
261+
return selected_drive
262+
263+
def on_select_changed(self, event: Select.Changed) -> None:
264+
"""Updates the directory tree when the drive is changed."""
265+
self.path_ = Path(event.value)
266+
self.query_one("#select_directory_tree_directory_tree").path = (
267+
self.path_
268+
)
269+
213270
@require_double_click
214271
def on_directory_tree_directory_selected(
215272
self, event: DirectoryTree.DirectorySelected

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ dependencies = [
2222
"textual==3.4.0",
2323
"show-in-file-manager",
2424
"gitpython",
25-
"typeguard"
25+
"typeguard",
26+
"psutil"
2627
]
2728

2829
classifiers = [
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import pytest
2+
from tui_base import TuiBase
3+
4+
from datashuttle.tui.app import TuiApp
5+
from datashuttle.tui.screens.modal_dialogs import (
6+
SelectDirectoryTreeScreen,
7+
)
8+
9+
10+
class TestSelectTree(TuiBase):
11+
@pytest.mark.asyncio
12+
async def test_select_directory_tree(self, monkeypatch):
13+
"""
14+
Test that changing the drive in SelectDirectoryTreeScreen
15+
updates the DirectoryTree path as expected.
16+
"""
17+
18+
# Set the Select drives to be these test cases
19+
monkeypatch.setattr(
20+
SelectDirectoryTreeScreen,
21+
"get_selected_drive",
22+
staticmethod(lambda: "Drive1"),
23+
)
24+
25+
monkeypatch.setattr(
26+
SelectDirectoryTreeScreen,
27+
"get_drives",
28+
staticmethod(lambda: ["Drive1", "Drive2"]),
29+
)
30+
31+
app = TuiApp()
32+
async with app.run_test() as pilot:
33+
34+
# Open the select directory tree screen
35+
await self.scroll_to_click_pause(
36+
pilot, "#mainwindow_new_project_button"
37+
)
38+
39+
await self.scroll_to_click_pause(
40+
pilot, "#configs_local_path_select_button"
41+
)
42+
assert isinstance(pilot.app.screen, SelectDirectoryTreeScreen)
43+
44+
# Switch the select, and ensure the directory tree is updated as expected
45+
tree = pilot.app.screen.query_one(
46+
"#select_directory_tree_directory_tree"
47+
)
48+
select = pilot.app.screen.query_one(
49+
"#select_directory_tree_drive_select"
50+
)
51+
52+
select.value = "Drive1"
53+
await pilot.pause()
54+
assert str(tree.path) == "Drive1"
55+
56+
select.value = "Drive2"
57+
await pilot.pause()
58+
assert str(tree.path) == "Drive2"

0 commit comments

Comments
 (0)