From b9861adf9caaf967e129b5c98117a7211f75f6f8 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Sat, 3 Aug 2024 15:31:29 -0400 Subject: [PATCH 1/2] Export stem styles on notes with implicit stem directions --- music21/musicxml/m21ToXml.py | 23 ++++++++++++++++------- music21/musicxml/test_m21ToXml.py | 8 ++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py index aad81005e..839456cc3 100644 --- a/music21/musicxml/m21ToXml.py +++ b/music21/musicxml/m21ToXml.py @@ -4103,17 +4103,26 @@ def noteToXml(self, n: note.GeneralNote, noteIndexInChord=0, chordParent=None): n = t.cast(note.NotRest, n) stemDirection = n.stemDirection - if stemDirection is not None: + if stem_has_style := (chordOrN.hasStyleInformation + and isinstance(chordOrN.style, style.NoteStyle) + and chordOrN.style.stemStyle is not None): + note_style = chordOrN.style + + if stemDirection is not None or stem_has_style: mxStem = SubElement(mxNote, 'stem') - sdText = stemDirection + if stemDirection is None: + if closest_clef := chordOrN.getContextByClass(clef.Clef): + sdText = closest_clef.getStemDirectionForPitches(chordOrN.pitches) + else: + sdText = 'up' + else: + sdText = stemDirection if sdText == 'noStem': sdText = 'none' mxStem.text = sdText - if (chordOrN.hasStyleInformation - and isinstance(chordOrN.style, style.NoteStyle) - and chordOrN.style.stemStyle is not None): - self.setColor(mxStem, chordOrN.style.stemStyle) - self.setPosition(mxStem, chordOrN.style.stemStyle) + if stem_has_style: + self.setColor(mxStem, note_style.stemStyle) + self.setPosition(mxStem, note_style.stemStyle) # end Stem diff --git a/music21/musicxml/test_m21ToXml.py b/music21/musicxml/test_m21ToXml.py index 8d368b061..0dabca2d7 100644 --- a/music21/musicxml/test_m21ToXml.py +++ b/music21/musicxml/test_m21ToXml.py @@ -27,6 +27,7 @@ from music21 import repeat from music21 import spanner from music21 import stream +from music21 import style from music21 import tempo from music21.musicxml import helpers @@ -921,6 +922,13 @@ def test_roman_musicxml_two_kinds(self): self.assertIn('', xmlOut) + def test_stem_style_without_direction(self): + one_note_tune = converter.parse('tinyNotation: 2/4 c2') + half_note = one_note_tune.recurse().notes.first() + half_note.style.stemStyle = style.Style() + half_note.style.stemStyle.color = 'red' + xmlOut = GeneralObjectExporter().parse(one_note_tune).decode('utf-8') + self.assertIn('up', xmlOut) class TestExternal(unittest.TestCase): From 08cd3db84761d1cc840a0f209cd30ea2ccd80b70 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Sat, 3 Aug 2024 16:01:26 -0400 Subject: [PATCH 2/2] fixup! Export fix possibly-used-before-assignment --- music21/musicxml/m21ToXml.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/music21/musicxml/m21ToXml.py b/music21/musicxml/m21ToXml.py index 839456cc3..ea2c7dc04 100644 --- a/music21/musicxml/m21ToXml.py +++ b/music21/musicxml/m21ToXml.py @@ -4103,12 +4103,13 @@ def noteToXml(self, n: note.GeneralNote, noteIndexInChord=0, chordParent=None): n = t.cast(note.NotRest, n) stemDirection = n.stemDirection - if stem_has_style := (chordOrN.hasStyleInformation - and isinstance(chordOrN.style, style.NoteStyle) - and chordOrN.style.stemStyle is not None): - note_style = chordOrN.style + stem_style = None + if (chordOrN.hasStyleInformation + and isinstance(chordOrN.style, style.NoteStyle) + and chordOrN.style.stemStyle is not None): + stem_style = chordOrN.style.stemStyle - if stemDirection is not None or stem_has_style: + if stemDirection is not None or stem_style: mxStem = SubElement(mxNote, 'stem') if stemDirection is None: if closest_clef := chordOrN.getContextByClass(clef.Clef): @@ -4120,9 +4121,9 @@ def noteToXml(self, n: note.GeneralNote, noteIndexInChord=0, chordParent=None): if sdText == 'noStem': sdText = 'none' mxStem.text = sdText - if stem_has_style: - self.setColor(mxStem, note_style.stemStyle) - self.setPosition(mxStem, note_style.stemStyle) + if stem_style: + self.setColor(mxStem, stem_style) + self.setPosition(mxStem, stem_style) # end Stem