regenerate something when the sentences changed
This commit is contained in:
@@ -555,6 +555,10 @@ def test_admin_can_split_sentence_and_reindexes_following_sentences(tmp_path):
|
||||
),
|
||||
None,
|
||||
)
|
||||
repository.save_sentence_translations(
|
||||
VIDEO_HASH,
|
||||
{0: "之前。", 1: "第一段第二段", 2: "下一句。"},
|
||||
)
|
||||
|
||||
class UnavailableTranscriber:
|
||||
available = False
|
||||
@@ -586,6 +590,7 @@ def test_admin_can_split_sentence_and_reindexes_following_sentences(tmp_path):
|
||||
"Next sentence.",
|
||||
]
|
||||
assert [item.index for item in document.sentences] == [0, 1, 2, 3]
|
||||
assert all(not (item.zh_text or "").strip() for item in document.sentences)
|
||||
|
||||
|
||||
def test_admin_can_merge_adjacent_sentences_and_reindexes_following_sentences(tmp_path):
|
||||
@@ -643,6 +648,10 @@ def test_admin_can_merge_adjacent_sentences_and_reindexes_following_sentences(tm
|
||||
),
|
||||
None,
|
||||
)
|
||||
repository.save_sentence_translations(
|
||||
VIDEO_HASH,
|
||||
{0: "之前。", 1: "第一段", 2: "第二段", 3: "下一句。"},
|
||||
)
|
||||
|
||||
class UnavailableTranscriber:
|
||||
available = False
|
||||
@@ -676,6 +685,7 @@ def test_admin_can_merge_adjacent_sentences_and_reindexes_following_sentences(tm
|
||||
assert [item.index for item in document.sentences] == [0, 1, 2]
|
||||
assert [item.start_ms for item in document.sentences] == [0, 2000, 9000]
|
||||
assert [item.end_ms for item in document.sentences] == [2000, 9000, 12000]
|
||||
assert all(not (item.zh_text or "").strip() for item in document.sentences)
|
||||
|
||||
last_response = client.put(
|
||||
f"/api/v1/admin/videos/{VIDEO_HASH}/sentences/2/merge",
|
||||
@@ -684,6 +694,99 @@ def test_admin_can_merge_adjacent_sentences_and_reindexes_following_sentences(tm
|
||||
assert last_response.json()["detail"] == "No next sentence to merge with."
|
||||
|
||||
|
||||
|
||||
def test_admin_sentence_merge_restarts_subtitle_translation(tmp_path, monkeypatch):
|
||||
client = make_client(tmp_path)
|
||||
_ready_video(client.app.state.video_repository)
|
||||
requested = []
|
||||
|
||||
def translate_sentences(sentences, **kwargs):
|
||||
requested.append([(index, text) for index, text in sentences])
|
||||
return {index: f"中文:{text}" for index, text in sentences}
|
||||
|
||||
class StubAITutor:
|
||||
available = True
|
||||
|
||||
stub = StubAITutor()
|
||||
stub.translate_sentences = translate_sentences
|
||||
monkeypatch.setattr(client.app.state, "ai_tutor", stub)
|
||||
client.app.state.subtitle_translations.ai_tutor = stub
|
||||
client.app.state.subtitle_translations.post_wait_seconds = 0.2
|
||||
|
||||
first = client.post(f"/api/v1/videos/{VIDEO_HASH}/subtitle-translation")
|
||||
if not first.json().get("complete"):
|
||||
first = wait_for_subtitle_translation(client, VIDEO_HASH)
|
||||
assert first.json()["translations"] == [
|
||||
{"index": 0, "zh_text": "中文:Hello."},
|
||||
{"index": 1, "zh_text": "中文:Nice to meet you."},
|
||||
]
|
||||
|
||||
merge = client.put(f"/api/v1/admin/videos/{VIDEO_HASH}/sentences/0/merge")
|
||||
assert merge.status_code == 200, merge.text
|
||||
assert merge.json()["text"] == "Hello. Nice to meet you."
|
||||
|
||||
finished = wait_for_subtitle_translation(client, VIDEO_HASH)
|
||||
assert finished.json()["complete"] is True
|
||||
assert finished.json()["translations"] == [
|
||||
{"index": 0, "zh_text": "中文:Hello. Nice to meet you."},
|
||||
]
|
||||
document = client.app.state.video_repository.get_document(VIDEO_HASH)
|
||||
assert [sentence.text for sentence in document.sentences] == ["Hello. Nice to meet you."]
|
||||
assert [sentence.zh_text for sentence in document.sentences] == ["中文:Hello. Nice to meet you."]
|
||||
assert requested[-1] == [(0, "Hello. Nice to meet you.")]
|
||||
|
||||
|
||||
def test_admin_sentence_merge_drops_stale_in_flight_translation(tmp_path, monkeypatch):
|
||||
client = make_client(tmp_path)
|
||||
_ready_video(client.app.state.video_repository)
|
||||
started = threading.Event()
|
||||
release = threading.Event()
|
||||
requested = []
|
||||
|
||||
def translate_sentences(sentences, **kwargs):
|
||||
call_index = len(requested)
|
||||
requested.append([(index, text) for index, text in sentences])
|
||||
persist = kwargs.get("persist")
|
||||
if call_index == 0:
|
||||
if persist is not None:
|
||||
persist({0: "旧0", 1: "旧1"})
|
||||
started.set()
|
||||
assert release.wait(timeout=5)
|
||||
if persist is not None:
|
||||
persist({0: "晚0", 1: "晚1"})
|
||||
return {0: "晚0", 1: "晚1"}
|
||||
return {index: f"新:{text}" for index, text in sentences}
|
||||
|
||||
class StubAITutor:
|
||||
available = True
|
||||
|
||||
stub = StubAITutor()
|
||||
stub.translate_sentences = translate_sentences
|
||||
monkeypatch.setattr(client.app.state, "ai_tutor", stub)
|
||||
client.app.state.subtitle_translations.ai_tutor = stub
|
||||
client.app.state.subtitle_translations.post_wait_seconds = 0.2
|
||||
|
||||
response = client.post(f"/api/v1/videos/{VIDEO_HASH}/subtitle-translation")
|
||||
assert started.wait(timeout=2)
|
||||
assert response.status_code == 200, response.text
|
||||
|
||||
merge = client.put(f"/api/v1/admin/videos/{VIDEO_HASH}/sentences/0/merge")
|
||||
assert merge.status_code == 200, merge.text
|
||||
release.set()
|
||||
|
||||
finished = wait_for_subtitle_translation(client, VIDEO_HASH)
|
||||
assert finished.json()["complete"] is True
|
||||
assert finished.json()["translations"] == [
|
||||
{"index": 0, "zh_text": "新:Hello. Nice to meet you."},
|
||||
]
|
||||
document = client.app.state.video_repository.get_document(VIDEO_HASH)
|
||||
assert [sentence.zh_text for sentence in document.sentences] == [
|
||||
"新:Hello. Nice to meet you."
|
||||
]
|
||||
assert requested[0] == [(0, "Hello."), (1, "Nice to meet you.")]
|
||||
assert requested[-1] == [(0, "Hello. Nice to meet you.")]
|
||||
|
||||
|
||||
def test_admin_boundary_adjustment_updates_linked_next_start(tmp_path):
|
||||
settings = replace(Settings.from_env(), data_dir=tmp_path / "data")
|
||||
settings.ensure_directories()
|
||||
|
||||
Reference in New Issue
Block a user