Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fresh off the press! I've got some check results for you. 🗞️I've aggregated the results of the automated checks for this PR below. 🔍 LintA quick update on the progress of your PR checks. 📈 ❌ ruff: issues found — see job log 📊 CoverageChecking the structural integrity of our tests. 🏗️ Files below 80% coverage (16 files)
Full report: download the ⚖️ License CheckI've verified the license compliance for your changes. ✅ ✅ No license violations found. Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed. 📋 Repo HealthScanning for any signs of 'comment' bad breath. 🌬️ ✅ All required files present. Latest Version: ✅ 🔒 Security (pip-audit)Looking for any Trojan horses in the dependencies. 🐎 ✅ No known vulnerabilities found (129 packages scanned). 🏷️ Release PreviewI've performed a final polish on the release notes. 🧼 Current:
✅ PR title follows conventional commit format. 🚀 Release Channel Compatibility Predicted next version:
🔨 Build TestsThe compiler has spoken! Here is the verdict. 📜 ✅ All versions pass
Powered by OVOS scripts and a bit of magic. ✨ |
cf5ef23 to
39f2275
Compare
39f2275 to
eb6b48b
Compare
ovos-media's feat/media-backend-v2-port branch replaces the v1 MediaBackend
contract (bus-emitting backends, handle_media_state_change) with a
report()/bind_event_reporter() contract, and drops handle_media_state_change
entirely in favour of BaseMediaService._handle_backend_event. ovoscope's
media harnesses predate that port and needed updating to keep testing the
real daemon shape rather than a v1 stand-in.
Adds MediaBackendHarness (ovoscope/media_backend.py), a plugin-author-facing
harness that binds a capturing spy reporter onto a single MediaBackend v2
plugin instance and asserts the PlaybackEvent sequence/data it reports,
without a daemon in front of it. The v2 template it targets
(ovos_plugin_manager.templates.media) only exists on the unreleased OPM
branch, so both the module import and the ovoscope/__init__.py re-export
are guarded: importing the module (and `import ovoscope`) is always safe,
and MediaBackendHarness() raises a clear ImportError only when actually
constructed against a released ovos-plugin-manager. test_media_backend_harness.py
carries the same guard at module scope (pytestmark skipif), since its
_FakePlugin stand-in subclasses the v2 template directly.
Adds MockOCPBackendV2 (ovoscope/media.py), the v2 counterpart to the existing
v1 MockOCPBackend (kept, unmodified, for unported plugins), and makes it the
OCPPlayerHarness default. Fixes OCPPlayerHarness.__enter__ to bind each
injected backend's event reporter, and to guard the v1-only
set_track_start_callback call on whether the *service* it reads
track_start from actually has that attribute (not on the backend, which a
v1 backend always has regardless of which ovos-media build is installed) —
guarding on the backend alone still crashed with AttributeError on a v2
ovos-media build. In default (no backend_factory) mode, audio_service is a
MagicMock with no real _handle_backend_event behind it, so the reporter is
bound to a small shim that reproduces the real daemon's END_OF_MEDIA/ERROR
wire translation for simulate_track_end()/simulate_invalid_stream() (the
only two events that mode's control-method API can actually drive); its
docstring names the two daemon guards (currency, staleness) it deliberately
doesn't reproduce, since a cell exercising those needs the real daemon
instead. Also drops the now-nonexistent handle_media_state_change bus
registration and a since-stale comment referencing it.
MockOCPBackendV2.load_track now clears current_uri on a failed load, so a
failed load doesn't leave a stale, PREVIOUS track's uri in place for a
following simulate_invalid_stream()/report_track_end() to report against.
Test coverage keeps working against a released ovos-plugin-manager (no v2
template): test_media.py's v2-only classes/cells are individually gated on
whether the v2 template actually imported (not merely on ovos-media being
installed), and _RecordingBackend (the backend_factory stand-in used by
several pre-existing cells) now has a v1 variant selected the same way, so
those cells stay green against a released, still-v1-shaped ovos-media
instead of silently trying to speak v2 to it. The v1 variant emits
LOADED_MEDIA on ovos.common_play.media.state, the topic a real v1
BaseMediaService actually subscribes handle_media_state_change to (not the
per-namespace ovos.{namespace}.service.media.state MockOCPBackend emits,
which no real BaseMediaService instance ever listens on).
Fail-before (temporarily reverted the source change, kept the test, ran
foreground, reverted the revert):
- set_track_start_callback hasattr guard: 16 of 42 test_media.py tests
failed (AttributeError) across every OCPPlayerHarness-based class.
- Default-mode event-reporter shim: the two new
TestOCPHarnessMediaBackendV2DefaultMode cells failed (no wire message
emitted at all) with the shim reverted to binding straight into the
MagicMock's _handle_backend_event.
- MockOCPBackendV2.load_track current_uri clearing:
test_failed_load_clears_current_uri failed with the clear removed.
Full ovoscope/test/unittests suite against released PyPI deps, python 3.10,
foreground: 655 passed, 55 skipped, 0 failed. The 55 skips are the v2-only
cells gated off without the v2 template.
CI: coverage-pages.yml and release-workflow.yml's build_tests job gain the
media, listener and bench extras, which they lacked. No workflow installs
from git: released ovos-plugin-manager (2.12.1a1, latest alpha) still ships
the v1 templates/media.py with no PlaybackEvent and no bind_event_reporter,
and released ovos-media is 2.2.5a1, so the [media] floor stays where it is
and the v2-only cells skip on the guard they already carry. They start
running once ovos-plugin-manager publishes the v2 template.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
eb6b48b to
15d0dba
Compare
ovos-media's
feat/media-backend-v2-portbranch replaces the v1MediaBackendcontract with areport()/bind_event_reporter()one: plugins report physicalPlaybackEvents (TRACK_START,PAUSED,RESUMED,STOPPED,END_OF_MEDIA,ERROR) instead of emitting bus messages themselves,load_trackreturns a bool instead of aNone, andstop()becomes a concrete template method that delegates to a plugin's_stop(). The daemon (ovos-media'sBaseMediaService) is now the sole translator from those events toovos.common_play.*wire messages, via_handle_backend_event— and it has droppedhandle_media_state_changeentirely. ovoscope's media harnesses predate this port and needed updating to keep exercising the real daemon shape.This adds
MediaBackendHarness(ovoscope/media_backend.py), a harness for a plugin author testing their ownMediaBackendv2 class in isolation: it binds a capturing spy reporter onto a backend instance and asserts the event sequence and per-event data it reports, without any daemon involved. The v2 template it targets (ovos_plugin_manager.templates.media) only exists on the unreleased OPM branch, so both the module import and theovoscope/__init__.pyre-export are guarded:import ovoscopeis always safe against a releasedovos-plugin-manager, andMediaBackendHarness()raises a clearImportErroronly when actually constructed without the v2 template installed. Its own test module carries the equivalent guard at collection time, since its plugin stand-in subclasses the v2 template directly.It also adds
MockOCPBackendV2(ovoscope/media.py), the v2 counterpart to the existingMockOCPBackend(kept unmodified, still importable, for plugin repos that haven't ported yet), and makes itOCPPlayerHarness's default injected backend.OCPPlayerHarness.__enter__now binds each injected backend's event reporter, and guards the v1-onlyset_track_start_callbackcall on whether the service it readstrack_startfrom actually has that attribute — not on the backend, which a v1 backend always has regardless of whichovos-mediabuild is installed; guarding on the backend alone still crashed withAttributeErroragainst a v2 build. In the default (nobackend_factory) mode,audio_serviceis aMagicMockwith no real_handle_backend_eventbehind it, so the backend's reporter is bound to a small shim reproducing the daemon'sEND_OF_MEDIA/ERRORwire translation — the only two events that mode's own control methods can actually drive — with its docstring naming the two daemon guards (currency, staleness) it deliberately skips, so a test needing those knows to go through the real daemon (backend_factory) instead.MockOCPBackendV2.load_tracknow clearscurrent_urion a failed load, so a failed load doesn't leave a stale, previous track's uri behind for a followingsimulate_invalid_stream()/report_track_end()to report against.Every v2-only test class and cell is now gated on whether the v2 template actually imported, not merely on
ovos-mediabeing installed, and thebackend_factorystand-in several pre-existing cells share (_RecordingBackend) now has a v1 variant selected the same way — including fixing that variant to emitLOADED_MEDIAon the topic a real v1BaseMediaServiceactually subscribes to (ovos.common_play.media.state), not the per-namespace oneMockOCPBackendemits, which no realBaseMediaServiceinstance has ever listened on. The full suite now collects and runs clean against both a releasedovos-plugin-manager(v2 cells skip) and the unreleased branches (v2 cells run) — collection used to abort entirely against released deps because a test module imported the v2 template unguarded at collection time.Fail-before (source reverted with the test kept, run foreground, then restored): the
set_track_start_callbackguard turned 16 of 42test_media.pytests failing withAttributeErroracross everyOCPPlayerHarness-based class; the default-mode event-reporter shim's two new cells failed with no wire message emitted at all when reverted to binding straight into theMagicMock's_handle_backend_event;test_failed_load_clears_current_urifailed with thecurrent_uriclear removed.Full suite against released PyPI deps on python 3.10, foreground: 655 passed, 55 skipped, 0 failed. The 55 skips are exactly the v2-only cells gated off without the v2 template.
No workflow installs from git.
coverage-pages.ymlandrelease-workflow.yml'sbuild_testsjob gain themedia,listenerandbenchextras, which they lacked, and that is the whole CI change. The releasedovos-plugin-manageris 2.12.1a1 (latest alpha; itstemplates/media.pyis still the v1 one, noPlaybackEvent, nobind_event_reporter) and releasedovos-mediais 2.2.5a1, so neither carries the v2 backend template. The[media]floor therefore stays atovos-media>=2.0.0a9and the v2 cells skip on the template guard they already carry; they start running onceovos-plugin-managerpublishes the v2 template and the floor can be raised to it.That also settles the
build_tests (3.10)failure onTestOCPHarnessWithoutHandlePlay::test_enter_and_play_succeed_when_handle_play_is_absent: it was specific to the git-branchovos-mediathosepre_install_piplines installed, not todev. Against released deps that cell passes, as does the rest of the suite.