Skip to content

Commit a2b1dba

Browse files
authored
Return empty tuple for no selected files (#415)
* Return empty tuple for no selected files This change makes the FileEdit in EXISTING_FILES mode return an empty tuple if no files are selected. The ability to detect "no selected file" is important to prevent parsing files that don't exist. The FileEdit has three possibilities, either it always has a Path value, or it is nullable and the neutral value should be None, or it is in multiple file selection mode and according to the signature, the neutral element should be an empty tuple. However, since `""`.split(some_delimiter)` always gives `[""]`, it currently returns a tuple with an empty path `Path(".")` which equals the home directory and is very impractical to distinguish from an intentionally selected path. * Check each individual split path for emptyness * Add test case for FileEdit value * Fix path expansion for no path and multiple paths
1 parent e383926 commit a2b1dba

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

magicgui/widgets/_concrete.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -502,21 +502,23 @@ def value(self) -> tuple[Path, ...] | Path | None:
502502
if self._nullable and not text:
503503
return None
504504
if self.mode is FileDialogMode.EXISTING_FILES:
505-
return tuple(Path(p) for p in text.split(", "))
505+
return tuple(Path(p) for p in text.split(", ") if p.strip())
506506
return Path(text)
507507

508508
@value.setter
509509
def value(self, value: Sequence[PathLike] | PathLike | None):
510510
"""Set current file path."""
511511
if value is None and self._nullable:
512512
value = ""
513-
if isinstance(value, (list, tuple)):
514-
value = ", ".join(os.fspath(p) for p in value)
515-
if not isinstance(value, (str, Path)):
513+
elif isinstance(value, (list, tuple)):
514+
value = ", ".join(os.fspath(Path(p).expanduser().absolute()) for p in value)
515+
elif isinstance(value, (str, Path)):
516+
value = os.fspath(Path(value).expanduser().absolute())
517+
else:
516518
raise TypeError(
517519
f"value must be a string, or list/tuple of strings, got {type(value)}"
518520
)
519-
self.line_edit.value = os.fspath(Path(value).expanduser().absolute())
521+
self.line_edit.value = value
520522

521523
def __repr__(self) -> str:
522524
"""Return string representation."""

tests/test_widgets.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import pytest
88
from tests import MyInt
99

10-
from magicgui import magicgui, use_app, widgets
10+
from magicgui import magicgui, types, use_app, widgets
1111
from magicgui.widgets._bases import ValueWidget
1212

1313

@@ -629,6 +629,37 @@ def test_file_dialog_button_events():
629629
assert fe.value == Path("hi")
630630

631631

632+
def test_file_edit_values():
633+
cwd = Path(".").absolute()
634+
635+
fe = widgets.FileEdit(mode=types.FileDialogMode.EXISTING_FILE)
636+
assert isinstance(fe.value, Path)
637+
638+
fe.value = Path("hi")
639+
assert fe.value == cwd / "hi"
640+
641+
fe = widgets.FileEdit(mode=types.FileDialogMode.EXISTING_FILE, nullable=True)
642+
assert fe.value is None
643+
644+
fe.value = Path("hi")
645+
assert fe.value == cwd / "hi"
646+
647+
fe.value = None
648+
assert fe.value is None
649+
650+
fe = widgets.FileEdit(mode=types.FileDialogMode.EXISTING_FILES)
651+
assert fe.value == tuple()
652+
653+
fe.value = Path("hi")
654+
assert fe.value == (cwd / "hi",)
655+
656+
fe.value = (Path("hi"), Path("world"))
657+
assert fe.value == (cwd / "hi", cwd / "world")
658+
659+
fe.value = tuple()
660+
assert fe.value == tuple()
661+
662+
632663
def test_null_events():
633664
"""Test that nullable widgets emit events when their null value is set"""
634665
wdg = widgets.ComboBox(choices=["a", "b"], nullable=True)

0 commit comments

Comments
 (0)