refactor: convert hotkey module to package with evdev backend
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,16 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import sys
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from whisper_local.hotkey import HotkeyListener
|
pytestmark = pytest.mark.skipif(sys.platform != "linux", reason="evdev only available on Linux")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def listener():
|
def listener():
|
||||||
return HotkeyListener(key_name="KEY_F12")
|
from whisper_local.hotkey._evdev import EvdevHotkeyListener
|
||||||
|
return EvdevHotkeyListener(key_name="KEY_F12")
|
||||||
|
|
||||||
|
|
||||||
class TestHotkeyListener:
|
class TestHotkeyListener:
|
||||||
@@ -33,6 +35,5 @@ class TestHotkeyListener:
|
|||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_no_callback_no_error(self, listener):
|
async def test_no_callback_no_error(self, listener):
|
||||||
# Kein Callback gesetzt — soll nicht crashen
|
|
||||||
await listener._handle_key_event(key_down=True)
|
await listener._handle_key_event(key_down=True)
|
||||||
await listener._handle_key_event(key_down=False)
|
await listener._handle_key_event(key_down=False)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
"""Hotkey-Listener — plattformspezifische Backends hinter gemeinsamem Interface."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from typing import Callable, Coroutine, Protocol, runtime_checkable
|
||||||
|
|
||||||
|
AsyncCallback = Callable[[], Coroutine]
|
||||||
|
|
||||||
|
|
||||||
|
@runtime_checkable
|
||||||
|
class HotkeyListener(Protocol):
|
||||||
|
on_press: AsyncCallback | None
|
||||||
|
on_release: AsyncCallback | None
|
||||||
|
|
||||||
|
async def listen(self) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
|
def create_listener(key_name: str = "KEY_F12") -> HotkeyListener:
|
||||||
|
"""Erstellt den plattformspezifischen HotkeyListener."""
|
||||||
|
if sys.platform == "linux":
|
||||||
|
from whisper_local.hotkey._evdev import EvdevHotkeyListener
|
||||||
|
return EvdevHotkeyListener(key_name)
|
||||||
|
else:
|
||||||
|
from whisper_local.hotkey._pynput import PynputHotkeyListener
|
||||||
|
return PynputHotkeyListener(key_name)
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
"""Hotkey-Listener via evdev für Push-to-Talk."""
|
"""Hotkey-Listener via evdev für Push-to-Talk (Linux)."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
|
||||||
from typing import Callable, Coroutine
|
|
||||||
|
|
||||||
import evdev
|
import evdev
|
||||||
from evdev import InputDevice, categorize, ecodes
|
from evdev import InputDevice, categorize, ecodes
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
from whisper_local.hotkey import AsyncCallback
|
||||||
|
|
||||||
AsyncCallback = Callable[[], Coroutine]
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def find_keyboard_devices(key_name: str) -> list[InputDevice]:
|
def find_keyboard_devices(key_name: str) -> list[InputDevice]:
|
||||||
@@ -31,7 +29,7 @@ def find_keyboard_devices(key_name: str) -> list[InputDevice]:
|
|||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
|
||||||
class HotkeyListener:
|
class EvdevHotkeyListener:
|
||||||
def __init__(self, key_name: str = "KEY_F12"):
|
def __init__(self, key_name: str = "KEY_F12"):
|
||||||
self.key_name = key_name
|
self.key_name = key_name
|
||||||
self.key_code = ecodes.ecodes.get(key_name)
|
self.key_code = ecodes.ecodes.get(key_name)
|
||||||
Reference in New Issue
Block a user