From 23e558fe1b106f3ab51abfb1e0a3fb788a5776ee Mon Sep 17 00:00:00 2001 From: Kenichiro NOGI Date: Sun, 2 Aug 2026 10:11:26 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=83=86=E3=83=B3=E3=83=97=E3=83=AC?= =?UTF-8?q?=E3=83=BC=E3=83=88=E9=81=B8=E5=AE=9A=E3=83=BB=E4=BE=9D=E5=AD=98?= =?UTF-8?q?=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E3=83=98=E3=83=AB=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5 --- .../ScanOCR/スクリプト/extract_and_rename.py | 38 ++++++++++++ .../tests/test_extract_and_rename.py | 58 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 PythonProj/ScanOCR/スクリプト/tests/test_extract_and_rename.py diff --git a/PythonProj/ScanOCR/スクリプト/extract_and_rename.py b/PythonProj/ScanOCR/スクリプト/extract_and_rename.py index c1b1392f..208a8d70 100644 --- a/PythonProj/ScanOCR/スクリプト/extract_and_rename.py +++ b/PythonProj/ScanOCR/スクリプト/extract_and_rename.py @@ -30,6 +30,44 @@ from box_detector import detect_template_fields, to_ratio_box DPI = 300 # PDF→画像変換の解像度。テンプレートも同じDPIで作成/スキャンしてください +import importlib + +TEMPLATE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".bmp"} + + +def select_template_file(template_dir: Path) -> Path: + candidates = sorted( + p for p in template_dir.iterdir() + if p.is_file() and p.suffix.lower() in TEMPLATE_EXTENSIONS + ) + if not candidates: + raise FileNotFoundError( + f"テンプレートフォルダに画像ファイルが見つかりません: {template_dir}" + ) + return candidates[0] + + +REQUIRED_MODULES = ("cv2", "numpy", "PIL", "pytesseract", "pdf2image") + + +def check_dependencies(modules: tuple[str, ...] = REQUIRED_MODULES) -> list[str]: + missing = [] + for mod in modules: + try: + importlib.import_module(mod) + except ImportError: + missing.append(mod) + return missing + + +def check_external_tools(tesseract_exe: Path, poppler_exe: Path) -> list[str]: + missing = [] + if not tesseract_exe.exists(): + missing.append(str(tesseract_exe)) + if not poppler_exe.exists(): + missing.append(str(poppler_exe)) + return missing + @dataclass class FieldBox: diff --git a/PythonProj/ScanOCR/スクリプト/tests/test_extract_and_rename.py b/PythonProj/ScanOCR/スクリプト/tests/test_extract_and_rename.py new file mode 100644 index 00000000..000751b1 --- /dev/null +++ b/PythonProj/ScanOCR/スクリプト/tests/test_extract_and_rename.py @@ -0,0 +1,58 @@ +from pathlib import Path + +from extract_and_rename import ( + check_dependencies, + check_external_tools, + select_template_file, +) + + +def test_select_template_file_picks_first_by_name(tmp_path): + (tmp_path / "b_template.png").write_bytes(b"x") + (tmp_path / "a_template.png").write_bytes(b"x") + (tmp_path / "note.txt").write_bytes(b"x") # 対象外拡張子 + + result = select_template_file(tmp_path) + + assert result == tmp_path / "a_template.png" + + +def test_select_template_file_no_candidates_raises(tmp_path): + (tmp_path / "note.txt").write_bytes(b"x") + + try: + select_template_file(tmp_path) + assert False, "FileNotFoundErrorが送出されるべき" + except FileNotFoundError: + pass + + +def test_check_dependencies_detects_missing_module(): + result = check_dependencies(("this_module_does_not_exist_xyz",)) + assert result == ["this_module_does_not_exist_xyz"] + + +def test_check_dependencies_detects_installed_module(): + result = check_dependencies(("os",)) + assert result == [] + + +def test_check_external_tools_detects_missing(tmp_path): + tesseract = tmp_path / "tools" / "tesseract" / "tesseract.exe" + poppler = tmp_path / "tools" / "poppler" / "pdftoppm.exe" + + result = check_external_tools(tesseract, poppler) + + assert str(tesseract) in result + assert str(poppler) in result + + +def test_check_external_tools_all_present(tmp_path): + tesseract = tmp_path / "tesseract.exe" + poppler = tmp_path / "pdftoppm.exe" + tesseract.write_bytes(b"x") + poppler.write_bytes(b"x") + + result = check_external_tools(tesseract, poppler) + + assert result == []