single_file_extractor#
- nominal.experimental.extractor.decorators.single_file_extractor(fn: Callable[[...], None], *, default_timestamp_column: str | None = None, default_timestamp_type: Iso8601 | Epoch | Relative | Custom | Literal['iso_8601', 'epoch_picoseconds', 'epoch_nanoseconds', 'epoch_microseconds', 'epoch_milliseconds', 'epoch_seconds', 'epoch_minutes', 'epoch_hours', 'epoch_days'] | None = None, output_format: FileOutputFormat | None = None) Extractor[SingleFileExtractorContext]#
- nominal.experimental.extractor.decorators.single_file_extractor(*, default_timestamp_column: str | None = None, default_timestamp_type: Iso8601 | Epoch | Relative | Custom | Literal['iso_8601', 'epoch_picoseconds', 'epoch_nanoseconds', 'epoch_microseconds', 'epoch_milliseconds', 'epoch_seconds', 'epoch_minutes', 'epoch_hours', 'epoch_days'] | None = None, output_format: FileOutputFormat | None = None) Callable[[Callable[[...], None]], Extractor[SingleFileExtractorContext]]
Declare a single-file extractor with
ctxfollowed by injected arguments.Use
@error(ExceptionType, code="...", exit_code=64)below this decorator to declare structured failures handled automatically byExtractor.run(). Declare inputs and parameters below this decorator with@inputand@parameter; they are passed as keyword arguments afterctx. Declaredefault_timestamp_columnanddefault_timestamp_typeto generateExtractor.registration_kwargs().For images registered with a single-file output format (
PARQUET,CSV, …): the ingest pipeline ingests exactly one output file, parsed per the registered format. Declare it withSingleFileExtractorContext.set_output(). If the image’s registered format turns out to beMANIFEST,Extractor.run()fails at startup with a clear error.Set
output_formatexplicitly to generate registration metadata; it must then match the registered format exactly. Omitting it preserves legacy runtime behavior.This is the original output contract, kept for images already registered against it. New extractors should use
manifest_extractor(), a strict superset: this mode has no per-output timestamp, tag-column, or channel-prefix control, and changing an image’s output format later requires registering a new image.Example
from pathlib import Path from nominal.core.container_image import FileOutputFormat from nominal.experimental.extractor import SingleFileExtractorContext, input, single_file_extractor @single_file_extractor( output_format=FileOutputFormat.PARQUET, default_timestamp_column="time_us", default_timestamp_type="epoch_microseconds", ) @input("source") def convert(ctx: SingleFileExtractorContext, *, source: Path) -> None: table = read_input(source) out = ctx.output_dir / "converted.parquet" write_parquet(table, out) ctx.set_output(out) if __name__ == "__main__": convert.run()