Source code for flat_file_renderers.base

import logging
from abc import abstractmethod
from datetime import datetime
from io import BytesIO
from pathlib import Path
from tempfile import NamedTemporaryFile
from zipfile import ZIP_DEFLATED, ZipFile

logger = logging.getLogger(__name__)


[docs] class ZipFileEntry: def __init__(self, zipfilealias: str, osfilepath: Path): self.zipfilealias = zipfilealias self.osfilepath = osfilepath
[docs] class BaseRenderer: """ Base class for dataset renderers. Defines the interface and basic structure for concrete renderers (CSV, Excel, Parquet, etc). Subclasses must implement the abstract `render` method to provide the file-generation logic. Attributes: context (dict): Context dict used to render the file. May hold input data, a validated form, the requesting user, etc. Example: class CsvRenderer(BaseRenderer): def render(self, *args, **kwargs) -> BytesIO: ... renderer = CsvRenderer({'columns': ["Name", "Age"], 'rows': [{"Name": "Alice", "Age": "30"}]}) csv_file = renderer.render() with open("data.csv", "wb") as f: f.write(csv_file.getvalue()) """ def __init__(self, context: dict[str, any]): """ Initializes the base renderer with the given context. Args: context (dict): Context dict holding whatever the renderer needs to produce the file. """ self.context = context @property def default_filename(self) -> str: """ Builds a default filename from the current date/time and the renderer's extension. Returns: str: Suggested filename. """ return f"dataset_{datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}.{self.extension}"
[docs] def write_zipfile(self, entries: list["ZipFileEntry"]) -> Path: """ Compresses one or more files into a temporary ZIP file. Args: entries (list[ZipFileEntry]): Entries to compress. Returns: Path: Path to the generated ZIP file. Examples: ```python zip_path = renderer.write_zipfile([ZipFileEntry("data.csv", Path("/path/to/data.csv"))]) with open(zip_path, "rb") as f: zip_content = f.read() from zipfile import ZipFile with ZipFile(zip_path, 'r') as zipf: print(zipf.namelist()) # ['data.csv'] ``` """ with NamedTemporaryFile(delete=False, suffix=".zip") as zipfilehandler: logger.info( "Creating temporary zip file to compress: %s", [entry.zipfilealias for entry in entries], ) with ZipFile(zipfilehandler, mode="w", compression=ZIP_DEFLATED) as archive: for entry in entries: logger.info("Adding file %s to zip as %s", entry.osfilepath, entry.zipfilealias) archive.write(entry.osfilepath, arcname=entry.zipfilealias) logger.info("Zip file created successfully: %s", zipfilehandler.name) return Path(zipfilehandler.name)
@property def extension(self) -> str: """ Returns the default file extension produced by this renderer. Returns: str: File extension (e.g. 'csv', 'xlsx'). """ return getattr(self, "_extension", "dat")
[docs] @abstractmethod def render(self, *args, **kwargs) -> BytesIO: """ Abstract method that renders the data and produces the file. Subclasses must implement this to provide the format-specific generation logic. Returns: BytesIO: In-memory generated file. """ ...