1"""The 2.0 parse pipeline: pure stages folded over ParseState.
2
3Stage names and ParseState are NOT public API. The stage list is data;
4runners other than the plain fold (explain(), parse_all()) arrive in
52.x minors without changing any stage signature.
6
7Layering: imports only nameparser._pipeline.* (enforced by
8tests/v2/test_layering.py).
9"""
10from __future__ import annotations
11
12from collections.abc import Callable
13
14from nameparser._pipeline._assign import assign
15from nameparser._pipeline._classify import classify
16from nameparser._pipeline._extract import extract_delimited
17from nameparser._pipeline._group import group
18from nameparser._pipeline._post_rules import post_rules
19from nameparser._pipeline._script_segment import script_segment
20from nameparser._pipeline._segment import segment
21from nameparser._pipeline._state import ParseState
22from nameparser._pipeline._tokenize import tokenize
23
24#: The full eight-stage fold.
25STAGES: tuple[Callable[[ParseState], ParseState], ...] = (
26 extract_delimited, tokenize, segment, script_segment, classify,
27 group, assign, post_rules,
28)
29
30
31def run(state: ParseState) -> ParseState:
32 """Fold the stages over the initial state. Pure: each stage returns
33 a new ParseState; parse is total over str input, so no stage may
34 raise on the *content* of a name (malformed policy/config is a
35 separate, allowed failure mode)."""
36 for stage in STAGES:
37 state = stage(state)
38 return state