Fix sanitize_filename consistency, add scanner server tests, remove stray file

- Unify sanitize_filename (organizer) and _sanitize_name (ripper): both now use
  whitelist approach — spaces→underscore, keep \w and hyphens, remove everything
  else (brackets, punctuation, commas, dots, …). _sanitize_name removed from
  ripper.py; ripper now imports sanitize_filename from organizer directly.
- Add tests/test_scanner_server.py: 15 tests covering HTTP GET/POST handlers,
  image upload queue, 404/400 error paths, _get_local_ip fallback, print_qr
  graceful degradation without qrcode installed.
- Delete empty stray file '3' from repo root.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-02-19 14:20:03 +01:00
commit 7135e681f8
5 changed files with 258 additions and 51 deletions

View file

@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
from musiksammlung.config import AudioFormat
from musiksammlung.models import Album, Disc, Track, TrackInfo
from musiksammlung.organizer import sanitize_filename
from musiksammlung.ripper import (
RipperConfig,
_clean_input,
@ -12,38 +13,37 @@ from musiksammlung.ripper import (
_parse_cddb_lines,
_parse_grab_tracks,
_rename_files,
_sanitize_name,
interactive_rip,
)
class TestSanitizeName:
"""Tests für _sanitize_name."""
"""Tests für sanitize_filename (aus organizer, genutzt von ripper und apply)."""
def test_replace_spaces(self) -> None:
assert _sanitize_name("Hello World") == "Hello_World"
assert _sanitize_name("Test Track Title") == "Test_Track_Title"
assert sanitize_filename("Hello World") == "Hello_World"
assert sanitize_filename("Test Track Title") == "Test_Track_Title"
def test_remove_invalid_chars(self) -> None:
assert _sanitize_name("Test/Track:Name") == "TestTrackName"
assert _sanitize_name('Test<Track>"Name') == "TestTrackName"
assert _sanitize_name("Test|Track?Name*") == "TestTrackName"
assert _sanitize_name("It's_a_Test") == "Its_a_Test"
assert sanitize_filename("Test/Track:Name") == "TestTrackName"
assert sanitize_filename('Test<Track>"Name') == "TestTrackName"
assert sanitize_filename("Test|Track?Name*") == "TestTrackName"
assert sanitize_filename("It's_a_Test") == "Its_a_Test"
def test_remove_brackets_and_punctuation(self) -> None:
assert _sanitize_name("Best of (1990)") == "Best_of_1990"
assert _sanitize_name("Hello, World!") == "Hello_World"
assert _sanitize_name("Vol. 2") == "Vol_2"
assert _sanitize_name("Salt & Pepper [Remix]") == "Salt_Pepper_Remix"
assert _sanitize_name("The Best of... (Deluxe Edition)") == "The_Best_of_Deluxe_Edition"
assert sanitize_filename("Best of (1990)") == "Best_of_1990"
assert sanitize_filename("Hello, World!") == "Hello_World"
assert sanitize_filename("Vol. 2") == "Vol_2"
assert sanitize_filename("Salt & Pepper [Remix]") == "Salt_Pepper_Remix"
assert sanitize_filename("The Best of... (Deluxe Edition)") == "The_Best_of_Deluxe_Edition"
def test_keep_umlauts(self) -> None:
assert _sanitize_name("Grüße aus Österreich") == "Grüße_aus_Österreich"
assert _sanitize_name("Schöne Sänger") == "Schöne_Sänger"
assert sanitize_filename("Grüße aus Österreich") == "Grüße_aus_Österreich"
assert sanitize_filename("Schöne Sänger") == "Schöne_Sänger"
def test_strip_underscores(self) -> None:
assert _sanitize_name("_Test_") == "Test"
assert _sanitize_name(" _Test_ ") == "Test"
assert sanitize_filename("_Test_") == "Test"
assert sanitize_filename(" _Test_ ") == "Test"
class TestCleanInput: