diff options
| -rw-r--r-- | hyprsunset_qt/daemon.py | 45 | ||||
| -rw-r--r-- | tests/test_daemon.py | 40 |
2 files changed, 85 insertions, 0 deletions
diff --git a/hyprsunset_qt/daemon.py b/hyprsunset_qt/daemon.py new file mode 100644 index 0000000..7bf0e47 --- /dev/null +++ b/hyprsunset_qt/daemon.py @@ -0,0 +1,45 @@ +"""Control the hyprsunset daemon: status, restart, live preview via hyprctl.""" + +from __future__ import annotations + +import shlex +import subprocess +from typing import Optional + + +def is_running() -> bool: + return subprocess.run( + ["pgrep", "-x", "hyprsunset"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode == 0 + + +def live_preview( + temperature: Optional[int] = None, + gamma: Optional[float] = None, + identity: bool = False, +) -> None: + """Push values to the running daemon over IPC. No file write, no restart.""" + if identity: + subprocess.run(["hyprctl", "hyprsunset", "identity"], check=False) + return + if temperature is not None: + subprocess.run( + ["hyprctl", "hyprsunset", "temperature", str(temperature)], + check=False, + ) + if gamma is not None: + # IPC gamma is integer percent; profile gamma is a 0-2 float. + pct = str(round(gamma * 100)) + subprocess.run(["hyprctl", "hyprsunset", "gamma", pct], check=False) + + +def restart(command: str = "hyprsunset") -> None: + subprocess.run(["pkill", "hyprsunset"], check=False) + subprocess.Popen( + shlex.split(command), + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + start_new_session=True, + ) diff --git a/tests/test_daemon.py b/tests/test_daemon.py new file mode 100644 index 0000000..337dc39 --- /dev/null +++ b/tests/test_daemon.py @@ -0,0 +1,40 @@ +from unittest.mock import patch, MagicMock +from hyprsunset_qt import daemon + + +def test_is_running_true(): + with patch("hyprsunset_qt.daemon.subprocess.run") as run: + run.return_value = MagicMock(returncode=0) + assert daemon.is_running() is True + run.assert_called_once() + + +def test_is_running_false(): + with patch("hyprsunset_qt.daemon.subprocess.run") as run: + run.return_value = MagicMock(returncode=1) + assert daemon.is_running() is False + + +def test_live_preview_identity(): + with patch("hyprsunset_qt.daemon.subprocess.run") as run: + daemon.live_preview(identity=True) + run.assert_called_with( + ["hyprctl", "hyprsunset", "identity"], check=False + ) + + +def test_live_preview_temp_and_gamma(): + with patch("hyprsunset_qt.daemon.subprocess.run") as run: + daemon.live_preview(temperature=5500, gamma=0.8) + calls = [c.args[0] for c in run.call_args_list] + assert ["hyprctl", "hyprsunset", "temperature", "5500"] in calls + assert ["hyprctl", "hyprsunset", "gamma", "80"] in calls + + +def test_restart_kills_then_launches(): + with patch("hyprsunset_qt.daemon.subprocess.run") as run, \ + patch("hyprsunset_qt.daemon.subprocess.Popen") as popen: + daemon.restart("hyprsunset") + run.assert_called_with(["pkill", "hyprsunset"], check=False) + popen.assert_called_once() + assert popen.call_args[0][0] == ["hyprsunset"] |
