diff --git a/music21/_version.py b/music21/_version.py index d45d6c0cd..240ab9a1f 100644 --- a/music21/_version.py +++ b/music21/_version.py @@ -47,7 +47,7 @@ ''' from __future__ import annotations -__version__ = '11.0.0b7' +__version__ = '11.0.0b8' def get_version_tuple(vv): v = vv.split('.') diff --git a/music21/base.py b/music21/base.py index 85ae8bbe7..3a3c407d2 100644 --- a/music21/base.py +++ b/music21/base.py @@ -26,7 +26,7 @@ >>> music21.VERSION_STR -'11.0.0b7' +'11.0.0b8' Alternatively, after doing a complete import, these classes are available under the module "base": diff --git a/music21/pitch.py b/music21/pitch.py index 8d909b8d4..40680a092 100644 --- a/music21/pitch.py +++ b/music21/pitch.py @@ -5048,6 +5048,17 @@ def set_displayStatus(newDisplayStatus: bool) -> None: set_displayStatus(True) return + # here tied and always are treated the same; we assume that + # making ties sets the displayStatus, and thus we would not be + # overriding that display status here + if (cautionaryAll is True + or (acc is not None + and acc.displayType in ('even-tied', 'always'))): + # show all accidentals, no matter what is in the past + # or in the key signature + set_displayStatus(True) + return # do not search past + # no pitches in the past list if not pitchPastAll: # if we have no past, we show the accidental if this pitch name @@ -5089,16 +5100,6 @@ def set_displayStatus(newDisplayStatus: bool) -> None: break # nope, no conflicting accidentals at this name and octave in the past - # here tied and always are treated the same; we assume that - # making ties sets the displayStatus, and thus we would not be - # overriding that display status here - if (cautionaryAll is True - or (acc is not None - and acc.displayType in ('even-tied', 'always'))): - # show all accidentals, even if past encountered - set_displayStatus(True) - return # do not search past - # store if a match was found and display set from past pitches setFromPitchPast = False diff --git a/music21/test/test_pitch.py b/music21/test/test_pitch.py index 80cfedfe0..309fe3f3c 100644 --- a/music21/test/test_pitch.py +++ b/music21/test/test_pitch.py @@ -396,6 +396,55 @@ def testOverrideDisplayStatus(self): n.pitch.updateAccidentalDisplay(overrideStatus=True, alteredPitches=k.alteredPitches) self.assertIs(n.pitch.accidental.displayStatus, False) + def testDisplayTypeAlwaysWithNothingInPast(self): + ''' + `displayType='always'` and `cautionaryAll` win over the key signature + even for the first pitch of a part, where nothing precedes it. + + AI-assisted (Claude). + ''' + p = Pitch('An2') + p.accidental.displayType = 'always' + p.updateAccidentalDisplay() + self.assertIs(p.accidental.displayStatus, True) + + # a sharp already implied by the key signature still shows + p = Pitch('F#4') + p.accidental.displayType = 'always' + p.updateAccidentalDisplay(alteredPitches=key.Key('G').alteredPitches) + self.assertIs(p.accidental.displayStatus, True) + + # cautionaryAll creates the natural that was not there + p = Pitch('B4') + p.updateAccidentalDisplay(cautionaryAll=True) + self.assertEqual(p.accidental.name, 'natural') + self.assertIs(p.accidental.displayStatus, True) + + # 'even-tied' behaves the same as 'always' here + p = Pitch('E-3') + p.accidental.displayType = 'even-tied' + p.updateAccidentalDisplay(alteredPitches=key.Key('E-').alteredPitches) + self.assertIs(p.accidental.displayStatus, True) + + # in a stream, every note of the part shows, not just the ones after the first + s = converter.parse('tinyNotation: AAn2 Fn') + for n in s.recurse().notes: + n.pitch.accidental.displayType = 'always' + s.makeAccidentals(inPlace=True) + self.assertEqual([n.pitch.accidental.displayStatus for n in s.recurse().notes], + [True, True]) + + # regression guard: a normal displayType is untouched by the above + p = Pitch('F#4') + p.updateAccidentalDisplay(alteredPitches=key.Key('G').alteredPitches) + self.assertIs(p.accidental.displayStatus, False) + + # regression guard: with a non-empty past, repeated pitches are unchanged + past = [Pitch('c#4')] + p = Pitch('c#4') + p.updateAccidentalDisplay(pitchPast=past) + self.assertIs(p.accidental.displayStatus, False) + def testImplicitToExplicitNatural(self): p = converter.parse('tinyNotation: 2/4 f4 fn4') last_note = p.recurse().notes.last()