Skip to content

fix: add notesMasterIdLst element when creating notes master - #1128

Open
robbybrodie wants to merge 1 commit into
scanny:developfrom
robbybrodie:fix/add-notes-master-id-lst
Open

fix: add notesMasterIdLst element when creating notes master#1128
robbybrodie wants to merge 1 commit into
scanny:developfrom
robbybrodie:fix/add-notes-master-id-lst

Conversation

@robbybrodie

@robbybrodie robbybrodie commented Apr 24, 2026

Copy link
Copy Markdown

Summary

When python-pptx creates a notes master on first access to slide.notes_slide, it correctly creates the NotesMasterPart and adds the relationship in the .rels file, but omits the corresponding <p:notesMasterIdLst> reference from presentation.xml. Without this element, OOXML consumers cannot discover the notes master from the presentation element, even though the relationship and part exist in the package.

This causes Apple Keynote (and potentially other OOXML consumers) to fail to recognize the notes master, breaking speaker notes when opening python-pptx-generated files.

What this PR does

  • Adds CT_NotesMasterIdList and CT_NotesMasterIdListEntry element classes with proper ZeroOrOne/RequiredAttribute declarations
  • Registers both element classes in the oxml element class lookup
  • Adds a ZeroOrOne declaration for notesMasterIdLst on CT_Presentation with the correct successor sequence per the OOXML spec
  • Updates PresentationPart.notes_master_part to populate the notesMasterIdLst element with the relationship ID after creating the notes master relationship
  • Updates the existing unit test to verify the new element is created correctly

Before (missing element)

<p:presentation>
  <p:sldMasterIdLst>...</p:sldMasterIdLst>
  <!-- notesMasterIdLst is absent even though notesMaster.xml exists in the package -->
  <p:sldIdLst>...</p:sldIdLst>
</p:presentation>

After (element present)

<p:presentation>
  <p:sldMasterIdLst>...</p:sldMasterIdLst>
  <p:notesMasterIdLst>
    <p:notesMasterId r:id="rId8"/>
  </p:notesMasterIdLst>
  <p:sldIdLst>...</p:sldIdLst>
</p:presentation>

Test results

Unit tests (pytest): 2700 passed, 0 failed

Acceptance tests (behave): 54 features, 973 scenarios, 2914 steps — all passed

The existing acceptance test in prs-presentation-props.feature (Presentation.notes_master with no notes master) already exercises the code path this fix modifies — creating a notes master when none exists. No new acceptance test was needed.

Manual verification:

  • Generated PPTX contains the notesMasterIdLst element in presentation.xml
  • Generated PPTX with speaker notes opens correctly in Apple Keynote with notes intact

Closes #1051

When python-pptx creates a notes master on first access to
slide.notes_slide, it correctly creates the NotesMasterPart and
adds the relationship in the .rels file, but omits the corresponding
<p:notesMasterIdLst> reference from presentation.xml. Without this
element, OOXML consumers cannot discover the notes master from the
presentation element, even though the relationship and part exist.

This causes Apple Keynote (and potentially other consumers) to
fail to recognize the notes master, breaking speaker notes import.

This fix:
- Adds CT_NotesMasterIdList and CT_NotesMasterIdListEntry element
  classes with proper ZeroOrOne/RequiredAttribute declarations
- Registers both element classes in the oxml element class lookup
- Adds a ZeroOrOne declaration for notesMasterIdLst on
  CT_Presentation with correct successor sequence
- Updates PresentationPart.notes_master_part to populate the
  notesMasterIdLst element with the relationship ID after creating
  the notes master relationship

Closes scanny#1051
@robbybrodie
robbybrodie force-pushed the fix/add-notes-master-id-lst branch from 2e83480 to c14854d Compare April 24, 2026 22:23
@robbybrodie
robbybrodie changed the base branch from master to develop April 24, 2026 22:38
lofcz added a commit to lofcz/python-pptx2 that referenced this pull request Aug 30, 2026
Creating a notes master (prs.notes_master on a deck without one, e.g.
the default template) related the new notesMaster part but never
recorded it in presentation.xml: no p:notesMasterIdLst element, no
p:notesMasterId r:id entry. presentation.xml therefore referenced no
notes master by id, which can make PowerPoint flag the saved file for
repair.

Add CT_NotesMasterIdList / CT_NotesMasterIdListEntry oxml classes and
a ZeroOrOne notesMasterIdLst on CT_Presentation (inserted per the
ECMA-376 CT_Presentation sequence: after sldMasterIdLst, before
handoutMasterIdLst / sldIdLst / sldSz / notesSz), and have
PresentationPart.notes_master_part write the id entry when it creates
and relates the part.

Because p:notesMasterId is maxOccurs=1, add_notesMasterId() creates
the child when absent and updates it in place otherwise, making
registration idempotent. The existing-master path reuses the known
rId from relate_to() and registers too, so decks saved by older
versions (relationship present, id list absent) are reconciled on
access instead of staying repair-flagged.

Port of scanny#1128 by robbybrodie.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Speaker Notes Issue w/ Keynote

1 participant