Skip to content

Commit

Permalink
added modified tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mxordn committed Jun 17, 2023
1 parent b5d7201 commit f62fc34
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 52 deletions.
8 changes: 5 additions & 3 deletions music21/harmony.py
Original file line number Diff line number Diff line change
Expand Up @@ -2509,9 +2509,9 @@ class FiguredBassIndication(Harmony):
The FiguredBassIndication object derives from the Harmony object and can be used
in the following way:
>>> fbi = harmony.FiguredBassIndication('#,6#')
>>> fbi = harmony.FiguredBassIndication('#,6#', part='1')
>>> fbi
<FiguredBassIndication figures: #,6#>
<FiguredBassIndication figures: #,6# part: 1>
The single figures are stored as figuredBass.notation.Figure objects:
>>> fbi.fig_notation.figures
Expand All @@ -2520,7 +2520,9 @@ class FiguredBassIndication(Harmony):
'''

isFigure: bool = True
part: str | None = None
part: str | None = None
_figs: str = ''

def __init__(self, figs: str | list | None = None, extenders: list[bool] | None = None ,
part: str | None=None, **keywords):
super().__init__(**keywords)
Expand Down
18 changes: 0 additions & 18 deletions music21/mei/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3235,15 +3235,12 @@ def measureFromElement(elem, backupNum, expectedNs, slurBundle=None, activeMeter
# track the bar's duration
maxBarDuration = None

print('=== EL', elem, '===')

# iterate all immediate children
for eachElem in elem.iterfind('*'):
# first get all information stored in <harm> tags.
# They are stored on the same level as <staff>.
if harmTag == eachElem.tag:
harmElements['fb'].append(harmFromElement(eachElem))
#print(' harms', harmElements, eachElem.get('n'))
elif staffTag == eachElem.tag:
staves[eachElem.get('n')] = stream.Measure(staffFromElement(eachElem,
slurBundle=slurBundle),
Expand Down Expand Up @@ -3614,14 +3611,6 @@ def scoreFromElement(elem, slurBundle):
# document. Iterating the keys in "parsed" would not preserve the order.
environLocal.printDebug('*** making the Score')

# TODO: Replace this with a better solution.
# Extract collected <harm> information stored in the dict unter the 'fb' key
harms: list[dict] | None = None
print('fb' in parsed.keys())
#if 'fb' in parsed.keys():
# harms = parsed['fb'][0]
# del parsed['fb']
# allPartNs = allPartNs[0:-1]

theScore = [stream.Part() for _ in range(len(allPartNs))]
for i, eachN in enumerate(allPartNs):
Expand All @@ -3631,13 +3620,6 @@ def scoreFromElement(elem, slurBundle):
theScore[i].append(eachObj)
theScore = stream.Score(theScore)

# loop through measures to insert harm elements from harms list at the right offsets
#if harms:
# for index, measureOffset in enumerate(theScore.measureOffsetMap().keys()):
# hms = harms[index]['fb']
# for h in hms:
# theScore.insert(measureOffset + h[0], h[1])

# put slurs in the Score
theScore.append(list(slurBundle))
# TODO: when all the Slur objects are at the end, they'll only be outputted properly if the
Expand Down
30 changes: 15 additions & 15 deletions music21/mei/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def testAllPartsPresent1(self):
staffDefs[0].get = mock.MagicMock(return_value='1')
elem = mock.MagicMock(spec_set=ETree.Element)
elem.findall = mock.MagicMock(return_value=staffDefs)
expected = ['1', 'fb']
expected = ['1']
actual = base.allPartsPresent(elem)
self.assertSequenceEqual(expected, actual)

Expand All @@ -212,7 +212,7 @@ def testAllPartsPresent2(self):
staffDefs[i].get = mock.MagicMock(return_value=str(i + 1))
elem = mock.MagicMock(spec_set=ETree.Element)
elem.findall = mock.MagicMock(return_value=staffDefs)
expected = ['1', '2', '3', '4', 'fb']
expected = ['1', '2', '3', '4']
actual = base.allPartsPresent(elem)
self.assertSequenceEqual(expected, actual)

Expand All @@ -225,7 +225,7 @@ def testAllPartsPresent3(self):
staffDefs[i].get = mock.MagicMock(return_value=str((i % 4) + 1))
elem = mock.MagicMock(spec_set=ETree.Element)
elem.findall = mock.MagicMock(return_value=staffDefs)
expected = ['1', '2', '3', '4', 'fb']
expected = ['1', '2', '3', '4']
actual = base.allPartsPresent(elem)
self.assertSequenceEqual(expected, actual)

Expand Down Expand Up @@ -3929,7 +3929,7 @@ def testMeasureUnit1(self, mockVoice, mockMeasure,
elem.append(eachStaff)
# @n="4" is in "expectedNs" but we're leaving it out as part of the test
backupNum = 900 # should be ignored by measureFromElement()
expectedNs = ['1', '2', '3', '4', 'fb']
expectedNs = ['1', '2', '3', '4']
slurBundle = mock.MagicMock(name='slurBundle')
activeMeter = mock.MagicMock(name='activeMeter')
activeMeter.barDuration = duration.Duration(4.0)
Expand Down Expand Up @@ -3963,7 +3963,7 @@ def testMeasureUnit1(self, mockVoice, mockMeasure,
for eachStaff in innerStaffs:
mockStaffFE.assert_any_call(eachStaff, slurBundle=slurBundle)
# ensure Measure.__init__() was called properly
self.assertEqual(len(expected) - 1, mockMeasure.call_count)
self.assertEqual(len(expected), mockMeasure.call_count)
for i in range(len(innerStaffs)):
mockMeasure.assert_any_call(i, number=int(elem.get('n')))
mockMeasure.assert_any_call([mockVoice.return_value], number=int(elem.get('n')))
Expand Down Expand Up @@ -3999,14 +3999,14 @@ def testMeasureIntegration1(self):
elem.append(eachStaff)
# @n="4" is in "expectedNs" but we're leaving it out as part of the test
backupNum = 900 # should be ignored by measureFromElement()
expectedNs = ['1', '2', '3', '4', 'fb']
expectedNs = ['1', '2', '3', '4']
slurBundle = spanner.SpannerBundle()
activeMeter = meter.TimeSignature('8/8') # bet you thought this would be 4/4, eh?

actual = base.measureFromElement(elem, backupNum, expectedNs, slurBundle, activeMeter)

# ensure the right number and @n of parts
self.assertEqual(5, len(actual.keys()))
self.assertEqual(4, len(actual.keys()))
for eachN in expectedNs:
self.assertTrue(eachN in actual)
# ensure the measure number is set properly,
Expand Down Expand Up @@ -4055,7 +4055,7 @@ def testMeasureUnit2(self, mockVoice, mockMeasure,
elem.append(eachStaff)
# @n="4" is in "expectedNs" but we're leaving it out as part of the test
backupNum = 900 # should be used by measureFromElement()
expectedNs = ['1', '2', '3', '4', 'fb']
expectedNs = ['1', '2', '3', '4']
slurBundle = mock.MagicMock(name='slurBundle')
activeMeter = mock.MagicMock(name='activeMeter')
# this must be longer than Measure.duration.quarterLength
Expand Down Expand Up @@ -4089,7 +4089,7 @@ def testMeasureUnit2(self, mockVoice, mockMeasure,
for eachStaff in innerStaffs:
mockStaffFE.assert_any_call(eachStaff, slurBundle=slurBundle)
# ensure Measure.__init__() was called properly
self.assertEqual(len(expected) - 1, mockMeasure.call_count)
self.assertEqual(len(expected), mockMeasure.call_count)
for i in range(len(innerStaffs)):
mockMeasure.assert_any_call(i, number=backupNum)
mockMeasure.assert_any_call([mockVoice.return_value], number=backupNum)
Expand Down Expand Up @@ -4123,14 +4123,14 @@ def testMeasureIntegration2(self):
elem.append(eachStaff)
# @n="4" is in "expectedNs" but we're leaving it out as part of the test
backupNum = 900 # should be used by measureFromElement()
expectedNs = ['1', '2', '3', '4', 'fb']
expectedNs = ['1', '2', '3', '4']
slurBundle = spanner.SpannerBundle()
activeMeter = meter.TimeSignature('8/8') # bet you thought this would be 4/4, eh?

actual = base.measureFromElement(elem, backupNum, expectedNs, slurBundle, activeMeter)

# ensure the right number and @n of parts (we expect one additional key, for the "rptboth")
self.assertEqual(6, len(actual.keys()))
self.assertEqual(5, len(actual.keys()))
for eachN in expectedNs:
self.assertTrue(eachN in actual)
self.assertTrue('next @left' in actual)
Expand All @@ -4151,7 +4151,7 @@ def testMeasureIntegration2(self):
self.assertIsInstance(actual[eachN].rightBarline, bar.Repeat)
self.assertEqual('final', actual[eachN].rightBarline.type)
else:
self.assertEqual([], actual[eachN]['fb'])
self.assertEqual([], actual[eachN])

@mock.patch('music21.mei.base.staffFromElement')
@mock.patch('music21.mei.base._correctMRestDurs')
Expand All @@ -4176,7 +4176,7 @@ def testMeasureUnit3a(self, mockStaffDefFE, mockMeasure,
staffElem = ETree.Element(staffTag, attrib={'n': '1'})
elem.append(staffElem)
backupNum = 900 # should be ignored by measureFromElement()
expectedNs = ['1', 'fb']
expectedNs = ['1']
slurBundle = mock.MagicMock(name='slurBundle')
activeMeter = mock.MagicMock(name='activeMeter')
# this must match Measure.duration.quarterLength
Expand Down Expand Up @@ -4230,7 +4230,7 @@ def testMeasureUnit3b(self, mockEnviron, mockMeasure,
staffElem = ETree.Element(staffTag, attrib={'n': '1'})
elem.append(staffElem)
backupNum = 900 # should be ignored by measureFromElement()
expectedNs = ['1', 'fb']
expectedNs = ['1']
slurBundle = mock.MagicMock(name='slurBundle')
activeMeter = mock.MagicMock(name='activeMeter')
# this must match Measure.duration.quarterLength
Expand Down Expand Up @@ -4290,7 +4290,7 @@ def testMeasureIntegration3(self):
actual = base.measureFromElement(elem, backupNum, expectedNs, slurBundle, activeMeter)

# ensure the right number and @n of parts
self.assertEqual(['1', 'fb'], list(actual.keys()))
self.assertEqual(['1'], list(actual.keys()))
# ensure the Measure has its expected Voice, BassClef, and Instrument
self.assertEqual(backupNum, actual['1'].number)
self.assertEqual(2, len(actual['1']))
Expand Down
2 changes: 1 addition & 1 deletion music21/musicxml/m21ToXml.py
Original file line number Diff line number Diff line change
Expand Up @@ -4644,7 +4644,7 @@ def figuredBassToXml(self, f: harmony.FiguredBassIndication):
>>> fbi = harmony.FiguredBassIndication()
>>> fbi.quarterLength = 2
>>> fbi.fig_noation = '#,6b'
>>> fbi.fig_notation = '#,6b'
>>> MEX = musicxml.m21ToXml.MeasureExporter()
Expand Down
3 changes: 2 additions & 1 deletion music21/musicxml/test_xmlToM21.py
Original file line number Diff line number Diff line change
Expand Up @@ -1515,7 +1515,8 @@ def testImportFiguredBassIndications(self):
self.assertIs(len(s.flatten().getElementsByClass(harmony.FiguredBassIndication)), 12)

s = converter.parse(xml_dir / 'piece01-bwv-1023-1-beginning.musicxml')
self.assertEqual(s.flatten().getElementsByClass(harmony.FiguredBassIndication)[12], '<FiguredBassIndication figures: 6,5♮>')
self.assertEqual(s.flatten().getElementsByClass(harmony.FiguredBassIndication)[12],
'<FiguredBassIndication figures: 6,5♮ part: P2>')


if __name__ == '__main__':
Expand Down
25 changes: 11 additions & 14 deletions music21/musicxml/xmlToM21.py
Original file line number Diff line number Diff line change
Expand Up @@ -5265,27 +5265,25 @@ def xmlToChordSymbol(

def xmlToFiguredBass(self, mxFiguredBass) -> harmony.FiguredBassIndication:
# noinspection PyShadowingNames
'''
"""
Converts a figured bass tag in musicxml to a harmony.FiguredBassIndication object:
>>> from xml.etree.ElementTree import fromstring as EL
>>> MP = musicxml.xmlToM21.MeasureParser()
>>> fbStr = """
<figured-bass>
<figure>
<figure-number>5</figure-number>
</figure>
<figure>
<figure-number>4</figure-number>
</figure>
</figured-bass>
"""
>>> fbStr = '''<figured-bass>
... <figure>
... <figure-number>5</figure-number>
... </figure>
... <figure>
... <figure-number>4</figure-number>
... </figure>
... </figured-bass>'''
>>> mxFigures = EL(fbStr)
>>> fbi = MP.xmlToFiguredBass(mxFigures)
>>> fbi
<FiguredBassIndication figures: 5,4>
'''
<FiguredBassIndication figures: 5,4 part: >
"""

fb_strings: list[str] = []
fb_extenders: list[bool] = []
Expand Down Expand Up @@ -5320,7 +5318,6 @@ def xmlToFiguredBass(self, mxFiguredBass) -> harmony.FiguredBassIndication:
# collect information on extenders
if el.tag == 'extend':
if 'type' in el.attrib.keys():
print((el.attrib['type'] in ['stop', 'continue', 'start']))
fb_extenders.append((el.attrib['type'] in ['stop', 'continue', 'start']))
if not subElement.findall('extend'):
fb_extenders.append(False)
Expand Down

0 comments on commit f62fc34

Please sign in to comment.