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

OPEN SOURCE

software/src/data/migrations.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/src/data/migrations.py196 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 0de42591fc7acc48c9f23ebb145e7e7d133f0742cb2496207404cd2145c88304
1"""Data migration utilities for upgrading glossary and other data formats."""23from __future__ import annotations45import json6from pathlib import Path7from typing import Any89from src.models.glossary import EnhancedGlossaryTerm, TheologicalDomain101112def infer_domain_from_notes(notes: str | None, english: str) -> TheologicalDomain:13    """Infer theological domain from notes and English translation.1415    Args:16        notes: Notes field from the term.17        english: English translation.1819    Returns:20        Best-guess theological domain.21    """22    if not notes:23        notes = ""2425    notes_lower = notes.lower()26    english_lower = english.lower()2728    # Christology indicators29    christology_terms = [30        "son",31        "christ",32        "messiah",33        "lord",34        "i am",35        "word",36        "logos",37    ]38    if any(term in notes_lower or term in english_lower for term in christology_terms):39        return TheologicalDomain.CHRISTOLOGY4041    # Pneumatology indicators42    pneumatology_terms = ["spirit", "holy spirit", "paraclete", "helper", "advocate"]43    if any(44        term in notes_lower or term in english_lower for term in pneumatology_terms45    ):46        return TheologicalDomain.PNEUMATOLOGY4748    # Soteriology indicators49    soteriology_terms = [50        "grace",51        "salvation",52        "save",53        "redeem",54        "faith",55        "believe",56        "justif",57    ]58    if any(term in notes_lower or term in english_lower for term in soteriology_terms):59        return TheologicalDomain.SOTERIOLOGY6061    # Hamartiology indicators62    hamartiology_terms = ["sin", "transgression", "iniquity", "flesh"]63    if any(64        term in notes_lower or term in english_lower for term in hamartiology_terms65    ):66        return TheologicalDomain.HAMARTIOLOGY6768    # Theology Proper indicators69    theology_proper_terms = ["god", "father", "divine", "glory", "holy"]70    if any(71        term in notes_lower or term in english_lower for term in theology_proper_terms72    ):73        return TheologicalDomain.THEOLOGY_PROPER7475    return TheologicalDomain.GENERAL767778def migrate_glossary_v1_to_v2(data: dict[str, Any]) -> dict[str, Any]:79    """Migrate glossary from v1 format to v2 format with enhanced metadata.8081    Args:82        data: V1 glossary data with 'terms' list.8384    Returns:85        V2 glossary data with enhanced fields and version marker.86    """87    v1_terms = data.get("terms", [])88    v2_terms = []8990    for v1_term in v1_terms:91        # Create enhanced term with inferred domain92        domain = infer_domain_from_notes(93            v1_term.get("notes"), v1_term.get("english", "")94        )9596        v2_term = {97            # Core fields (preserved)98            "original": v1_term["original"],99            "transliteration": v1_term["transliteration"],100            "japanese": v1_term["japanese"],101            "english": v1_term["english"],102            "notes": v1_term.get("notes"),103            # Enhanced fields (defaults)104            "definition": None,105            "semantic_range": [],106            "domain": domain.value,107            "usage_examples": [],108            "frequency": 0,109            "related_terms": [],110            "avoid_translations": [],111        }112        v2_terms.append(v2_term)113114    return {115        "version": "2.0",116        "terms": v2_terms,117    }118119120def migrate_glossary_file(121    input_path: Path, output_path: Path | None = None, backup: bool = True122) -> list[EnhancedGlossaryTerm]:123    """Migrate a glossary JSON file from v1 to v2 format.124125    Args:126        input_path: Path to the v1 glossary file.127        output_path: Path for the output file. If None, overwrites input.128        backup: Whether to create a backup of the original file.129130    Returns:131        List of migrated EnhancedGlossaryTerm objects.132    """133    if output_path is None:134        output_path = input_path135136    # Load existing data137    with input_path.open("r", encoding="utf-8") as f:138        v1_data = json.load(f)139140    # Check if already v2141    if v1_data.get("version") == "2.0":142        terms = v1_data.get("terms", [])143        return [EnhancedGlossaryTerm(**term) for term in terms]144145    # Create backup146    if backup and output_path == input_path:147        backup_path = input_path.with_suffix(".json.v1.bak")148        with backup_path.open("w", encoding="utf-8") as f:149            json.dump(v1_data, f, ensure_ascii=False, indent=2)150151    # Migrate152    v2_data = migrate_glossary_v1_to_v2(v1_data)153154    # Write output155    with output_path.open("w", encoding="utf-8") as f:156        json.dump(v2_data, f, ensure_ascii=False, indent=2)157158    return [EnhancedGlossaryTerm(**term) for term in v2_data["terms"]]159160161def load_glossary_any_version(path: Path) -> list[EnhancedGlossaryTerm]:162    """Load glossary from any version, converting to EnhancedGlossaryTerm.163164    Args:165        path: Path to the glossary JSON file.166167    Returns:168        List of EnhancedGlossaryTerm objects.169    """170    if not path.exists():171        return []172173    with path.open("r", encoding="utf-8") as f:174        data = json.load(f)175176    # Check version177    version = data.get("version", "1.0")178    terms = data.get("terms", [])179180    if version == "2.0":181        # Already v2, load directly182        return [EnhancedGlossaryTerm(**term) for term in terms]183184    # V1 format - convert on load. Preserve any enhanced fields (e.g.185    # inflected_forms) that may already be present in the entries.186    converted_terms = []187    for v1_term in terms:188        term_data = dict(v1_term)189        if not term_data.get("domain"):190            term_data["domain"] = infer_domain_from_notes(191                v1_term.get("notes"), v1_term.get("english", "")192            )193        converted_terms.append(EnhancedGlossaryTerm(**term_data))194195    return converted_terms196