diff --git a/src/pptx/oxml/__init__.py b/src/pptx/oxml/__init__.py index 21afaa921..c70fe7b21 100644 --- a/src/pptx/oxml/__init__.py +++ b/src/pptx/oxml/__init__.py @@ -273,6 +273,8 @@ def register_element_cls(nsptagname: str, cls: Type[BaseOxmlElement]): from pptx.oxml.presentation import ( # noqa: E402 + CT_NotesMasterIdList, + CT_NotesMasterIdListEntry, CT_Presentation, CT_SlideId, CT_SlideIdList, @@ -281,6 +283,8 @@ def register_element_cls(nsptagname: str, cls: Type[BaseOxmlElement]): CT_SlideSize, ) +register_element_cls("p:notesMasterId", CT_NotesMasterIdListEntry) +register_element_cls("p:notesMasterIdLst", CT_NotesMasterIdList) register_element_cls("p:presentation", CT_Presentation) register_element_cls("p:sldId", CT_SlideId) register_element_cls("p:sldIdLst", CT_SlideIdList) diff --git a/src/pptx/oxml/presentation.py b/src/pptx/oxml/presentation.py index 17997c2b1..ddd111dd4 100644 --- a/src/pptx/oxml/presentation.py +++ b/src/pptx/oxml/presentation.py @@ -17,6 +17,7 @@ class CT_Presentation(BaseOxmlElement): get_or_add_sldSz: Callable[[], CT_SlideSize] get_or_add_sldIdLst: Callable[[], CT_SlideIdList] get_or_add_sldMasterIdLst: Callable[[], CT_SlideMasterIdList] + get_or_add_notesMasterIdLst: Callable[[], CT_NotesMasterIdList] sldMasterIdLst: CT_SlideMasterIdList | None = ( ZeroOrOne( # pyright: ignore[reportAssignmentType] @@ -30,6 +31,17 @@ class CT_Presentation(BaseOxmlElement): ), ) ) + notesMasterIdLst: CT_NotesMasterIdList | None = ( + ZeroOrOne( # pyright: ignore[reportAssignmentType] + "p:notesMasterIdLst", + successors=( + "p:handoutMasterIdLst", + "p:sldIdLst", + "p:sldSz", + "p:notesSz", + ), + ) + ) sldIdLst: CT_SlideIdList | None = ZeroOrOne( # pyright: ignore[reportAssignmentType] "p:sldIdLst", successors=("p:sldSz", "p:notesSz") ) @@ -115,6 +127,30 @@ class CT_SlideMasterIdListEntry(BaseOxmlElement): rId: str = RequiredAttribute("r:id", XsdString) # pyright: ignore[reportAssignmentType] +class CT_NotesMasterIdList(BaseOxmlElement): + """`p:notesMasterIdLst` element. + + Child of `p:presentation` containing a reference to the notes master that belongs to the + presentation. + """ + + _add_notesMasterId: Callable[..., CT_NotesMasterIdListEntry] + notesMasterId = ZeroOrOne("p:notesMasterId") + + def add_notesMasterId(self, rId: str) -> CT_NotesMasterIdListEntry: + """Create and return a new `p:notesMasterId` child element with r:id set to `rId`.""" + return self._add_notesMasterId(rId=rId) + + +class CT_NotesMasterIdListEntry(BaseOxmlElement): + """`p:notesMasterId` element. + + Child of `p:notesMasterIdLst` containing an `rId` reference to the notes master part. + """ + + rId: str = RequiredAttribute("r:id", XsdString) # pyright: ignore[reportAssignmentType] + + class CT_SlideSize(BaseOxmlElement): """`p:sldSz` element. diff --git a/src/pptx/parts/presentation.py b/src/pptx/parts/presentation.py index 1413de457..59e8ba848 100644 --- a/src/pptx/parts/presentation.py +++ b/src/pptx/parts/presentation.py @@ -72,7 +72,8 @@ def notes_master_part(self) -> NotesMasterPart: return self.part_related_by(RT.NOTES_MASTER) except KeyError: notes_master_part = NotesMasterPart.create_default(self.package) - self.relate_to(notes_master_part, RT.NOTES_MASTER) + rId = self.relate_to(notes_master_part, RT.NOTES_MASTER) + self._element.get_or_add_notesMasterIdLst().add_notesMasterId(rId) return notes_master_part @lazyproperty diff --git a/tests/parts/test_presentation.py b/tests/parts/test_presentation.py index edde4c44c..a28b373a7 100644 --- a/tests/parts/test_presentation.py +++ b/tests/parts/test_presentation.py @@ -65,13 +65,21 @@ def but_it_adds_a_notes_master_part_when_needed( NotesMasterPart_ = class_mock(request, "pptx.parts.presentation.NotesMasterPart") NotesMasterPart_.create_default.return_value = notes_master_part_ part_related_by_.side_effect = KeyError - prs_part = PresentationPart(None, None, package_, None) + relate_to_.return_value = "rId42" + prs_elm = element("p:presentation/p:sldMasterIdLst") + prs_part = PresentationPart(None, None, package_, prs_elm) notes_master_part = prs_part.notes_master_part NotesMasterPart_.create_default.assert_called_once_with(package_) relate_to_.assert_called_once_with(prs_part, notes_master_part_, RT.NOTES_MASTER) assert notes_master_part is notes_master_part_ + # --- notesMasterIdLst element was added to presentation.xml --- + notesMasterIdLst = prs_elm.notesMasterIdLst + assert notesMasterIdLst is not None + notesMasterId = notesMasterIdLst.notesMasterId + assert notesMasterId is not None + assert notesMasterId.rId == "rId42" def it_provides_access_to_its_notes_master(self, request, notes_master_part_): notes_master_ = instance_mock(request, NotesMaster)