Spaces:
Running on Zero
Running on Zero
| import json | |
| from pathlib import Path | |
| import pytest | |
| from engine.formats import ( | |
| export_to_docx, | |
| export_to_json, | |
| export_to_txt, | |
| load_source_file, | |
| parse_json, | |
| ) | |
| TIBETAN = "སΰ½ΰ½¦ΰΌΰ½’ΰΎΰΎ±ΰ½¦ΰΌΰ½ΰ½Όΰ½¦ΰΌΰ½ΰ½ΰΌΰ½ΰ½Όΰ½ΰ½¦ΰΌΰ½ΰΎ±ΰ½²ΰΌΰ½ΰ½ΰ½Όΰ½ΰΌΰ½’ΰΎ£ΰ½ΰ½¦ΰΌΰ½£ΰΌ" | |
| # ββ load_source_file ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def test_load_txt(tmp_path): | |
| path = tmp_path / "in.txt" | |
| path.write_text(f"{TIBETAN}\n\nSecond paragraph.", encoding="utf-8") | |
| segments = load_source_file(str(path)) | |
| assert segments == [ | |
| {"source": TIBETAN, "target": ""}, | |
| {"source": "Second paragraph.", "target": ""}, | |
| ] | |
| def test_load_docx(tmp_path): | |
| docx = pytest.importorskip("docx") | |
| path = tmp_path / "in.docx" | |
| doc = docx.Document() | |
| doc.add_paragraph(TIBETAN) | |
| doc.add_paragraph("Second paragraph.") | |
| doc.add_paragraph("") # blank paragraphs should be dropped, not turned into segments | |
| doc.save(str(path)) | |
| segments = load_source_file(str(path)) | |
| assert segments == [ | |
| {"source": TIBETAN, "target": ""}, | |
| {"source": "Second paragraph.", "target": ""}, | |
| ] | |
| def test_load_pdf(tmp_path): | |
| pytest.importorskip("pypdf") | |
| reportlab_canvas = pytest.importorskip("reportlab.pdfgen.canvas") | |
| from reportlab.lib.pagesizes import letter | |
| path = tmp_path / "in.pdf" | |
| c = reportlab_canvas.Canvas(str(path), pagesize=letter) | |
| c.drawString(72, 700, "Hello world.") | |
| c.save() | |
| segments = load_source_file(str(path)) | |
| assert len(segments) == 1 | |
| assert "Hello world." in segments[0]["source"] | |
| assert segments[0]["target"] == "" | |
| def test_load_unsupported_extension_raises(tmp_path): | |
| path = tmp_path / "in.rtf" | |
| path.write_text("whatever", encoding="utf-8") | |
| with pytest.raises(ValueError, match="Unsupported file type"): | |
| load_source_file(str(path)) | |
| def test_load_empty_file_raises(tmp_path): | |
| path = tmp_path / "empty.txt" | |
| path.write_text(" \n\n ", encoding="utf-8") | |
| with pytest.raises(ValueError, match="No text could be extracted"): | |
| load_source_file(str(path)) | |
| def test_load_respects_max_chars(tmp_path): | |
| path = tmp_path / "in.txt" | |
| long_text = ("a" * 50 + "ΰ₯€ ") * 10 | |
| path.write_text(long_text, encoding="utf-8") | |
| segments = load_source_file(str(path), max_chars=100) | |
| assert len(segments) > 1 | |
| assert all(len(s["source"]) <= 110 for s in segments) | |
| # ββ the committed sample files (samples/sample_tibetan.*) βββββββββββββββββ | |
| SAMPLES_DIR = Path(__file__).parent.parent / "samples" | |
| def test_sample_files_load_successfully(ext): | |
| path = SAMPLES_DIR / f"sample_tibetan.{ext}" | |
| segments = load_source_file(str(path)) | |
| assert len(segments) > 0 | |
| assert all(seg["target"] == "" for seg in segments) | |
| combined = "".join(seg["source"] for seg in segments) | |
| assert "སΰ½ΰ½¦ΰΌΰ½’ΰΎΰΎ±ΰ½¦" in combined # "Buddha" appears in the refuge verse | |
| # ββ parse_json βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def test_parse_json_valid_list(): | |
| content = json.dumps([{"source": "src1", "target": "tgt1"}, {"source": "src2"}]) | |
| segments = parse_json(content) | |
| assert segments == [ | |
| {"source": "src1", "target": "tgt1"}, | |
| {"source": "src2", "target": ""}, | |
| ] | |
| def test_parse_json_accepts_bytes(): | |
| content = json.dumps([{"source": "src1", "target": "tgt1"}]).encode("utf-8") | |
| segments = parse_json(content) | |
| assert segments == [{"source": "src1", "target": "tgt1"}] | |
| def test_parse_json_rejects_non_list(): | |
| with pytest.raises(ValueError, match="non-empty list"): | |
| parse_json(json.dumps({"source": "a"})) | |
| def test_parse_json_rejects_empty_list(): | |
| with pytest.raises(ValueError, match="non-empty list"): | |
| parse_json(json.dumps([])) | |
| def test_parse_json_rejects_missing_source(): | |
| with pytest.raises(ValueError, match="Item 0 is missing 'source'"): | |
| parse_json(json.dumps([{"target": "only a target"}])) | |
| def test_parse_json_rejects_non_dict_item(): | |
| with pytest.raises(ValueError, match="Item 1 is missing 'source'"): | |
| parse_json(json.dumps([{"source": "ok"}, "not a dict"])) | |
| # ββ export_to_txt / export_to_docx / export_to_json βββββββββββββββββββββββ | |
| def test_export_to_txt_joins_nonempty_targets(): | |
| segments = [{"source": "s1", "target": "t1"}, {"source": "s2", "target": ""}, {"source": "s3", "target": "t3"}] | |
| assert export_to_txt(segments, "target") == "t1\n\nt3\n" | |
| def test_export_to_txt_all_empty_returns_empty_string(): | |
| segments = [{"source": "s1", "target": ""}, {"source": "s2", "target": " "}] | |
| assert export_to_txt(segments, "target") == "" | |
| def test_export_to_txt_source_field(): | |
| segments = [{"source": "s1", "target": "t1"}, {"source": "s2", "target": "t2"}] | |
| assert export_to_txt(segments, "source") == "s1\n\ns2\n" | |
| def test_export_to_docx_roundtrips_through_load(tmp_path): | |
| docx = pytest.importorskip("docx") | |
| segments = [{"source": "s1", "target": "First translation."}, {"source": "s2", "target": "Second translation."}] | |
| data = export_to_docx(segments, "target") | |
| assert isinstance(data, bytes) and len(data) > 0 | |
| out_path = tmp_path / "out.docx" | |
| out_path.write_bytes(data) | |
| doc = docx.Document(str(out_path)) | |
| texts = [p.text for p in doc.paragraphs if p.text.strip()] | |
| assert texts == ["First translation.", "Second translation."] | |
| def test_export_to_docx_skips_empty_targets(): | |
| segments = [{"source": "s1", "target": ""}, {"source": "s2", "target": "kept"}] | |
| data = export_to_docx(segments, "target") | |
| docx = pytest.importorskip("docx") | |
| import io | |
| doc = docx.Document(io.BytesIO(data)) | |
| texts = [p.text for p in doc.paragraphs if p.text.strip()] | |
| assert texts == ["kept"] | |
| def test_export_to_json_roundtrip(): | |
| segments = [{"source": "s1", "target": "t1"}, {"source": "s2", "target": ""}] | |
| text = export_to_json(segments) | |
| assert json.loads(text) == segments | |
| def test_export_to_json_preserves_unicode_without_escaping(): | |
| segments = [{"source": TIBETAN, "target": ""}] | |
| text = export_to_json(segments) | |
| assert TIBETAN in text # ensure_ascii=False | |