File size: 4,023 Bytes
2d7d24d b7d353c 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d b7d353c 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d 27c92ac 2d7d24d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | """EuropaLex CSV Export β creates a zipped folder containing CSV + media files."""
import csv
import shutil
from pathlib import Path
from typing import Any
from export._constants import _PROJECT_ROOT, get_language_abbrev, sanitize_folder_name
def export_csv_zip(
cards: list[dict[str, Any]],
scenario: str,
cefr_level: str,
target_language: str,
) -> str:
"""Export cards as a zipped folder containing CSV + media files.
Creates a folder under {models_dir}/output/export/ with the following flat structure:
{folder_name}/
cards.csv (CSV with 7 columns, one row per card)
{scenario_slug}_{CEFR}_{LANG}_0.wav (copied from TTS output)
{scenario_slug}_{CEFR}_{LANG}_0.png (copied from image generation)
{folder_name}.zip (zipped archive of the above)
CSV columns: scenario, cefr_level, target_language, english_text, translated_text,
audio_filename, image_filename
Media filenames are bare filenames in the export folder (e.g., 'ordering_coffee_A2_LV_0.wav').
Missing media files are silently skipped β CSV entries remain empty strings.
Args:
cards: List of card dicts with keys: 'text', 'translation',
'audio_path' (str or None), 'image_path' (str or None).
scenario: Free-form scenario/topic string.
cefr_level: CEFR level string (e.g., 'A2', 'B1').
target_language: Target language name (e.g., 'Latvian').
Returns:
Absolute path to the generated .zip file.
Raises:
ValueError: If target_language is not in the supported mapping.
RuntimeError: If zip creation fails.
"""
# Resolve output directory from project root
export_base = _PROJECT_ROOT / ".local" / "models" / "output" / "export"
export_base.mkdir(parents=True, exist_ok=True)
# Build folder name
scenario_slug = sanitize_folder_name(scenario)
lang_abbrev = get_language_abbrev(target_language)
folder_name = f"{scenario_slug}_{cefr_level}_{lang_abbrev}"
export_dir = export_base / folder_name
export_dir.mkdir(parents=True, exist_ok=True)
# Copy media files and build CSV rows (flat folder β no subfolders)
csv_path = export_dir / "cards.csv"
with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL)
# Header row
writer.writerow([
'scenario', 'cefr_level', 'target_language',
'english_text', 'translated_text',
'audio_filename', 'image_filename'
])
for i, card in enumerate(cards):
audio_path = card.get('audio_path')
image_path = card.get('image_path')
# Build the common prefix: {scenario_slug}_{CEFR}_{LANG_ABBREV}
base_name = f"{scenario_slug}_{cefr_level}_{lang_abbrev}"
# Copy audio file if it exists β flat naming
audio_filename = ''
if audio_path and Path(audio_path).exists():
audio_dst = export_dir / f"{base_name}_{i}.wav"
shutil.copy2(audio_path, audio_dst)
audio_filename = f"{base_name}_{i}.wav"
# Copy image file if it exists β flat naming
image_filename = ''
if image_path and Path(image_path).exists():
image_dst = export_dir / f"{base_name}_{i}.png"
shutil.copy2(image_path, image_dst)
image_filename = f"{base_name}_{i}.png"
writer.writerow([
scenario,
cefr_level,
target_language,
card.get('text', ''),
card.get('translation', ''),
audio_filename,
image_filename,
])
# Create zip archive
zip_path = shutil.make_archive(
str(export_base / folder_name),
'zip',
export_dir,
)
return str(zip_path)
|