mirror of
https://github.com/Sea-Haven-Industries/procurement-ingest.git
synced 2026-10-07 16:08:54 +00:00
Cover the deterministic parser with golden-file tests over 55 real scrubbed .eml fixtures (both comment sub-shapes, username Submitted-By, address present/absent, br+CRLF assign addresses), fail-closed validation-gate rules, adversarial and prompt-injection cases that must route to ai_fallback or parse without corrupting other fields, the issue #23 comment_id idempotency invariants, and the Bedrock-fallback dispatch plus EMF-metric emission with a mocked invoke_model. Extend pytest.ini testpaths to discover the co-located suite, and update tests/conftest.load_handler to put a handler's own directory on sys.path so the WO handler's new `from template_parser import ...` resolves under the existing shared handler tests. Point test_local.py at the new template-first + Bedrock flow. Refs: #23
54 lines
1.7 KiB
Python
54 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Local test script - parses sample WO emails through the deterministic template
|
|
parser, falling back to Claude on Bedrock for anything the templates don't cover.
|
|
|
|
Usage:
|
|
# AWS credentials with bedrock:InvokeModel are only needed if a sample falls
|
|
# back to the AI extractor; pure-template samples parse fully offline.
|
|
python test_local.py
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent / "lambdas" / "wo" / "email_processor"))
|
|
|
|
from handler import parse_raw_email, extract_with_bedrock
|
|
from template_parser import try_deterministic_parse
|
|
|
|
|
|
def main():
|
|
samples_dir = Path(__file__).parent / "samples"
|
|
eml_files = list(samples_dir.glob("*.eml"))
|
|
|
|
if not eml_files:
|
|
print("No .eml files found in samples/")
|
|
return
|
|
|
|
for eml_path in eml_files:
|
|
print(f"\n{'=' * 80}")
|
|
print(f"FILE: {eml_path.name}")
|
|
print(f"{'=' * 80}")
|
|
|
|
raw = eml_path.read_bytes()
|
|
email_data = parse_raw_email(raw)
|
|
|
|
print(f"Subject: {email_data['subject']}")
|
|
print(f"From: {email_data['sender']}")
|
|
print(f"Date: {email_data['date']}")
|
|
print(f"Body preview: {email_data['body'][:200]}...")
|
|
print()
|
|
|
|
parsed, method, template_id, reason = try_deterministic_parse(email_data)
|
|
if parsed is None:
|
|
print(f"Template miss ({template_id}/{reason}); sending to Bedrock...")
|
|
parsed = extract_with_bedrock(email_data)
|
|
method = "ai_fallback"
|
|
print(f"Parse method: {method} (template={template_id}, reason={reason})")
|
|
print(json.dumps(parsed, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|