From c7b8389b509151c62ad112650c46114c4f0f76cf Mon Sep 17 00:00:00 2001 From: David Bishop Date: Fri, 13 Feb 2026 01:48:06 -0800 Subject: [PATCH] Fix M3U parser truncating EXTINF duration to single character (#3152) The EXTINF duration parser used `info[0].strip()[0]` which takes only the first character of the duration string. For multi-digit durations like "120", this truncates to "1". Also, the `-1` check on line 79 compared against "-1" but could only ever see "-" (a single char), so negative/unknown durations were never properly detected. Remove the erroneous `[0]` index so the full duration string is used and the `-1` sentinel is correctly recognized. Co-authored-by: David Bishop Co-authored-by: Claude Opus 4.6 --- music_assistant/helpers/playlists.py | 2 +- tests/core/test_playlists.py | 29 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/core/test_playlists.py diff --git a/music_assistant/helpers/playlists.py b/music_assistant/helpers/playlists.py index c66448c6..81e501a3 100644 --- a/music_assistant/helpers/playlists.py +++ b/music_assistant/helpers/playlists.py @@ -75,7 +75,7 @@ def parse_m3u(m3u_data: str) -> list[PlaylistItem]: info = line.split("#EXTINF:")[1].split(",", 1) if len(info) != 2: continue - length = info[0].strip()[0] + length = info[0].strip() if length == "-1": length = None title = info[1].strip() diff --git a/tests/core/test_playlists.py b/tests/core/test_playlists.py new file mode 100644 index 00000000..720074e6 --- /dev/null +++ b/tests/core/test_playlists.py @@ -0,0 +1,29 @@ +"""Tests for playlist parsing helpers.""" + +from music_assistant.helpers.playlists import parse_m3u + + +def test_m3u_extinf_duration_not_truncated() -> None: + """Test that EXTINF duration is parsed as full string, not truncated to first char.""" + m3u_data = "#EXTM3U\n#EXTINF:120,Test Song\nhttp://example.com/song.mp3\n" + result = parse_m3u(m3u_data) + assert len(result) == 1 + assert result[0].length == "120" + assert result[0].title == "Test Song" + + +def test_m3u_extinf_negative_duration() -> None: + """Test that EXTINF with -1 duration is treated as None (unknown length).""" + m3u_data = "#EXTM3U\n#EXTINF:-1,Live Stream\nhttp://example.com/stream\n" + result = parse_m3u(m3u_data) + assert len(result) == 1 + assert result[0].length is None + assert result[0].title == "Live Stream" + + +def test_m3u_extinf_single_digit_duration() -> None: + """Test that single-digit durations still work correctly.""" + m3u_data = "#EXTM3U\n#EXTINF:5,Short Clip\nhttp://example.com/clip.mp3\n" + result = parse_m3u(m3u_data) + assert len(result) == 1 + assert result[0].length == "5" -- 2.34.1