diff --git a/mpris.py b/mpris.py index a274c67..ca486f4 100644 --- a/mpris.py +++ b/mpris.py @@ -52,7 +52,7 @@ except ImportError: def __init__(self, name: str) -> None: self._interface_name = name def emit_properties_changed(self, changed, invalidated) -> None: - pass + """Stub — no-op; real implementation emits D-Bus PropertiesChanged.""" ServiceInterface = _FallbackServiceInterface # type: ignore[assignment,misc] dbus_method = lambda **kw: lambda f: f diff --git a/player.py b/player.py index 31d3ca0..d95cbfd 100644 --- a/player.py +++ b/player.py @@ -61,9 +61,13 @@ except (ImportError, OSError): class _StubQThread: """Stub replacement for PySide6.QtCore.QThread.""" - def start(self) -> None: pass - def quit(self) -> None: pass - def wait(self, timeout: int = 3000) -> bool: return True + def start(self) -> None: + """Stub — no-op; real QThread would start the event loop.""" + def quit(self) -> None: + """Stub — no-op; real QThread would exit the event loop.""" + def wait(self, msecs: int = 3000) -> bool: + """Stub — returns True immediately without waiting.""" + return True QThread = _StubQThread Signal = lambda *a: lambda f: f @@ -71,47 +75,84 @@ except (ImportError, OSError): QUrl = None class _StubPlaybackState: - StoppedState = 0 - PlayingState = 1 - PausedState = 2 + """Stub mirroring QMediaPlayer.PlaybackState enum values.""" + stopped_state = 0 + playing_state = 1 + paused_state = 2 + # Backward-compatible aliases for code that uses Qt CamelCase names. + StoppedState = stopped_state + PlayingState = playing_state + PausedState = paused_state class _StubMediaStatus: - NoMedia = 0 - LoadingMedia = 1 - LoadedMedia = 2 - StalledMedia = 3 - BufferingMedia = 4 - BufferedMedia = 5 - EndOfMedia = 6 - InvalidMedia = 7 + """Stub mirroring QMediaPlayer.MediaStatus enum values.""" + no_media = 0 + loading_media = 1 + loaded_media = 2 + stalled_media = 3 + buffering_media = 4 + buffered_media = 5 + end_of_media = 6 + invalid_media = 7 + # Backward-compatible aliases for code that uses Qt CamelCase names. + NoMedia = no_media + LoadingMedia = loading_media + LoadedMedia = loaded_media + StalledMedia = stalled_media + BufferingMedia = buffering_media + BufferedMedia = buffered_media + EndOfMedia = end_of_media + InvalidMedia = invalid_media class _StubError: - NoError = 0 - ResourceError = 1 - FormatError = 2 - NetworkError = 3 - AccessDeniedError = 4 - ServiceMissingError = 5 + """Stub mirroring QMediaPlayer.Error enum values.""" + no_error = 0 + resource_error = 1 + format_error = 2 + network_error = 3 + access_denied_error = 4 + service_missing_error = 5 + # Backward-compatible aliases for code that uses Qt CamelCase names. + NoError = no_error + ResourceError = resource_error + FormatError = format_error + NetworkError = network_error + AccessDeniedError = access_denied_error + ServiceMissingError = service_missing_error class _StubQMediaPlayer: + """Stub replacement for PySide6.QtMultimedia.QMediaPlayer.""" PlaybackState = _StubPlaybackState MediaStatus = _StubMediaStatus Error = _StubError def __init__(self): - self._playback_state = _StubPlaybackState.StoppedState + self._playback_state = _StubPlaybackState.stopped_state - def setSource(self, url) -> None: pass - def play(self) -> None: pass - def pause(self) -> None: pass - def stop(self) -> None: pass - def setPosition(self, ms: int) -> None: pass - def position(self) -> int: return 0 - def duration(self) -> int: return 0 - def playbackState(self) -> int: + def set_source(self, url) -> None: + """Stub — no-op; real QMediaPlayer would load media from *url*.""" + def play(self) -> None: + """Stub — no-op; real QMediaPlayer would start playback.""" + def pause(self) -> None: + """Stub — no-op; real QMediaPlayer would pause playback.""" + def stop(self) -> None: + """Stub — no-op; real QMediaPlayer would stop playback.""" + def set_position(self, ms: int) -> None: + """Stub — no-op; real QMediaPlayer would seek to *ms*.""" + def position(self) -> int: + """Stub — returns 0; real QMediaPlayer returns current position in ms.""" + return 0 + def duration(self) -> int: + """Stub — returns 0; real QMediaPlayer returns media duration in ms.""" + return 0 + def get_playback_state(self) -> int: + """Stub — returns the current playback state value.""" return self._playback_state - def audioOutput(self): return None - def setAudioOutput(self, output) -> None: pass + def get_audio_output(self): + """Stub — returns None; real QMediaPlayer returns its QAudioOutput.""" + return None + def set_audio_output(self, output) -> None: + """Stub — no-op; real QMediaPlayer would set its audio output.""" QMediaPlayer = _StubQMediaPlayer QAudioOutput = None diff --git a/tests/test_gui_widgets.py b/tests/test_gui_widgets.py index e1892fd..a6b72ec 100644 --- a/tests/test_gui_widgets.py +++ b/tests/test_gui_widgets.py @@ -72,11 +72,6 @@ def visualizer_mock(): return mock.MagicMock(name="visualizer") -# ═══════════════════════════════════════════════════════════════════════════════ -# AudioVisualizer -# ═══════════════════════════════════════════════════════════════════════════════ - - class TestAudioVisualizer: def test_reset_activity(self, app): @@ -90,11 +85,6 @@ class TestAudioVisualizer: _cleanup(viz, app) -# ═══════════════════════════════════════════════════════════════════════════════ -# PlaybackBar -# ═══════════════════════════════════════════════════════════════════════════════ - - class TestPlaybackBar: def test_clear_seek_flag(self, app, player_mock, visualizer_mock): @@ -154,11 +144,6 @@ class TestPlaybackBar: _cleanup(bar, app) -# ═══════════════════════════════════════════════════════════════════════════════ -# SearchPage -# ═══════════════════════════════════════════════════════════════════════════════ - - class TestSearchPage: def test_on_show_more_clicked_from_button(self, app): diff --git a/tests/test_import_fallbacks.py b/tests/test_import_fallbacks.py index 7eed7f7..2c9c654 100644 --- a/tests/test_import_fallbacks.py +++ b/tests/test_import_fallbacks.py @@ -27,7 +27,7 @@ import pytest def _clean_pyside_modules(): """Remove PySide6 and target modules from sys.modules.""" keys_to_del = [] - for key in list(sys.modules.keys()): + for key in sys.modules: if key.startswith("PySide6") or key in ("player", "gui", "discord_rpc"): keys_to_del.append(key) for key in keys_to_del: @@ -73,7 +73,7 @@ class TestPlayerQtFallback: sys.modules.pop("player", None) # PySide6 modules may have been removed, restore them by clearing # the cached import so that a fresh import re-imports the real lib. - for key in list(sys.modules.keys()): + for key in sys.modules: if key.startswith("PySide6") and key not in _ORIGINAL_PYSIDE_MODS: del sys.modules[key] @@ -145,8 +145,8 @@ class TestPlayerQtFallback: assert callable(player.QThread.quit) assert callable(player.QThread.wait) # Quick functional check - QTh = player.QThread - inst = QTh() + qt_cls = player.QThread + inst = qt_cls() inst.start() # should not raise inst.quit() # should not raise assert inst.wait() is True @@ -212,7 +212,7 @@ class TestGuiQtFallback: """Remove stale fallback modules so subsequent tests get the real ones.""" for mod_name in ("gui", "player", "discord_rpc"): sys.modules.pop(mod_name, None) - for key in list(sys.modules.keys()): + for key in sys.modules: if key.startswith("PySide6") and key not in _ORIGINAL_PYSIDE_MODS: del sys.modules[key] diff --git a/tests/test_main.py b/tests/test_main.py index 200a943..ae3b2b5 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -21,10 +21,6 @@ from unittest import mock import pytest -# ═══════════════════════════════════════════════════════════════════════════ -# Helpers -# ═══════════════════════════════════════════════════════════════════════════ - def _reload_main(): """Re-import the ``main`` module with a fresh module object. @@ -113,13 +109,13 @@ class TestModuleConstants: """``_LOG_LEVEL`` is ``logging.INFO`` when not verbose.""" with mock.patch.dict("os.environ", {}, clear=True): main_mod = _reload_main() - assert main_mod._LOG_LEVEL is logging.INFO + assert main_mod._LOG_LEVEL == logging.INFO def test_log_level_debug_when_verbose(self): """``_LOG_LEVEL`` is ``logging.DEBUG`` when verbose.""" with mock.patch.dict("os.environ", {"TUNETTI_VERBOSE": "1"}, clear=True): main_mod = _reload_main() - assert main_mod._LOG_LEVEL is logging.DEBUG + assert main_mod._LOG_LEVEL == logging.DEBUG # ── _LOG_FORMAT ────────────────────────────────────────────────────── diff --git a/tests/test_mpris.py b/tests/test_mpris.py index edc08f9..f9bf141 100644 --- a/tests/test_mpris.py +++ b/tests/test_mpris.py @@ -217,7 +217,7 @@ class TestMprisPlayerInterface: assert iface.CanControl is True def test_methods_emit_via_bridge(self): - state, bridge, iface = self._make() + _, bridge, iface = self._make() for method_name, signal_name in [ ("Play", "play_requested"), ("Pause", "pause_requested"), @@ -231,7 +231,7 @@ class TestMprisPlayerInterface: mock_sig.emit.assert_called_once() def test_seek_emits_with_offset(self): - state, bridge, iface = self._make() + _, bridge, iface = self._make() with mock.patch.object(bridge, "seek_requested") as mock_sig: iface.Seek(5000) mock_sig.emit.assert_called_once_with(5000)