Pre-publication review draft
日常訳NICHIJOYAKU日本語 ↗

OPEN SOURCE

software/tests/test_versification.py

Read on this site and download the files you need.

Nichijoyaku was created using AI. A complete review by human biblical-language and biblical-studies specialists has not been established. Read alongside established translations and original-language resources.

← Back to the open-source guide

software/tests/test_versification.py142 linesDownload this file ↓

This is the same source included in the download. Each line number is a link you can save or share.

File verification detailsSHA-256 689332e957502045561f87ae89fef6050346b7fd770a92fc64d320534ce7b767
1"""Regression cases for shifted chapters, partial verses and mixed languages."""2import json3import shutil4from pathlib import Path56import pytest78from src.data.versification import DATA, load_map, spans_for, build_originals9from src.output.originals import group_segments, build101112def words(count, replacement=None):13    result = [{'word': f'w{i}', 'morph': 'HNp'} for i in range(count)]14    if replacement:15        index, text = replacement16        result[index]['word'] = text17    return {'words': result}181920def test_cross_chapter_and_heading_maps():21    mapping = load_map()22    assert mapping['joel', 4, 1] == [(3, 1, 0, None)]23    assert mapping['genesis', 32, 1] == [(31, 55, 0, None)]24    assert mapping['psalms', 3, 1] == [(3, 0, 0, None)]25    assert mapping['psalms', 51, 1] == [(51, 0, 0, None)]26    assert mapping['psalms', 51, 2] == [(51, 0, 0, None)]27    assert mapping['3john', 1, 15] == [(1, 14, 0, None)]28    assert mapping['revelation', 12, 18] == [(12, 17, 0, None)]293031@pytest.mark.parametrize('key,count,boundary,expected', [32    (('1kings',18,34),16,(10,'ויאמר'),[(('1kings',18,33),0,10),(('1kings',18,34),10,16)]),33    (('1kings',20,3),15,(6,'כספך'),[(('1kings',20,2),0,6),(('1kings',20,3),6,15)]),34    (('1kings',22,21),12,(8,'ויאמר'),[(('1kings',22,21),0,8),(('1kings',22,22),8,12)]),35    (('1kings',22,44),9,None,[(('1kings',22,43),0,9)]),36    (('isaiah',63,19),16,(9,'לוא'),[(('isaiah',63,19),0,9),(('isaiah',64,1),9,16)]),37    (('psalms',13,6),11,(6,'אשירה'),[(('psalms',13,5),0,6),(('psalms',13,6),6,11)]),38    (('zechariah',2,15),18,(12,'וידעת'),[(('zechariah',2,11),0,12),(('zechariah',2,12),12,18)]),39])40def test_partial_boundaries(key,count,boundary,expected):41    assert spans_for(*key, words(count,boundary), load_map()) == expected424344def test_acts_closing_sentence_and_source_drift():45    record=words(2)46    record['words'] += [{'word': w} for w in 'καὶ ταῦτα εἰπὼν ἀπέλυσεν τὴν ἐκκλησίαν'.split()]47    assert spans_for('acts',19,40,record,{}) == [(('acts',19,40),0,2),(('acts',19,41),2,8)]48    with pytest.raises(ValueError,match='closing sentence'):49        spans_for('acts',19,40,words(10),{})50    with pytest.raises(ValueError,match='boundary'):51        spans_for('isaiah',63,19,words(16),load_map())525354def test_invalid_spans_fail_closed():55    key=('genesis',1,1)56    for spans in [[(1,1,0,0)],[(1,1,0,8)]]:57        with pytest.raises(ValueError,match='Invalid word span'):58            spans_for(*key,words(3),{key:spans})59    with pytest.raises(ValueError,match='loss or duplication'):60        spans_for(*key,words(3),{key:[(1,1,0,2),(1,2,1,3)]})616263def test_map_changes_rejected(tmp_path):64    original=(DATA/'versification/oshb-VerseMap.xml').read_text()65    p=tmp_path/'map.xml'66    p.write_text(original.replace('type="partial"','type="unsupported"',1))67    with pytest.raises(ValueError,match='Unknown map type'):load_map(p)68    p.write_text(original.replace('type="partial"','type="full"',1))69    with pytest.raises(ValueError,match='Partial verse map changed'):load_map(p)70    line='<verse wlc="Gen.32.1" kjv="Gen.31.55" type="full"/>'71    p.write_text(original.replace(line,line+line))72    with pytest.raises(ValueError,match='Duplicate'):load_map(p)737475def test_language_runs_and_word_conservation(tmp_path):76    (tmp_path/'versification').mkdir()77    shutil.copy(DATA/'versification/oshb-VerseMap.xml',tmp_path/'versification/oshb-VerseMap.xml')78    for language,book,record in [79        ('hebrew','genesis',{'words':[{'word':'א/ב','morph':'HNp'},{'word':'גד','morph':'ANp'},{'word':'הו','morph':'HNp'}]}),80        ('greek','john',{'words':[{'word':'λόγος'},{'word':'θεός'}]}),81    ]:82        path=tmp_path/'sources'/language;path.mkdir(parents=True)83        (path/f'{book}.json').write_text(json.dumps({'1:1':record}))84    result,mapping=build_originals(tmp_path)85    assert sum(map(len,result.values()))==586    assert [w['language'] for w in result['genesis',1,1]]==['he','arc','he']87    assert result['genesis',1,1][0]['text']=='אב'88    assert group_segments(result['john',1,1])==[{'language':'grc','source':'john:1:1','text':'λόγος θεός'}]89    assert len(mapping)==2909192def test_export_never_overwrites_source_data(tmp_path):93    with pytest.raises(ValueError,match='outside translator data'):94        build(tmp_path/'output',data_dir=tmp_path)959697def test_unknown_language_tag_rejected(tmp_path):98    (tmp_path/'versification').mkdir()99    shutil.copy(DATA/'versification/oshb-VerseMap.xml',tmp_path/'versification/oshb-VerseMap.xml')100    (tmp_path/'sources/hebrew').mkdir(parents=True)101    (tmp_path/'sources/hebrew/genesis.json').write_text(json.dumps({'1:1':{'words':[{'word':'אב','morph':'?'}]}}))102    with pytest.raises(ValueError,match='Unknown word language'):build_originals(tmp_path)103104105def test_export_includes_headings_omissions_hashes_and_language_runs(tmp_path,monkeypatch):106    from src.output import originals107    data=tmp_path/'input';(data/'versification').mkdir(parents=True)108    (data/'versification/oshb-VerseMap.xml').write_text('fixture')109    source=data/'sources/hebrew';source.mkdir(parents=True)110    (source/'psalms.json').write_text('{}')111    monkeypatch.setattr(originals,'load_site',lambda _: ({('psalms',3,1):'本文',('psalms',3,2):'本文'}, {'psalms':'ps'}))112    original_words={('psalms',3,0):[{'language':'he','text':'דוד','source':'psalms:3:1','word':0}],('psalms',3,1):[{'language':'he','text':'יהוה','source':'psalms:3:2','word':0}]}113    monkeypatch.setattr(originals,'build_originals',lambda _: (original_words,{('psalms',3,1):[(('psalms',3,0),0,1)],('psalms',3,2):[(('psalms',3,1),0,1)]}))114    out=tmp_path/'out';report=originals.build(out,data)115    payload=json.loads((out/'ps.json').read_text())116    assert payload['chapters']['3']['heading'][0]['text']=='דוד'117    assert payload['chapters']['3']['verses']['2']==[]118    assert report['without_original']==['psalms:3:2']119    assert report['words_by_language']=={'he':2}120    assert report['mapped_source_references']==2121    assert len(report['files']['ps.json'])==64122    original_words[('psalms',3,3)]=[]123    with pytest.raises(ValueError,match='outside site'):originals.build(out,data)124125126def test_site_reference_validation(tmp_path):127    from src.output.originals import load_site,normalize_book128    assert normalize_book('III John')=='3john'129    assert normalize_book('II Corinthians')=='2corinthians'130    assert normalize_book('I Samuel')=='1samuel'131    assert normalize_book('Song of Solomon')=='song_of_solomon'132    refs,codes=load_site()133    assert len(refs)==31101 and len(codes)==66134    (tmp_path/'src/lib').mkdir(parents=True)135    (tmp_path/'public').mkdir()136    (tmp_path/'src/lib/data.ts').write_text("'Genesis': { code: 'gen'")137    csvfile=tmp_path/'public/JapKougo.csv'138    csvfile.write_text('Book,Chapter,Verse,Text\nGenesis,1,1,本文\nGenesis,1,1,本文\n')139    with pytest.raises(ValueError,match='Invalid site reference'):load_site(tmp_path)140    csvfile.write_text('Book,Chapter,Verse,Text\nGenesis,1,1,本文\n')141    with pytest.raises(ValueError,match='complete'):load_site(tmp_path)142