Commit f0fc1f8
committed
feat(text): _Paragraph.fields field-discovery accessor (Phase 4)
Public Python API for the headers/footers/slide-numbers/dates epic (#20).
Phase 4 ships the small read-side companion to Phase 3's authoring API:
`_Paragraph.fields` returns the paragraph's `<a:fld>` children wrapped as
`_Field` instances in document order. Combined with Phase 3, a user can
now `add_field()` to write, save, re-open, and `paragraph.fields[0]` to
read or mutate.
Why this is small. The heavy lift landed in Phase 3 — `_Field` itself,
the OOXML primitives (Phase 1), and the field-aware `content_children`
+ `_Paragraph.text` (also Phase 3). Phase 4 just exposes the parallel-
to-`runs` discovery accessor that the existing `fld_lst` on
`CT_TextParagraph` made trivial.
Changes:
- pptx.text.text._Paragraph.fields — new `@property`, returns
`tuple[_Field, ...]` built from `self._element.fld_lst`. Mirrors the
shape of `_Paragraph.runs` exactly so the idiom is instantly familiar.
Out of scope for Phase 4 (deliberate):
- Interleaved ordered iterator combining `_Run` / `_Field` /
`_LineBreak` in a single sequence. `content_children` already
exposes this at the oxml layer; surfacing as public API can land
later if real users ask.
- `Slide.has_auto_slide_number` / `has_auto_date` convenience flags —
derive from `.fields` if useful; deferred.
- HandoutMaster class and watermark helper — Phase 5.
Anti-criteria upheld:
- `_Paragraph.runs` continues to yield only `_Run` instances. The new
test `it_keeps_runs_field_free_on_mixed_paragraphs` regression-pins
that on a mixed `(a:r, a:fld, a:r)` paragraph.
- `_Paragraph.text` semantics unchanged (still field-inclusive, as
Phase 3 made it).
- `_Field` class itself is read-only here — no modifications.
Verification (local, CPython 3.14.4):
- python3 -m pytest tests/ -q → 3632 passed in 5.24s (+6 vs Phase 3 baseline)
- python3 -m ruff check src tests → All checks passed!
- python3 -m ruff format --check src tests → 216 files already formatted
- python3 -m behave features/ --no-color → 1048 scenarios, 0 failed
- python3 uat/uat_headers_footers_phase4.py → PASS (opened uat/out_headers_footers_phase3.pptx,
discovered fields[0] with type='slidenum' and id={2ED44585-...}, mutated text to "X" via the
discovered handle, re-saved + re-opened, round-tripped clean)
Refs #20.1 parent 3bd4216 commit f0fc1f8
2 files changed
Lines changed: 58 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
778 | 778 | | |
779 | 779 | | |
780 | 780 | | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
781 | 792 | | |
782 | 793 | | |
783 | 794 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
902 | 902 | | |
903 | 903 | | |
904 | 904 | | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
905 | 952 | | |
906 | 953 | | |
907 | 954 | | |
| |||
0 commit comments