baml.csv.Reader
A streaming CSV reader. Create one with `baml.csv.open` or `baml.csv.reader`.
Signature
class baml.csv.ReaderA streaming CSV reader. Create one with baml.csv.open or
baml.csv.reader.
A Reader is a lazy iterator over Record values, so a multi-gigabyte
file parses in constant memory and every baml.iter adapter and default
method (map, filter, collect, ...) works on it. There is one cursor:
raw iteration, rows<T>(), and headers() all draw from the same stream.
A thrown record error has already consumed the offending record. The parser
resynchronizes at the next record boundary, so the next call to next()
continues and one corrupt cell costs exactly one record.
on_error governs record-scoped failures for every read on this handle.
Under the default "throw" they propagate. Under "skip" they are
counted, handed to ReaderOptions.on_skip, and stepped over. Options and
Header failures are never record-scoped and throw either way — a header
that cannot serve T will not start serving it on the next row.
Every read throws Error { kind: Closed } after close(); skipped(),
skipped_count(), and position() stay valid. A baml.errors.Io failure
from the source is stream-scoped and final: the reader is marked exhausted
before the throw, so a caller that swallows it gets baml.iter.Done rather
than an infinite retry.
Source:<builtin>/baml/ns_csv/csv.bamlbytes 14905–23246
Fields
_handle
$rust_type_file
baml.fs.File | null_on_skip
((baml.csv.Error) -> null throws never) | null_owns_file
boolInstance methods
_feed
(self, chunk: uint8array) -> null throws never(internal) Append a chunk of source bytes to the parse buffer.
_feed_eof
(self) -> null throws never(internal) Mark the source as exhausted.
_mark_closed
(self) -> null throws never(internal) Mark the reader closed (idempotent).
_mark_exhausted
(self) -> null throws never(internal) Mark the iterator exhausted: subsequent polls return Done.
_poll
((internal) Advance the native parser by one step.
(internal) Resolve headers, or request more input.
(internal) Pull the next chunk from the backing file, or mark EOF for in-memory sources.
The reader is marked exhausted before an IO error is thrown, so
subsequent next() calls return baml.iter.Done. A closed handle
arrives as an IO error, because baml.io.Read has no separate
closed-handle error channel.
Releases the reader. Idempotent.
The underlying file handle is closed only when the reader owns it
(created by open); a handle passed to reader(file) stays open,
since its lifecycle belongs to the caller. Closing is optional, as with
baml.fs.File — the GC reclaims unreferenced readers.
Throws
baml.errors.Ioif closing an owned file handle fails. The reader is already marked closed by then, so a retry will not reopen it.
The column names: the headers option when set, the file's header row
when has_header = true (consumed on first call), and null otherwise.
Idempotent. The header is resolved once and cached, so calling this
before iterating costs nothing and consumes no data record. An empty
input has no header row, and reads as the headers option or null.
A malformed header record surfaces from whichever call reads the header
first, and it exhausts the reader rather than resynchronizing: without
a trustworthy header every later name-to-column mapping would be
silently wrong. on_error does not apply, because there is no next
header to resume at.
Throws
Error { kind: Quote }orError { kind: Encoding }if the header record itself is malformed. Every later call rethrows the same error.baml.errors.Ioif the source cannot be read.
The position of the start of the next unread record. Its record
field counts all data records consumed so far, including skipped ones.
rows
<T>(A typed iterator over the remaining records, decoding each into T.
Validates eagerly. It reads the header if necessary and checks that
every non-optional field of T is satisfiable, so an unusable T
throws Error { kind: Header } at the call site rather than on the
millionth row.
The decode rules are Record.decode<T>'s, under this reader's
on_error policy. "Remaining" is literal: this shares the reader's one
cursor, so records already pulled by next() are gone.
Throws
Error { kind: Header }if a required field ofThas no column, or its column name is duplicated.Error { kind: Options }ifTis not a flat class of cell-decodable fields.- Anything
headers()throws, since it is called first.
The first max_skipped (default 1,000) Error values skipped under
on_error = "skip".
Retention is bounded so a pathological file cannot turn a
constant-memory stream into an unbounded error log. It keeps the first
errors rather than the last, because the first ones usually explain the
rest. Use ReaderOptions.on_skip to observe every skip, and
skipped_count() for the true total.
skipped_count
(self) -> int throws neverExact count of records skipped under on_error = "skip".
Unaffected by max_skipped — the counter is kept even once retention
stops.
Implementations
baml.Concrete for T
Source:<builtin>/baml/core.bamlbytes 763–795
baml.iter.Iterable for baml.csv.Reader
Item = baml.csv.RecordError = baml.csv.Error | baml.errors.IoInstance methods
iter
(Returns self: a Reader is its own iterator, so a reader can be
consumed exactly once. There is only one cursor to hand out, and a
second traversal would resume mid-file rather than restart.
Source:<builtin>/baml/ns_csv/csv.bamlbytes 15045–15575
baml.iter.Iterator for baml.csv.Reader
Item = baml.csv.RecordError = baml.csv.Error | baml.errors.IoInstance methods
chain
<E2>(Returns an iterator over all of self's elements followed by all of
other's.
other.iter() is called right away, when the chain is built; only the
advancing is deferred. The two sides may have different error types, and
the result throws either.
Returns
A baml.iter.Chain.
collect
(self) -> (Self as baml.iter.Iterator).Item[] throws (Self as baml.iter.Iterator).ErrorConsumes the rest of this iterator into an array, in order.
The rest: elements already pulled from a partly-consumed iterator are
not included, and an already-exhausted iterator collects to [].
Throws
Self.Errorif advancing the iterator fails. The elements gathered so far are lost, since the array is only returned on success.
Consumes the rest of this iterator and returns how many elements there
were, 0 if it was already exhausted.
Every element is actually pulled — there is no size hint to short circuit with — so counting a chain runs the whole chain, callbacks included.
Throws
Self.Errorif advancing the iterator fails.
every
<E2>(Whether predicate holds for every remaining element — Python's all,
JavaScript's every.
Short circuits at the first false. An empty iterator gives true — the
empty conjunction — which is worth remembering when the iterator may have
been exhausted already.
Throws
Self.Errorif advancing the iterator fails.E2ifpredicatethrows.
ALIASES: all
filter
<E2>(Returns an iterator over the elements for which predicate is true, in
order.
A rejected element is skipped, not a stopping point — use
baml.iter.Iterator.take_while to stop at the first failure instead.
Returns
A baml.iter.Filter yielding the kept elements.
filter_map
<R, E2>(Returns an iterator over the non-null results of fn: map and filter
in one pass.
null is the skip signal, so the produced item type R is the
non-optional one. An iterator whose own items you want to keep as null
cannot be expressed this way — filter and map it in two steps instead.
Returns
A baml.iter.FilterMap yielding the non-null results, in order.
find
<E2>(The first remaining element for which predicate is true, or null if
the iterator runs out first.
Short circuits: the matching element is consumed, and the iterator is left positioned just after it.
The result is Self.Item?, so — unlike next, which uses the distinct
baml.iter.Done sentinel — an iterator whose items are themselves
nullable cannot tell a found null from no match. Use
baml.iter.Iterator.filter followed by next when that distinction
matters.
Throws
Self.Errorif advancing the iterator fails.E2ifpredicatethrows.
flat_map
<R, E2, E3>(Returns an iterator over the elements of the iterables fn produces, laid
end to end.
Each inner sequence is drained before the next outer element is pulled,
and one that is empty contributes nothing. Three error types meet here —
the source's, fn's E2, and the inner iterables' E3 — and the result
throws all of them.
Returns
A baml.iter.FlatMap yielding R.
for_each
<E2>(Calls fn on each remaining element, in order, for its side effects.
A for (.. in ..) loop is generally preferable; this is for the end of a
long chain of calls. It runs to exhaustion — there is no way for fn to
stop it early. Use baml.iter.Iterator.some or a for loop with a
break when you need to.
Throws
Self.Errorif advancing the iterator fails.E2iffnthrows, which ends the traversal at that element.
map
<R, E2>(Returns an iterator that applies fn to each element — Python's map,
JavaScript's Iterator.prototype.map.
fn is applied exactly once per element that is actually pulled, in
order, so a chain that ends early never touches the elements it skipped.
Returns
A baml.iter.Map yielding R, of the same length as self.
Yields the next raw Record, pumping input from the source as the
parser needs it.
A skipped record is not a result, so the loop runs until one
survives or the stream ends. Under "throw" the error propagates
instead — but the record has already been consumed, so calling
next() again resumes cleanly at the following record.
peekable
(Returns an iterator with one element of look-ahead.
Unlike the other adapters this returns the concrete baml.iter.Peekable
class rather than the Iterator interface, because peek lives on the
class: an existential would hide it.
Returns
A baml.iter.Peekable yielding exactly what self yields, plus a peek
that reads the next element without consuming it.
reduce
<A, E2>(Folds every remaining element into an accumulator, left to right.
The accumulator starts at initial and each call to fn replaces it with
the result; initial is what comes back for an empty iterator. Because
the seed is required and its type A is independent of the item type,
this is the operation Rust calls Iterator::fold and Python calls
functools.reduce — not Rust's reduce.
Parameters
fn: combines the accumulator so far with the next element.initial: the starting accumulator, and the result for an empty iterator.
Throws
Self.Errorif advancing the iterator fails.E2iffnthrows. The fold stops there; the partial accumulator is not recoverable.
ALIASES: fold
skip
(Returns an iterator over everything after the first n elements.
For n <= 0 every element is yielded; a source with fewer than n
elements yields nothing. The skipped elements are pulled from the source
and discarded — they are not free, and they can still throw. A skip is
counted only once the source has actually yielded, so a throw the caller
retries does not consume part of the count.
Parameters
n: how many leading elements to discard.
Returns
A baml.iter.Skip.
Examples
baml.iter.Range.new(0, 5).skip(2).collect() // [2, 3, 4]
skip_while
<E2>(Returns an iterator over everything from the first element predicate
rejects onwards.
That first rejected element is itself yielded — it is the start of the kept run, not a discarded boundary. The predicate is not consulted again afterwards, so later elements it would have matched are still yielded.
Returns
A baml.iter.SkipWhile.
Examples
// stops skipping at 3, so the trailing 1 and 2 are kept
[1, 2, 3, 1, 2].iter().skip_while((x: int) -> bool { x < 3 }).collect() // [3, 1, 2]
some
<E2>(Whether predicate holds for any remaining element — Python's any,
JavaScript's some.
Short circuits at the first true, leaving the iterator positioned just
after the matching element so it can be inspected further. An empty
iterator gives false, the empty disjunction.
Throws
Self.Errorif advancing the iterator fails.E2ifpredicatethrows.
ALIASES: any
step_by
(Returns an iterator over every nth element, starting with the first.
The elements kept are those at positions 0, n, 2n, and so on. The
skipped ones are still pulled from the source — and so may still throw —
they are simply discarded.
Parameters
n: how far to advance between yielded elements. Values below1mean "advance by one", i.e. yield everything.
Returns
A baml.iter.StepBy.
take
(Returns an iterator over at most the first n elements.
Once n elements have been yielded the source is no longer advanced, and
if the source ends first this ends with it. For n <= 0 it yields
nothing. A slot is spent only once the source has actually yielded an
element, so a source that throws and is then retried does not silently
lose one.
This is the usual way to bound an unbounded iterator such as
Repeat.new(v) or a wide Range.
Parameters
n: the greatest number of elements to yield.
Returns
A baml.iter.Take yielding at most n elements.
Examples
baml.iter.Repeat.new(0).take(5).collect() // [0, 0, 0, 0, 0]
baml.iter.Range.new(0, 10).take(3).collect() // [0, 1, 2]
take_while
<E2>(Returns an iterator over the leading run of elements for which
predicate is true.
The element that fails the predicate is consumed from the source and is
not yielded. Unlike filter, iteration stops at the first failure
rather than skipping it, and the stop latches: the source is never
advanced again, however often next is called.
Returns
A baml.iter.TakeWhile.
Examples
// stops at 5, so 6 and 8 are never yielded
[2, 4, 5, 6, 8].iter().take_while((x: int) -> bool { x % 2 == 0 }).collect() // [2, 4]
Source:<builtin>/baml/ns_csv/csv.bamlbytes 15581–16952
Related definitions
baml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.iter.Iteratorbaml.Arraybaml.Boolbaml.Concretebaml.csv._Headersbaml.csv._NeedDatabaml.csv._Skipbaml.csv.Errorbaml.csv.Positionbaml.csv.Recordbaml.errors.Iobaml.fs.Filebaml.Intbaml.io.Readbaml.iter.Chainbaml.iter.Donebaml.iter.Filterbaml.iter.FilterMapbaml.iter.FlatMapbaml.iter.Iterablebaml.iter.Iteratorbaml.iter.Mapbaml.iter.Peekablebaml.iter.Skipbaml.iter.SkipWhilebaml.iter.StepBybaml.iter.Takebaml.iter.TakeWhilebaml.Nullbaml.Uint8Arraybaml.csv.openbaml.csv.reader