fix/various fixes

This commit is contained in:
Kevin
2026-03-20 15:15:35 +08:00
parent 7f57f96c25
commit 7317bf10cd
112 changed files with 3790 additions and 2242 deletions

View File

@@ -14,7 +14,19 @@ def _mock_get_sync_db(db):
return _cm() # 返回 context manager 实例,供 with 使用
def _fake_chapter_for_pipeline():
return SimpleNamespace(
id="chapter-1",
canonical_markdown="# 标题\n\n正文若干字。",
cover_asset_id=None,
images=[],
)
class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
@patch("app.tasks.chapter_compose_tasks.recompose_chapters_for_story.delay")
@patch("app.tasks.story_image_tasks.generate_story_image.delay")
@patch("app.tasks.memoir_tasks.run_story_pipeline_for_category_batch")
@patch(
"app.features.memory.repo.retrieve_evidence_sync",
return_value={
@@ -36,14 +48,14 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
)
@patch("app.tasks.memoir_tasks._get_or_create_state_sync")
@patch("app.tasks.memoir_tasks._get_llm")
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover.delay")
@patch("app.tasks.chapter_cover_enqueue.try_enqueue_generate_chapter_cover")
@patch("app.tasks.memoir_tasks.get_sync_db")
@patch("app.tasks.memoir_tasks.MemoirImageSettings.from_env")
def test_process_memoir_segments_parses_markdown_wrapped_state_extraction_json(
self,
settings_from_env,
get_sync_db_mock,
delay_mock,
try_enqueue_mock,
get_llm_mock,
get_state_mock,
_classify_mock,
@@ -53,6 +65,9 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
_update_status_mock,
ingest_mock,
retrieve_mock,
mock_pipeline,
_delay_story_image,
_delay_recompose,
):
settings_from_env.return_value = MemoirImageSettings(
enabled=True,
@@ -70,6 +85,7 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
update_slot_mock.return_value = SimpleNamespace(
current_stage="childhood", slots={}
)
mock_pipeline.return_value = (_fake_chapter_for_pipeline(), True, {"story-1"})
llm = Mock()
bound_llm = Mock()
bound_llm.invoke.side_effect = [
@@ -83,14 +99,10 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
}
```"""
),
SimpleNamespace(
content='{"paragraphs":[{"content":"新的章节正文","image_description":"南方小镇的青石板路"}]}'
),
]
llm.bind.return_value = bound_llm
llm.invoke.side_effect = [
SimpleNamespace(content="childhood"),
SimpleNamespace(content="童年的门前"),
]
get_llm_mock.return_value = llm
@@ -103,26 +115,12 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
segments_result = Mock()
segments_result.scalars.return_value.all.return_value = [segment]
unique_result = Mock()
unique_result.scalar_one_or_none.return_value = None
chapter_result = Mock()
chapter_result.unique.return_value = unique_result
book_result = Mock()
book_result.scalar_one_or_none.return_value = None
empty_sections_result = Mock()
empty_sections_result.scalars.return_value.all.return_value = []
version_count_result = Mock()
version_count_result.scalar.return_value = 0
db = Mock()
db.execute.side_effect = [
segments_result,
chapter_result,
empty_sections_result, # _save_narrative_to_sections 内查询 ChapterSection
version_count_result, # ensure_chapter_markdown_and_version_sync 内 count
book_result,
]
db.get.return_value = None
@@ -130,7 +128,9 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
events: list[str] = []
db.commit.side_effect = lambda: events.append("commit")
delay_mock.side_effect = lambda chapter_id: events.append(f"delay:{chapter_id}")
try_enqueue_mock.side_effect = lambda chapter_id, source="pipeline": (
events.append(f"enqueue:{chapter_id}")
)
task_self = SimpleNamespace(
request=SimpleNamespace(id="task-1"),
@@ -146,11 +146,15 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
["segment-1"],
db,
)
mock_pipeline.assert_called_once()
self.assertIn("commit", events)
delay_events = [event for event in events if event.startswith("delay:")]
self.assertEqual(len(delay_events), 1)
self.assertGreater(events.index(delay_events[0]), events.index("commit"))
enqueue_events = [event for event in events if event.startswith("enqueue:")]
self.assertEqual(len(enqueue_events), 1)
self.assertGreater(events.index(enqueue_events[0]), events.index("commit"))
@patch("app.tasks.chapter_compose_tasks.recompose_chapters_for_story.delay")
@patch("app.tasks.story_image_tasks.generate_story_image.delay")
@patch("app.tasks.memoir_tasks.run_story_pipeline_for_category_batch")
@patch(
"app.features.memory.repo.retrieve_evidence_sync",
return_value={
@@ -171,14 +175,14 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
)
@patch("app.tasks.memoir_tasks._get_or_create_state_sync")
@patch("app.tasks.memoir_tasks._get_llm", return_value=None)
@patch("app.tasks.chapter_cover_tasks.generate_chapter_cover.delay")
@patch("app.tasks.chapter_cover_enqueue.try_enqueue_generate_chapter_cover")
@patch("app.tasks.memoir_tasks.get_sync_db")
@patch("app.tasks.memoir_tasks.MemoirImageSettings.from_env")
def test_process_memoir_segments_does_not_enqueue_image_jobs_when_feature_disabled(
self,
settings_from_env,
get_sync_db_mock,
delay_mock,
try_enqueue_mock,
_get_llm,
get_state_mock,
_classify_mock,
@@ -187,6 +191,9 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
_update_status_mock,
ingest_mock,
retrieve_mock,
mock_pipeline,
_delay_story_image,
_delay_recompose,
):
settings_from_env.return_value = MemoirImageSettings(
enabled=False,
@@ -201,6 +208,7 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
get_state_mock.return_value = SimpleNamespace(
current_stage="childhood", slots={}
)
mock_pipeline.return_value = (_fake_chapter_for_pipeline(), True, set())
segment = SimpleNamespace(
id="segment-1",
@@ -211,26 +219,12 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
segments_result = Mock()
segments_result.scalars.return_value.all.return_value = [segment]
unique_result = Mock()
unique_result.scalar_one_or_none.return_value = None
chapter_result = Mock()
chapter_result.unique.return_value = unique_result
book_result = Mock()
book_result.scalar_one_or_none.return_value = None
empty_sections_result = Mock()
empty_sections_result.scalars.return_value.all.return_value = []
version_count_result = Mock()
version_count_result.scalar.return_value = 0
db = Mock()
db.execute.side_effect = [
segments_result,
chapter_result,
empty_sections_result, # _save_narrative_to_sections 内查询 ChapterSection
version_count_result, # ensure_chapter_markdown_and_version_sync 内 count
book_result,
]
db.get.return_value = None
@@ -242,4 +236,4 @@ class ProcessMemoirSegmentsImageEnqueueTest(unittest.TestCase):
)
process_memoir_segments.run.__func__(task_self, "user-1", ["segment-1"])
delay_mock.assert_not_called()
try_enqueue_mock.assert_not_called()