Files
spoopyghosty0--frameport/tests/test_pickers.py
T
spoopyghosty0 62e28f655e GUI: file pickers work without the desktop portal (#208)
Flet's Linux picker asks the XDG desktop portal; window managers without one (IceWM, bare X11) answer
NameHasNoOwner and every pick raised. C.pick_files / C.pick_dir now fall back to zenity or kdialog (kdialog
first on KDE; core/pickers.py, run off the UI loop), and without either to a "type the full path" box. All
twelve pickers go through them.
2026-10-12 17:58:06 -04:00

60 lines
2.6 KiB
Python

"""File-picker fallback without the desktop portal (GitHub #208): tool choice, command lines, results."""
import subprocess
from types import SimpleNamespace
import pytest
from frameport.core import pickers
def which_of(*names):
return lambda n: f"/usr/bin/{n}" if n in names else None
def test_portal_missing_only_on_linux():
exc = RuntimeError("org.freedesktop.DBus.Error.NameHasNoOwner: Could not activate remote peer")
assert pickers.portal_missing(exc, "linux")
assert not pickers.portal_missing(exc, "win32")
assert not pickers.portal_missing(ValueError("x"), "linux")
def test_choose_tool_prefers_zenity_except_on_kde():
assert pickers.choose_tool({}, which_of("zenity", "kdialog")) == ("zenity", "/usr/bin/zenity")
kde = {"XDG_CURRENT_DESKTOP": "KDE"}
assert pickers.choose_tool(kde, which_of("zenity", "kdialog")) == ("kdialog", "/usr/bin/kdialog")
assert pickers.choose_tool(kde, which_of("zenity")) == ("zenity", "/usr/bin/zenity")
assert pickers.choose_tool({}, which_of()) is None
def test_zenity_command_lines():
files = pickers.argv("zenity", "zenity", multiple=True, title="Pick", extensions=["apk", ".exe"], start="/h")
assert files == ["zenity", "--file-selection", "--title", "Pick", "--filename", "/h/", "--multiple",
"--separator", "\n", "--file-filter", "*.apk *.exe"]
folder = pickers.argv("zenity", "zenity", directory=True, start="/h/")
assert folder == ["zenity", "--file-selection", "--filename", "/h/", "--directory"]
def test_kdialog_command_lines():
files = pickers.argv("kdialog", "kd", multiple=True, title="Pick", extensions=["json"], start="/h")
assert files == ["kd", "--title", "Pick", "--getopenfilename", "/h", "*.json", "--multiple",
"--separate-output"]
assert pickers.argv("kdialog", "kd", directory=True, start="/h") == ["kd", "--getexistingdirectory", "/h"]
with pytest.raises(ValueError):
pickers.argv("yad", "yad")
def fake_run(code, out="", err=""):
return lambda cmd, **kw: SimpleNamespace(returncode=code, stdout=out, stderr=err)
def test_run_results():
assert pickers.run(["zenity"], fake_run(0, "/a b/x.apk\n/c/y.apk\n\n")) == ["/a b/x.apk", "/c/y.apk"]
assert pickers.run(["zenity"], fake_run(1)) == [] # cancelled
with pytest.raises(pickers.PickerError, match="no display"):
pickers.run(["zenity"], fake_run(5, err="no display"))
def boom(cmd, **kw):
raise subprocess.TimeoutExpired(cmd, 1)
with pytest.raises(pickers.PickerError):
pickers.run(["/usr/bin/kdialog"], boom)