fix(startup): allow launch without pynput backend (#448)

This commit is contained in:
Jatin K Malik
2026-06-02 12:06:20 -07:00
committed by GitHub
parent b3c73dd872
commit 6dff5b2296
4 changed files with 33 additions and 14 deletions
+3 -8
View File
@@ -103,14 +103,9 @@ def check_dependencies():
"AppIndicator3/AyatanaAppIndicator3 - Required for system tray icon"
)
# pynput is used for keyboard detection but we check at module startup
# requests is used by various components
# These are intentional checks to provide user-friendly error messages
try:
import pynput # noqa: F401
except ImportError:
missing_python_deps.append("pynput (install with: pip install pynput)")
# Keyboard backends are optional and checked lazily by the shortcut manager.
# Importing pynput can fail on Wayland/X-less sessions even when installed.
# requests is used by various components and should remain a required check.
try:
import requests # noqa: F401
except ImportError:
@@ -26,17 +26,13 @@ logger = logging.getLogger(__name__)
# Import available backends
try:
from .evdev_backend import EvdevKeyboardBackend
EVDEV_AVAILABLE = True
from .evdev_backend import EVDEV_AVAILABLE, EvdevKeyboardBackend
except ImportError:
EvdevKeyboardBackend = None # type: ignore
EVDEV_AVAILABLE = False
try:
from .pynput_backend import PynputKeyboardBackend
PYNPUT_AVAILABLE = True
from .pynput_backend import PYNPUT_AVAILABLE, PynputKeyboardBackend
except ImportError:
PynputKeyboardBackend = None # type: ignore
PYNPUT_AVAILABLE = False
+9
View File
@@ -22,11 +22,20 @@ from vocalinux.ui.keyboard_backends import (
DesktopEnvironment,
create_backend,
)
from vocalinux.ui.keyboard_backends.evdev_backend import EVDEV_AVAILABLE as EVDEV_BACKEND_AVAILABLE
from vocalinux.ui.keyboard_backends.pynput_backend import (
PYNPUT_AVAILABLE as PYNPUT_BACKEND_AVAILABLE,
)
class TestDesktopEnvironmentDetect:
"""Test DesktopEnvironment.detect() method."""
def test_package_availability_flags_match_backend_modules(self):
"""Test package-level availability flags mirror backend import checks."""
assert EVDEV_AVAILABLE == EVDEV_BACKEND_AVAILABLE
assert PYNPUT_AVAILABLE == PYNPUT_BACKEND_AVAILABLE
def test_detect_xdg_session_type_wayland(self):
"""Test detection of Wayland via XDG_SESSION_TYPE."""
with patch.dict(os.environ, {"XDG_SESSION_TYPE": "wayland"}, clear=False):
+19
View File
@@ -447,6 +447,25 @@ class TestCheckDependencies(unittest.TestCase):
result = check_dependencies()
self.assertTrue(result)
def test_check_dependencies_does_not_require_pynput(self):
"""Test startup is allowed when the optional pynput backend is unavailable."""
mock_gi = MagicMock()
mock_gi.require_version = MagicMock()
mock_gtk = MagicMock()
mock_appindicator = MagicMock()
mock_requests = MagicMock()
with patch.dict(
"sys.modules",
{
"gi": mock_gi,
"gi.repository": MagicMock(Gtk=mock_gtk, AppIndicator3=mock_appindicator),
"requests": mock_requests,
},
):
result = check_dependencies()
self.assertTrue(result)
def test_check_dependencies_missing_gtk(self):
"""Test when GTK is missing."""