Fix unbound prefix recovery when xmlns:dlna is absent - #53
Merged
StevenLooman merged 4 commits intoAug 15, 2026
Merged
Conversation
The strict=False recovery added in StevenLooman#35 anchored its namespace injection on an existing `xmlns:dlna` declaration. Some real-world devices (JBL Authentics, WiiM/LinkPlay) emit `<song:*>` tags without declaring `xmlns:dlna`, so the injection was silently skipped and the unbound prefix remained, raising ParseError when otherwise recoverable. Anchor the injection on the DIDL-Lite root opening tag instead. That element is guaranteed to be present in any valid DIDL-Lite document, so the recovery works regardless of which namespace declarations the producer chose to include. Also batch all missing prefixes into a single regex substitution and add a regression test that exercises the no-dlna-namespace case.
for more information, see https://pre-commit.ci
StevenLooman
left a comment
Owner
There was a problem hiding this comment.
Thank you for this PR @sfortis. Apologies for not replying earlier, I must have missed the notification mail.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #53 +/- ##
==========================================
+ Coverage 94.60% 94.82% +0.21%
==========================================
Files 3 3
Lines 408 406 -2
Branches 46 45 -1
==========================================
- Hits 386 385 -1
Misses 12 12
+ Partials 10 9 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Owner
|
Looks good to me. Can you add a Towncrier fragment, as is required for PRs? |
Contributor
Author
|
Oops, the fragment was already there but with the wrong name. Fixed. |
Owner
|
Thanks! |
Owner
|
Do you want a release with this? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The `strict=False` recovery added in #35 anchored its namespace injection on an existing `xmlns:dlna` declaration. Some real-world devices (JBL Authentics, WiiM/LinkPlay) emit `song:*` tags without declaring `xmlns:dlna`, so the injection was silently skipped and the unbound prefix remained, raising `ParseError` when the path was otherwise supposed to recover.
Observable today: `python-didl-lite==1.5.0` is shipped via `async-upnp-client` into Music Assistant, where JBL Authentics 200 owners still see ~100 `unbound prefix` errors per hour and a broken DLNA state-sync loop (downstream tracking: music-assistant/support#4398).
Fix
Anchor the namespace injection on the DIDL-Lite root opening tag (`<DIDL-Lite`) instead of the optional `xmlns:dlna` declaration. The root element is guaranteed to be present in any valid DIDL-Lite document, so recovery works regardless of which namespace declarations the producer chose to include.
Also batches all missing prefix injections into a single regex substitution rather than looping per-prefix.
Test
Added `test_from_xml_string_unbound_prefix_without_dlna_namespace` that exercises the no-`xmlns:dlna` case. The existing `test_from_xml_string_unbound_prefix` (with `xmlns:dlna` present) still passes.
```
$ python3 -m pytest tests/ -v
...
26 passed in 0.18s
```
`ruff check` clean.
Compatibility
(Replaces #52, which was accidentally opened from the wrong account.)