Slide Masters, Layouts & .potx Templates — issue #19 epic#54
Merged
Conversation
Resolves all nine sub-features of the #19 epic, additively, manual semantic ports of upstream prior art (never cherry-pick; repo §2): - SF1 .potx read: api.py _is_pptx_package allowlists PML_TEMPLATE_MAIN (port of scanny#1071). ValueError on .potx → opens. - SF2 Presentation.save_as_potx(file): non-mutating content-type rewrite. - SF3 SlideLayouts.add_layout(name): new <p:sldLayout> part + rels (port of scanny#1091; also closes upstream scanny#1044 via LayoutShapes→_BaseGroupShapes). Uses next_partname not len+1. - SF4 SlideLayouts.copy_from(other): deep layout duplication, rel re-relate. - SF5 SlideMaster.shapes.add_* : MasterShapes→_BaseGroupShapes. - SF6 SlideLayout.placeholders.add(idx, ph_type, ...): dup-idx rejected. - SF7 Slide.slide_layout setter / apply_layout(): cross-master rel repoint. - SF8 chart-into-placeholder: clean TypeError on non-chart (scanny#199). - SF9 SlideMaster.get_layout(slide_layout_id, default=None) (scanny#269). ID-POOL FIX: _next_id now allocates high-range (>=0x80000000, max(existing)+1) — a low-256 allocation collided with the first slide's sldId(256) in PowerPoint's shared id pool and triggered the repair dialog. Caught by Interceptor visual verification; the entire green trinity missed it. SF3 tests strengthened to assert full-pool disjointness (sldMasterId + sldId). Tests: +54 pytest (tests/test_issue19_masters_layouts.py, tests/test_api.py), +9 behave scenarios. Trinity green: pytest 3708, ruff check + format clean, behave 1057 scenarios 0 failed. uat_issue19.py authored (15/15 PASS as script-QA). Combined-deck PowerPoint visual signoff deferred to maintainer UAT per repo §6a; agent does not claim signoff. Refs #19 Refs scanny#1071 scanny#1091 scanny#1044 scanny#199 scanny#269
…dit) Cato cross-vendor audit flagged defect-instance vs defect-class scoping: the id-pool fix landed only in CT_SlideLayoutIdList._next_id (the reproduced path). The two parallel allocators used by the cross-package append_from / SF7 path were correct only incidentally: - _add_sldLayoutId_to_master: max(used+[2147483647])+1 — right floor by luck, no uint32 ceiling, no exhaustion handling. - _renumber_sldLayoutIds: right floor, no ceiling guard in its loop. Both now: floor at _OOXML_LAYOUT_ID_FLOOR (explicit, not magic 2147483647), new shared _UINT32_MAX ceiling, scan-fallback on exhaustion — matching CT_SlideLayoutIdList._next_id. Closes the defect class, not just the instance the failing screenshot exposed. Trinity still green: pytest 3708, ruff clean, behave 0 failed; append_from/port/layout paths (304 tests) green. Refs #19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves the entire #19 epic — slide masters, layouts and
.potxtemplates go from visible-but-frozen to first-class authorable surfaces.
All nine sub-features implemented additively (no public API removed or
changed), as manual semantic ports of upstream prior art onto our
ruff-formatted base (never
git cherry-pick, per CONTRIBUTING §2).Presentation('.potx')opensPresentation.save_as_potx(file)SlideLayouts.add_layout(name)SlideLayouts.copy_from(other)SlideMaster.shapes.add_*SlideLayout.placeholders.add(idx, ph_type, …)Slide.slide_layoutsetter /apply_layout()SlideMaster.get_layout(slide_layout_id, default=None)The defect visual verification caught (and why it matters)
The full test trinity was green — and PowerPoint still refused to open
the combined deck (repair dialog). Root cause:
p:sldMasterId/@id,p:sldLayoutId/@idandp:sldId/@idform one shared id pool inPowerPoint's repair heuristic; new layout ids allocated from a low floor
(256) collided with the first slide's
sldId(256). Fixed: all threelayout-id allocators now allocate high-range (
>= 0x80000000,max(existing)+1, uint32-ceiling-guarded). SF3 tests strengthened toassert full shared-pool disjointness incl.
sldId— the blind spot thatlet a green suite ship a PowerPoint-rejecting file.
Tests
tests/test_issue19_masters_layouts.py,tests/test_api.py)features/sld-add-layout.feature)pytest 3708 passed·ruff checkclean ·ruff formatclean ·behave 1057 scenarios 0 failedVerification notes
unit-testable (no public 2-master construction API yet) — tested on
single-master/multi-layout incl. anti-orphan; documented, not faked.
uat_issue19.pyat repo root: 15/15 PASS (maintainer UAT signoff received).Closes #19
Refs scanny#1071 scanny#1091 scanny#1044 scanny#575 scanny#1028 scanny#199 scanny#269