refactor(subtitles): move SubtitlePlacer to application layer

The placer performs filesystem I/O (os.link) — it belongs in the
application layer, not the domain. Domain services should be pure.

- Move alfred/domain/subtitles/services/placer.py to
  alfred/application/subtitles/placer.py
- Move tests/domain/test_subtitle_placer.py to
  tests/application/test_subtitle_placer.py
- Update all callers (manage_subtitles use case, metadata store, tests)
- Drop placer re-exports from domain.subtitles.services.__init__
This commit is contained in:
2026-05-19 15:07:39 +02:00
parent 9556bf9e08
commit 903e9e7117
8 changed files with 9 additions and 13 deletions
@@ -8,7 +8,7 @@ from alfred.domain.subtitles.entities import SubtitleCandidate
from alfred.domain.subtitles.services.identifier import SubtitleIdentifier
from alfred.domain.subtitles.services.matcher import SubtitleMatcher
from alfred.domain.subtitles.services.pattern_detector import PatternDetector
from alfred.domain.subtitles.services.placer import (
from alfred.application.subtitles.placer import (
PlacedTrack,
SubtitlePlacer,
_build_dest_name,
@@ -5,8 +5,8 @@ import os
from dataclasses import dataclass
from pathlib import Path
from ..entities import SubtitleCandidate
from ..value_objects import SubtitleType
from alfred.domain.subtitles.entities import SubtitleCandidate
from alfred.domain.subtitles.value_objects import SubtitleType
logger = logging.getLogger(__name__)
@@ -1,13 +1,9 @@
from .identifier import SubtitleIdentifier
from .matcher import SubtitleMatcher
from .pattern_detector import PatternDetector
from .placer import PlacedTrack, PlaceResult, SubtitlePlacer
__all__ = [
"SubtitleIdentifier",
"SubtitleMatcher",
"PatternDetector",
"SubtitlePlacer",
"PlacedTrack",
"PlaceResult",
]
@@ -14,7 +14,7 @@ from pathlib import Path
from typing import Any
from alfred.domain.subtitles.entities import SubtitleCandidate
from alfred.domain.subtitles.services.placer import PlacedTrack
from alfred.application.subtitles.placer import PlacedTrack
from alfred.infrastructure.metadata.store import MetadataStore
logger = logging.getLogger(__name__)
+1 -1
View File
@@ -41,7 +41,7 @@ from alfred.application.filesystem.manage_subtitles import (
_to_unresolved_dto,
)
from alfred.domain.subtitles.entities import MediaSubtitleMetadata, SubtitleCandidate
from alfred.domain.subtitles.services.placer import PlacedTrack, PlaceResult
from alfred.application.subtitles.placer import PlacedTrack, PlaceResult
from alfred.domain.subtitles.value_objects import (
ScanStrategy,
SubtitleFormat,
@@ -1,4 +1,4 @@
"""Tests for ``alfred.domain.subtitles.services.placer.SubtitlePlacer``.
"""Tests for ``alfred.application.subtitles.placer.SubtitlePlacer``.
The placer hard-links subtitle files next to a destination video, naming
them ``{video_stem}.{lang}[.sdh|.forced].{ext}``.
@@ -22,7 +22,7 @@ from unittest.mock import patch
import pytest
from alfred.domain.subtitles.entities import SubtitleCandidate
from alfred.domain.subtitles.services.placer import (
from alfred.application.subtitles.placer import (
PlacedTrack,
PlaceResult,
SubtitlePlacer,
@@ -198,7 +198,7 @@ class TestOSError:
video.write_bytes(b"")
track = _track(src)
with patch(
"alfred.domain.subtitles.services.placer.os.link",
"alfred.application.subtitles.placer.os.link",
side_effect=OSError("cross-device link"),
):
result = placer.place([track], video)
@@ -17,7 +17,7 @@ from __future__ import annotations
from pathlib import Path
from alfred.domain.subtitles.entities import SubtitleCandidate
from alfred.domain.subtitles.services.placer import PlacedTrack
from alfred.application.subtitles.placer import PlacedTrack
from alfred.domain.subtitles.value_objects import (
SubtitleFormat,
SubtitleLanguage,