Classify static and smart crates

This commit is contained in:
Philip Guzman
2026-06-30 18:20:05 -07:00
parent c92d929f37
commit 35713bbbb3
15 changed files with 199 additions and 23 deletions
+1
View File
@@ -123,6 +123,7 @@ def test_analyze_prints_health_without_writing_reports(tmp_path, monkeypatch, ca
assert "Overall Health: 50.0%" in output
assert "Tracks: 1" in output
assert "Crate References: 2" in output
assert "References Scored: 2" in output
assert "Healthy References: 1" in output
assert "Broken References: 1" in output
assert "Unused Tracks: 0" in output
+17
View File
@@ -3,12 +3,14 @@ from pathlib import Path
import pytest
from serato_doctor.crate_parser import (
classify_crate,
clean_path,
load_crate,
parse_crate,
parse_crates,
path_markers,
)
from serato_doctor.models.crate import CrateKind
@pytest.mark.parametrize(
@@ -84,3 +86,18 @@ def test_parse_crates_reuses_configured_roots_for_every_crate(tmp_path):
"First.mp3",
"Second.mp3",
}
@pytest.mark.parametrize(
("relative_path", "expected"),
[
("_Serato_/Subcrates/House.crate", CrateKind.STATIC),
("_Serato_/Smartcrates/Warmup.crate", CrateKind.SMART),
("_Serato_/Subcrates/Compatible by key.crate", CrateKind.SMART),
("fixtures/Unknown.crate", CrateKind.UNKNOWN),
],
)
def test_classify_crate_uses_provenance_and_known_dynamic_name(
tmp_path, relative_path, expected
):
assert classify_crate(tmp_path / relative_path) is expected
+32 -1
View File
@@ -1,6 +1,7 @@
from pathlib import Path
from serato_doctor.health import analyze_health
from serato_doctor.models.crate import Crate, CrateKind
from serato_doctor.models.library import Library
from serato_doctor.models.reference import TrackReference
from serato_doctor.models.track import DiskTrack
@@ -36,9 +37,10 @@ def test_health_report_exposes_each_metric():
assert report.score == 33.3
assert report.score_basis == (
"Resolved crate references / total crate references"
"Resolved non-dynamic references / non-dynamic references scored"
)
assert report.total_references == 3
assert report.scored_references == 3
assert report.healthy_references == 1
assert report.missing_references == 2
assert report.unique_missing_filenames == 2
@@ -54,3 +56,32 @@ def test_empty_library_has_no_health_score():
assert report.score is None
assert report.total_references == 0
assert report.scored_references == 0
def test_smart_crate_references_are_reported_but_not_scored():
static_reference = reference("Found.mp3")
smart_reference = TrackReference(
Path("Smartcrates/Dynamic.crate"),
Path("/old/House/Dynamic.mp3"),
"Dynamic.mp3",
)
crates = [
Crate(Path("Subcrates/Static.crate"), (static_reference,), CrateKind.STATIC),
Crate(
Path("Smartcrates/Dynamic.crate"),
(smart_reference,),
CrateKind.SMART,
),
]
library = Library.from_crates(crates, [track("Found.mp3")])
report = analyze_health(library)
assert report.score == 100.0
assert report.total_references == 2
assert report.scored_references == 1
assert report.missing_references == 0
assert report.static_crates == 1
assert report.smart_crates == 1
assert report.dynamic_references_excluded == 1
+8 -4
View File
@@ -1,7 +1,8 @@
import runpy
from pathlib import Path
from serato_doctor.crate_parser import parse_crates
from serato_doctor.crate_parser import load_library_crates
from serato_doctor.models.crate import CrateKind
from serato_doctor.models.library import Library
from serato_doctor.scanner import scan_audio
@@ -13,9 +14,10 @@ def test_generated_sample_library_has_expected_scenario(tmp_path):
build_sample = runpy.run_path(str(generator_path))["build_sample"]
sample_root = build_sample(tmp_path / "sample")
references = parse_crates(sample_root / "Serato" / "_Serato_" / "Subcrates")
crates = load_library_crates(sample_root / "Serato" / "_Serato_")
tracks = scan_audio(sample_root / "Music")
results = Library.build(references, tracks).reconcile_by_filename()
library = Library.from_crates(crates, tracks)
results = library.reconcile_by_filename()
missing = {
result.reference.filename
for result in results
@@ -23,6 +25,8 @@ def test_generated_sample_library_has_expected_scenario(tmp_path):
}
assert len(list((sample_root / "Serato").rglob("*.crate"))) == 7
assert len(references) == 13
assert len(library.references) == 13
assert len(tracks) == 10
assert missing == {"Missing.mp3", "Old Name.mp3"}
assert sum(crate.kind is CrateKind.STATIC for crate in crates) == 5
assert sum(crate.kind is CrateKind.SMART for crate in crates) == 2