Skip to content

Custom parsers

Use this when the built-in formats, --format-option, and --field options are not enough. Users still run the same CLI:

jevotron preview data.custom --config jev_config.py
jevotron scan data.custom --config jev_config.py --warnings-only

A parser is a callable accepting a Path and yielding Chunk objects. No inheritance, registration, decorators, or package installation is required for a local adapter. Import existing parsing libraries or wrap a built-in parser.

import csv
from jevotron import Chunk, Config


def parse(path):
    with path.open(encoding="utf-8", newline="") as stream:
        for index, row in enumerate(csv.DictReader(stream), 1):
            yield Chunk(
                id=row["ident"],
                data=row,
                fields=["/name", "/iso_country"],
                source=f"{path}:row:{index}",
            )


config = Config(parser=parse)
Chunk property Contract
id Nonempty string, unique within a scan; used in reports.
data JSON-compatible object, array, or scalar; the entry shown to Jev. Object keys must be strings.
fields Optional list of JSON Pointers to score. Defaults to top-level object keys, or the root for other values.
source Optional string locating the original entry; carried into reports.

Field paths use JSON Pointer syntax: /name, /terms/0/start, /synonym/1. Escape a literal / in a key as ~1 and a literal ~ as ~0. The empty path selects the whole entry. Missing paths, duplicate selected paths, and empty field selections are errors. Filter an entry out in your parser to skip it.

Reuse a built-in parser

Format-specific settings are ordinary constructor arguments. For example, --format-option 'delimiter=;' corresponds to CSV(delimiter=";"):

from jevotron import Config
from jevotron.parsers import CSV

config = Config(parser=CSV(delimiter=";", id_column="sku", fields=["/price"]))

Other adapters are JSON, JSONL, YAML, TOML, Text, OBO, FASTA, and GMT. All accept encoding; JSON/YAML/TOML accept records, Text accepts split, and OBO accepts stanza. CSV/JSON/JSONL/YAML/TOML also accept id_column and fields. The format reference documents their behavior.

For automatic detection inside a wrapper, call for_path(path, format=None, options=None) from jevotron.parsers. It returns a callable. options is a dictionary of strings using the same keys as --format-option:

from jevotron import Config
from jevotron.parsers import for_path


def parse(path):
    parser = for_path(path, options={"records": "/products"})
    for chunk in parser(path):
        if chunk.data.get("active", True):
            yield chunk


config = Config(parser=parse)

The parser in a config controls parsing completely; set its options there. The CLI rejects --format and --format-option alongside a custom parser. --field and --id-column still override fields and IDs on its yielded chunks. Built-in adapters apply an ID override before validating the configured ID column. Custom parser code must successfully yield a chunk before its ID can be replaced. ID columns must contain nonempty scalar values; lists, mappings, and nulls are rejected consistently in Python parser settings and CLI options. This keeps local Python adapters simple: no registration or plugin interface is needed, and existing ETL libraries can be used directly.

OBO is a lightweight tokenizer: it preserves repeated tags, value text, comments, and escapes, and joins continued lines. It ignores the file header and does not resolve identifiers, interpret axioms, or traverse the graph. Supply relevant general information through guidance. The units config demonstrates wrapping OBO to score only definitions and synonyms while keeping the whole stanza visible.