from musicscore.exceptions import (
AlreadyFinalizedError,
ClassHasNoMusicXMLEquivalentError,
)
[docs]class FinalizeMixin:
"""
FinalizeMixin is a mixin for finalizable classes: Score, Part, Measure, Staff, Voice, Beat and Chord
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._finalized = False
[docs] def finalize(self) -> None:
"""
:obj:`~musicscore.finalize.FinalizeMixin` method
finalize can only be called once.
It calls finalize method of all children.
"""
if self._finalized:
raise AlreadyFinalizedError(self)
for child in self.get_children():
if not child._finalized:
child.finalize()
self._finalized = True
[docs] def to_string(self, *args, **kwargs):
"""
:obj:`~musicscore.finalize.FinalizeMixin` method
It triggers :obj:`~finalize()` first before calling parent's ``xml_object.to_string()`` method. If no xml_object exists (it means there is no direct MusicXML equavalent of this class) a
:obj:`~musicscore.exceptions.ClassHasNoMusicXMLEquivalentError` is thrown.
"""
if not self._finalized:
self.finalize()
try:
return super().to_string(*args, **kwargs)
except AttributeError:
raise ClassHasNoMusicXMLEquivalentError(
f"{self.__class__} has no direct equivalent in MusicXML and cannot be converted to string."
)