mirror of
https://github.com/denizsafak/abogen.git
synced 2026-09-20 11:40:57 +02:00
refactor: word substitution in planner, add planner tests
This commit is contained in:
@@ -82,17 +82,34 @@ def _extract_source_text(request: ConversionRequest) -> Optional[str]:
|
|||||||
from abogen.subtitle_utils import clean_text
|
from abogen.subtitle_utils import clean_text
|
||||||
|
|
||||||
if request.direct_text:
|
if request.direct_text:
|
||||||
return clean_text(request.direct_text)
|
text = clean_text(request.direct_text)
|
||||||
if request.source_path and request.source_path.exists():
|
elif request.source_path and request.source_path.exists():
|
||||||
encoding = "utf-8"
|
encoding = "utf-8"
|
||||||
try:
|
try:
|
||||||
with open(request.source_path, "r", encoding=encoding, errors="replace") as f:
|
with open(request.source_path, "r", encoding=encoding, errors="replace") as f:
|
||||||
text = f.read()
|
text = f.read()
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
return clean_text(text)
|
text = clean_text(text)
|
||||||
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# Apply word substitutions if configured
|
||||||
|
if request.word_substitution:
|
||||||
|
from abogen.word_substitution import apply_word_substitutions
|
||||||
|
|
||||||
|
ws = request.word_substitution
|
||||||
|
text = apply_word_substitutions(
|
||||||
|
text,
|
||||||
|
ws.substitutions_list,
|
||||||
|
ws.case_sensitive,
|
||||||
|
ws.replace_caps,
|
||||||
|
ws.replace_numerals,
|
||||||
|
ws.fix_punctuation,
|
||||||
|
)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
def _extract_metadata(request: ConversionRequest) -> Dict[str, Any]:
|
def _extract_metadata(request: ConversionRequest) -> Dict[str, Any]:
|
||||||
"""Extract metadata from source file."""
|
"""Extract metadata from source file."""
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from abogen.application.conversion_models import (
|
|||||||
OutputLayout,
|
OutputLayout,
|
||||||
SegmentPlan,
|
SegmentPlan,
|
||||||
)
|
)
|
||||||
from abogen.application.conversion_config import ChapterChunkConfig
|
from abogen.application.conversion_config import ChapterChunkConfig, WordSubstitutionConfig
|
||||||
from abogen.application.conversion_planner import build_conversion_plan
|
from abogen.application.conversion_planner import build_conversion_plan
|
||||||
from abogen.application.conversion_request import ConversionRequest
|
from abogen.application.conversion_request import ConversionRequest
|
||||||
|
|
||||||
@@ -203,6 +203,60 @@ class TestBuildConversionPlan:
|
|||||||
assert plan.chapters[0].segments[0].kind == "body"
|
assert plan.chapters[0].segments[0].kind == "body"
|
||||||
|
|
||||||
|
|
||||||
|
class TestWordSubstitution:
|
||||||
|
"""Tests for word substitution in the planner."""
|
||||||
|
|
||||||
|
def test_basic_substitution(self):
|
||||||
|
"""Single word substitution is applied."""
|
||||||
|
req = ConversionRequest(
|
||||||
|
direct_text="The quick brown fox",
|
||||||
|
voice="M1",
|
||||||
|
word_substitution=WordSubstitutionConfig(
|
||||||
|
substitutions_list="fox|cat",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
plan = build_conversion_plan(req)
|
||||||
|
assert "cat" in plan.chapters[0].body_text
|
||||||
|
assert "fox" not in plan.chapters[0].body_text
|
||||||
|
|
||||||
|
def test_multiple_substitutions(self):
|
||||||
|
"""Multiple word substitutions are applied."""
|
||||||
|
req = ConversionRequest(
|
||||||
|
direct_text="The quick brown fox jumps",
|
||||||
|
voice="M1",
|
||||||
|
word_substitution=WordSubstitutionConfig(
|
||||||
|
substitutions_list="fox|cat\nquick|slow",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
plan = build_conversion_plan(req)
|
||||||
|
text = plan.chapters[0].body_text
|
||||||
|
assert "cat" in text
|
||||||
|
assert "slow" in text
|
||||||
|
|
||||||
|
def test_substitution_preserves_chapter_markers(self):
|
||||||
|
"""Chapter markers are preserved during substitution."""
|
||||||
|
req = ConversionRequest(
|
||||||
|
direct_text="<<CHAPTER_MARKER:Ch1>>\nThe quick brown fox",
|
||||||
|
voice="M1",
|
||||||
|
word_substitution=WordSubstitutionConfig(
|
||||||
|
substitutions_list="fox|cat",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
plan = build_conversion_plan(req)
|
||||||
|
assert len(plan.chapters) >= 1
|
||||||
|
assert "cat" in plan.chapters[0].body_text
|
||||||
|
|
||||||
|
def test_no_substitution_when_disabled(self):
|
||||||
|
"""No substitution when word_substitution is None."""
|
||||||
|
req = ConversionRequest(
|
||||||
|
direct_text="The quick brown fox",
|
||||||
|
voice="M1",
|
||||||
|
word_substitution=None,
|
||||||
|
)
|
||||||
|
plan = build_conversion_plan(req)
|
||||||
|
assert "fox" in plan.chapters[0].body_text
|
||||||
|
|
||||||
|
|
||||||
class TestPlannerWithFileSource:
|
class TestPlannerWithFileSource:
|
||||||
"""Tests using actual file sources (not direct_text)."""
|
"""Tests using actual file sources (not direct_text)."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user