""" 测试新的两段式待确认文件 + done 信号机制。 """ import pytest import tempfile import shutil from pathlib import Path from pl_japanese.cleaner import TaskManager from pl_japanese.cleaner.workflow import CleanerWorkflow @pytest.fixture def temp_dir(): """每个测试独立的临时目录""" tmp = Path(tempfile.mkdtemp()) yield tmp shutil.rmtree(tmp, ignore_errors=True) @pytest.fixture(autouse=True) def reset_pinyin_dict(): """每个测试前重置拼音字典单例""" from pl_japanese.cleaner.pinyin_overrides import DEFAULT_DICT original_path = DEFAULT_DICT.source_path original_word = DEFAULT_DICT.word_override.copy() original_kana = DEFAULT_DICT.kana_hint.copy() yield DEFAULT_DICT.source_path = original_path DEFAULT_DICT.word_override = original_word DEFAULT_DICT.kana_hint = original_kana def test_two_section_file_generation(temp_dir): """测试两段式待确认文件生成""" tmp = temp_dir tm = TaskManager(tasks_root=str(tmp / 'tasks')) src = tmp / 'src.txt' src.write_text( '議会:ぎかい:\n' # 多音字 → 待确认 '社会:しゃかい:\n' # 多音字 → 待确认 '飲料:いんりょう:\n' # 自动通过 'IT:アイティー:\n', # 无汉字 → 建议skip encoding='utf-8') task = tm.create_task('t1', source=str(src)) main_path = str(tmp/'voc.txt') skipped_path = str(tmp/'skip.txt') wf = CleanerWorkflow(task, main=main_path, skipped=skipped_path) result = wf.run() assert result['status'] == 'reviewing' assert result['process']['auto_pass'] == 1 assert result['process']['need_review'] == 3 # 2多音字 + 1skip建议 # 检查文件结构 review_file = Path(task.review_file) content = review_file.read_text(encoding='utf-8') lines = content.splitlines() # 第一段标记 assert '自动通过' in lines[0] # 飲料在第一段 assert '飲|料:いん|りょう:yin|liao' in content # 第二段标记 assert '待确认' in content # 待确认条目 assert '議|会:ぎ|かい:yi|hui' in content assert '# 多音字' in content # skip建议(无汉字条目拼音为空) assert 'skip IT:アイティー:' in content def test_apply_review_with_modifications(temp_dir): """测试人工review后应用修改""" tmp = temp_dir tm = TaskManager(tasks_root=str(tmp / 'tasks')) src = tmp / 'src.txt' src.write_text('議会:ぎかい:\n社会:しゃかい:\n飲料:いんりょう:\n', encoding='utf-8') task = tm.create_task('t1', source=str(src)) main_path = str(tmp/'voc.txt') skipped_path = str(tmp/'skip.txt') wf = CleanerWorkflow(task, main=main_path, skipped=skipped_path) wf.run() # 模拟人工review:修改第一条拼音,第二条加skip review_file = Path(task.review_file) content = review_file.read_text(encoding='utf-8') # 修改拼音 content = content.replace('議|会:ぎ|かい:yi|hui', '議|会:ぎ|かい:yi|kuai') # 加skip标记 content = content.replace('社|会:しゃ|かい:she|hui', 'skip 社|会:しゃ|かい:she|hui') content += 'done\n' review_file.write_text(content, encoding='utf-8') # 应用 result = wf.run() assert result['status'] == 'ready' assert result['apply_result']['accepted'] == 2 # 飲料 + 議会 assert result['apply_result']['skipped'] == 1 # 社会 # 检查落地文件 proc = wf.processor auto = proc._read_clean_lines(proc.auto_done) assert len(auto) == 2 assert '飲|料:いん|りょう:yin|liao' in auto assert '議|会:ぎ|かい:yi|kuai' in auto # 修正后的拼音 skip = proc._read_clean_lines(proc.skip) assert len(skip) == 1 assert '社|会:しゃ|かい:she|hui' in skip def test_format_error_rollback_to_third_section(temp_dir): """测试格式错误回退到第三段""" tmp = temp_dir tm = TaskManager(tasks_root=str(tmp / 'tasks')) src = tmp / 'src.txt' src.write_text('議会:ぎかい:\n社会:しゃかい:\n', encoding='utf-8') task = tm.create_task('t1', source=str(src)) main_path = str(tmp/'voc.txt') skipped_path = str(tmp/'skip.txt') wf = CleanerWorkflow(task, main=main_path, skipped=skipped_path) wf.run() # 模拟人工错误修改(误删分隔符) review_file = Path(task.review_file) content = review_file.read_text(encoding='utf-8') content = content.replace('議|会:ぎ|かい:yi|hui', '議|会ぎ|かいyi|hui') content += 'done\n' review_file.write_text(content, encoding='utf-8') # 尝试应用 → 格式错误 result = wf.run() assert result['action'] == 'need_human' assert '格式错误' in result['message'] # 检查回退结果:三段结构 content_after = review_file.read_text(encoding='utf-8') lines = content_after.splitlines() # 第一段:自动通过(无) assert '自动通过' in content_after # 第二段:待确认(正确的) assert '待确认' in content_after assert '社|会:しゃ|かい:she|hui' in content_after # 第三段:格式错误 assert '格式错误,请修正' in content_after assert '議|会ぎ|かいyi|hui # 格式错误:' in content_after # done 被删除 assert 'done' not in content_after def test_skip_suggestion_can_be_accepted_or_modified(temp_dir): """测试skip建议可以接受或修改""" tmp = temp_dir tm = TaskManager(tasks_root=str(tmp / 'tasks')) src = tmp / 'src.txt' src.write_text('IT:アイティー:\nCS:シーエス:\n', encoding='utf-8') task = tm.create_task('t1', source=str(src)) main_path = str(tmp/'voc.txt') skipped_path = str(tmp/'skip.txt') wf = CleanerWorkflow(task, main=main_path, skipped=skipped_path) wf.run() review_file = Path(task.review_file) content = review_file.read_text(encoding='utf-8') # IT保持skip,CS删掉skip前缀(改为保留) # 注意:无汉字条目的拼音段为空,格式是 CS:シーエス: content = content.replace('skip CS:シーエス:', 'CS:シーエス:') content += 'done\n' review_file.write_text(content, encoding='utf-8') result = wf.run() assert result['status'] == 'ready' proc = wf.processor auto = proc._read_clean_lines(proc.auto_done) skip = proc._read_clean_lines(proc.skip) assert 'CS:シーエス:' in auto # 删skip后进auto assert 'IT:アイティー:' in skip # 保持skip def test_tilde_preserved_in_output(temp_dir): """测试~被保留在输出中(占一段,拼音留空)""" tmp = temp_dir tm = TaskManager(tasks_root=str(tmp / 'tasks')) src = tmp / 'src.txt' src.write_text('~人:アメリカじん:\n~員:かいいん:\n', encoding='utf-8') task = tm.create_task('t1', source=str(src)) main_path = str(tmp/'voc.txt') skipped_path = str(tmp/'skip.txt') wf = CleanerWorkflow(task, main=main_path, skipped=skipped_path) result = wf.run() # ~ 条目全部自动通过,直接进 auto_done(不经过待确认) assert result['status'] == 'ready' proc = wf.processor auto = proc._read_clean_lines(proc.auto_done) # ~ 占一段,拼音留空 assert '~|人:アメリカ|じん:|ren' in auto assert '~|員:かい|いん:|yuan' in auto