Skip to content

Adding a Parser

This guide explains how to add support for a new input format by implementing and registering a parser.

Overview

Parsers convert a file at a given path into a normalized pandas.DataFrame that downstream logic can use. Parsers advertise one or more file extensions and can optionally perform content-based detection when the extension is ambiguous.

Contract

  • parse(path: Path) -> pd.DataFrame: read and normalize the file.
  • extensions: tuple[str, ...]: handled file extensions (lowercase, with dot).
  • Optional detect(path: Path) -> bool: return True if this parser should handle the file despite an ambiguous extension.

Parsers should raise ParserError on unrecoverable input problems. Keep errors isolated to the currently processed file.

Minimal example

from pathlib import Path

import pandas as pd

from batteryproc.parsers import ParserError, BaseParser, ParserRegistry


@ParserRegistry.register_parser
class MyCsvParser(BaseParser):
    extensions = (".csv",)

    def parse(self, path: Path) -> pd.DataFrame:
        try:
            df = pd.read_csv(path)
        except Exception as exc:  # I/O or decode errors
            raise ParserError(f"Failed to read CSV: {path}") from exc

        # Normalize columns (example only; real projects may use a mapping helper)
        rename_map = {
            "volt": "Voltage (V)",
            "current": "Current (A)",
            "time_s": "Time (s)",
        }
        df = df.rename(columns={k: v for k, v in rename_map.items() if k in df.columns})

        # Minimal sanity checks (example):
        required = {"Voltage (V)", "Current (A)"}
        missing = required - set(df.columns)
        if missing:
            raise ParserError(f"Missing required columns: {sorted(missing)} in {path}")

        return df

    # Optional: content-based detection for ambiguous extensions
    def detect(self, path: Path) -> bool:
        return path.suffix.lower() in self.extensions

Registration and discovery

  • The @ParserRegistry.register_parser decorator registers the class at import time.
  • The CLI dispatches files by extension using the registry. When running on directories, files are discovered deterministically, parsed independently, and failures are summarized at the end of the run.

Checklist

  • Add unit tests for the new parser (happy path + edge cases).
  • Verify registration via ParserRegistry.supported_extensions() in an interactive session.
  • Ensure errors raise ParserError with actionable messages.
  • Update documentation as needed (User Guide and Input File Requirements).

See Also