Skip to content

Commit 642e74f

Browse files
committed
Music Cleanups
Saw some cleanups while reviewing PR cuthbertLab#1905 but I decided to make this separate. "Let Python be Python" -- move string concat in tests to use implicit. Fix a bug in ABC Parsing of ABCNote vs subclass ABCChord (order of attributes in parse were reversed -- was okay because they were called by keyword). Standardize ElementTree.fromstring as `EL` not `ET.fromstring` or `El`
1 parent ceb8893 commit 642e74f

23 files changed

Lines changed: 348 additions & 326 deletions

music21/abcFormat/__init__.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,11 @@ def __init__(self, src: str = ''):
17681768
# store a list of component objects
17691769
self.subTokens: list[ABCToken] = []
17701770

1771-
def parse(self, forceKeySignature=None, forceDefaultQuarterLength=None):
1771+
def parse(
1772+
self,
1773+
forceDefaultQuarterLength: float|None = None,
1774+
forceKeySignature: key.KeySignature|None = None
1775+
):
17721776
'''
17731777
Handles the following types of chords:
17741778
@@ -1803,6 +1807,7 @@ def parse(self, forceKeySignature=None, forceDefaultQuarterLength=None):
18031807
outer_lengthModifier = self.getQuarterLength(outerLengthModifierStr,
18041808
forceDefaultQuarterLength=1.0)
18051809

1810+
activeKeySignature: key.KeySignature|None
18061811
if forceKeySignature is not None:
18071812
activeKeySignature = forceKeySignature
18081813
else: # may be None
@@ -1815,7 +1820,7 @@ def parse(self, forceKeySignature=None, forceDefaultQuarterLength=None):
18151820
# may need to supply key?
18161821
ah.tokenize(tokenStr)
18171822

1818-
inner_quarterLength = 0
1823+
inner_quarterLength: OffsetQL = 0.0
18191824
# tokens contained here are each ABCNote instances
18201825
for token in ah.tokens:
18211826
# environLocal.printDebug(['ABCChord: subTokens', t])
@@ -2631,10 +2636,10 @@ def tokenProcess(self) -> None:
26312636
# notes within slur marks need to be added to the spanner
26322637
if isinstance(token, ABCSlurStart):
26332638
token.fillSlur()
2639+
slurObj = token.slurObj
26342640
if t.TYPE_CHECKING:
2635-
assert token.slurObj is not None
2636-
2637-
self.activeSpanners.append(token.slurObj)
2641+
assert slurObj is not None
2642+
self.activeSpanners.append(slurObj)
26382643
self.activeParens.append('Slur')
26392644
elif isinstance(token, ABCParenStop):
26402645
if self.activeParens:
@@ -2951,10 +2956,10 @@ def definesMeasures(self):
29512956
Returns True if this token structure defines Measures in a normal Measure form.
29522957
Otherwise False
29532958
2954-
>>> abcStr = ('M:6/8\\nL:1/8\\nK:G\\nV:1 name="Whistle" ' +
2955-
... 'snm="wh"\\nB3 A3 | G6 | B3 A3 | G6 ||\\nV:2 name="violin" ' +
2956-
... 'snm="v"\\nBdB AcA | GAG D3 | BdB AcA | GAG D6 ||\\nV:3 name="Bass" ' +
2957-
... 'snm="b" clef=bass\\nD3 D3 | D6 | D3 D3 | D6 ||')
2959+
>>> abcStr = ('M:6/8\\nL:1/8\\nK:G\\nV:1 name="Whistle" '
2960+
... 'snm="wh"\\nB3 A3 | G6 | B3 A3 | G6 ||\\nV:2 name="violin" '
2961+
... 'snm="v"\\nBdB AcA | GAG D3 | BdB AcA | GAG D6 ||\\nV:3 name="Bass" '
2962+
... 'snm="b" clef=bass\\nD3 D3 | D6 | D3 D3 | D6 ||')
29582963
>>> ah = abcFormat.ABCHandler()
29592964
>>> junk = ah.process(abcStr)
29602965
>>> ah.definesMeasures()
@@ -2989,10 +2994,10 @@ def splitByVoice(self) -> list[ABCHandler]:
29892994
29902995
Each part is returned as a ABCHandler instance.
29912996
2992-
>>> abcStr = ('M:6/8\\nL:1/8\\nK:G\\nV:1 name="Whistle" ' +
2993-
... 'snm="wh"\\nB3 A3 | G6 | B3 A3 | G6 ||\\nV:2 name="violin" ' +
2994-
... 'snm="v"\\nBdB AcA | GAG D3 | BdB AcA | GAG D6 ||\\nV:3 name="Bass" ' +
2995-
... 'snm="b" clef=bass\\nD3 D3 | D6 | D3 D3 | D6 ||')
2997+
>>> abcStr = ('M:6/8\\nL:1/8\\nK:G\\nV:1 name="Whistle" '
2998+
... 'snm="wh"\\nB3 A3 | G6 | B3 A3 | G6 ||\\nV:2 name="violin" '
2999+
... 'snm="v"\\nBdB AcA | GAG D3 | BdB AcA | GAG D6 ||\\nV:3 name="Bass" '
3000+
... 'snm="b" clef=bass\\nD3 D3 | D6 | D3 D3 | D6 ||')
29963001
>>> ah = abcFormat.ABCHandler()
29973002
>>> ah.process(abcStr)
29983003
>>> tokenColls = ah.splitByVoice()

music21/alpha/analysis/search.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ def findConsecutiveScale(source, targetScale, degreesRequired=5,
187187
stepSize=1,
188188
comparisonAttribute=comparisonAttribute):
189189
pass
190-
# environLocal.printDebug(['matched degree count but next pitch is ' +
191-
# 'in scale and direction', 'collDegrees', collDegrees])
190+
# environLocal.printDebug(['matched degree count but next pitch is '
191+
# + 'in scale and direction', 'collDegrees', collDegrees])
192192
else:
193193
# environLocal.printDebug(['matched degree count', 'collDegrees', collDegrees,
194194
# 'pNext', pNext])

music21/analysis/reduction.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -615,11 +615,10 @@ def _createEventSpans(self):
615615
# eLast = partMeasures[0][i]
616616
# # use duration, not barDuration.quarterLength
617617
# # as want filled duration?
618-
# eEnd = (eLast.getOffsetBySite(
619-
# partMeasures[0]) +
620-
# eLast.barDuration.quarterLength)
621-
# ds = {'eStart':eStart, 'span':eEnd-eStart,
622-
# 'weight':None, 'color':pColor}
618+
# eEnd = (eLast.getOffsetBySite(partMeasures[0])
619+
# + eLast.barDuration.quarterLength)
620+
# ds = {'eStart': eStart, 'span': eEnd - eStart,
621+
# 'weight': None, 'color': pColor}
623622
# dataEvents.append(ds)
624623
# eStart = None
625624
# eLast = partMeasures[0][i]

music21/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,8 +2447,8 @@ def _setActiveSite(self, site: stream.Stream|None):
24472447
self._activeSiteStoredOffset = storedOffset
24482448
# siteId = id(site)
24492449
# if not self.sites.hasSiteId(siteId): # This should raise a warning, should not happen
2450-
# # environLocal.warn('Adding a siteDict entry for a ' +
2451-
# # 'site that should already be there!')
2450+
# # environLocal.warn('Adding a siteDict entry for a '
2451+
# # 'site that should already be there!')
24522452
# self.sites.add(site, idKey=siteId)
24532453
else:
24542454
self._activeSiteStoredOffset = None

music21/capella/fromCapellaXML.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def domElementFromText(self, xmlText=None):
148148
149149
>>> ci = capella.fromCapellaXML.CapellaImporter()
150150
>>> funnyTag = ci.domElementFromText(
151-
... '<funny yes="definitely"><greg/>hi<greg><ha>ha</ha>' +
151+
... '<funny yes="definitely"><greg/>hi<greg><ha>ha</ha>'
152152
... '<greg type="embedded"/></greg></funny>')
153153
>>> funnyTag
154154
<Element 'funny' at 0x...>
@@ -441,7 +441,7 @@ def chordOrNoteFromChord(self, chordElement):
441441
This one is an actual chord
442442
443443
>>> chordElement = ci.domElementFromText(
444-
... '<chord><duration base="1/8"/>' +
444+
... '<chord><duration base="1/8"/>'
445445
... '<heads><head pitch="G4"/><head pitch="A5"/></heads></chord>')
446446
>>> c = ci.chordOrNoteFromChord(chordElement)
447447
>>> c
@@ -615,7 +615,7 @@ def lyricListFromLyric(self, lyricElement):
615615
616616
>>> ci = capella.fromCapellaXML.CapellaImporter()
617617
>>> lyricEl = ci.domElementFromText(
618-
... '<lyric><verse i="0" hyphen="true">di</verse>' +
618+
... '<lyric><verse i="0" hyphen="true">di</verse>'
619619
... '<verse i="1">man,</verse><verse i="2">frau,</verse></lyric>')
620620
>>> ci.lyricListFromLyric(lyricEl)
621621
[<music21.note.Lyric number=1 syllabic=begin text='di'>,

music21/converter/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ def parseURL(
749749
re-reading from a cached file.
750750
751751
>>> joplinURL = ('https://github.com/cuthbertLab/music21/raw/master'
752-
... + '/music21/corpus/joplin/maple_leaf_rag.mxl')
752+
... '/music21/corpus/joplin/maple_leaf_rag.mxl')
753753
>>> c = converter.Converter()
754754
>>> #_DOCS_SHOW c.parseURL(joplinURL)
755755
>>> #_DOCS_SHOW joplinStream = c.stream
@@ -2130,8 +2130,8 @@ def testMEIvsMX(self):
21302130
# These strings aren't valid documents, but they are enough to pass the detection we're
21312131
# testing in parseData(). But it does mean we'll be testing in a strange way.
21322132
meiString = '<?xml version="1.0" encoding="UTF-8"?><mei><note/></mei>'
2133-
# mxlString = ('<?xml version="1.0" encoding="UTF-8"?>' +
2134-
# '<score-partwise><note/></score-partwise>')
2133+
# mxlString = ('<?xml version="1.0" encoding="UTF-8"?>'
2134+
# '<score-partwise><note/></score-partwise>')
21352135

21362136
# The "mei" module raises an MeiElementError with "meiString," so as long as that's raised,
21372137
# we know that parseData() chose correctly.

music21/converter/subConverters.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,8 @@ def parseData(self, humdrumString, number=None):
631631
Open Humdrum data from a string -- calls
632632
:meth:`~music21.humdrum.spineParser.HumdrumDataCollection.parse()`.
633633
634-
>>> humData = ('**kern\\n*M2/4\\n=1\\n24r\\n24g#\\n24f#\\n24e\\n24c#\\n' +
635-
... '24f\\n24r\\n24dn\\n24e-\\n24gn\\n24e-\\n24dn\\n*-')
634+
>>> humData = ('**kern\\n*M2/4\\n=1\\n24r\\n24g#\\n24f#\\n24e\\n24c#\\n'
635+
... '24f\\n24r\\n24dn\\n24e-\\n24gn\\n24e-\\n24dn\\n*-')
636636
>>> c = converter.subConverters.ConverterHumdrum()
637637
>>> s = c.parseData(humData)
638638
>>> c.stream.show('text')
@@ -762,8 +762,8 @@ def parseData(self, nwcData):
762762
r'''
763763
Open Noteworthy data from a string or list
764764
765-
>>> nwcData = ('!NoteWorthyComposer(2.0)\n|AddStaff\n|Clef|' +
766-
... 'Type:Treble\n|Note|Dur:Whole|Pos:1^')
765+
>>> nwcData = ('!NoteWorthyComposer(2.0)\n|AddStaff\n|Clef|'
766+
... 'Type:Treble\n|Note|Dur:Whole|Pos:1^')
767767
>>> c = converter.subConverters.ConverterNoteworthy()
768768
>>> c.parseData(nwcData)
769769
>>> c.stream.show('text')

music21/corpus/testCorpus.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ def testSearch10(self):
155155
# self.assertGreater(len(searchResults), 0)
156156
# # returns items in pairs: url and work number
157157
# self.assertEqual(searchResults[0].sourcePath,
158-
# 'http://impromastering.com/uploads/transcription_file/' +
159-
# 'file/196/Giant_Steps__John_Coltrane_C.xml')
158+
# 'http://impromastering.com/uploads/transcription_file/'
159+
# + 'file/196/Giant_Steps__John_Coltrane_C.xml')
160160

161161
# def testGetWorkList(self):
162162
# self.assertGreaterEqual(len(corpus.corpora.CoreCorpus().getPaths('.md')), 38)

music21/harmony.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ def _updateFromParameters(
297297
but we want the objects to retain their initial root, bass, and inversion.
298298
'''
299299
if root and isinstance(root, str):
300-
root = common.cleanedFlatNotation(root)
301-
self.root(pitch.Pitch(root, octave=3))
300+
root_str = common.cleanedFlatNotation(root)
301+
self.root(pitch.Pitch(root_str, octave=3))
302302
elif root is not None:
303303
self.root(root)
304304

@@ -308,8 +308,8 @@ def _updateFromParameters(
308308

309309
# and then bass.
310310
if bass and isinstance(bass, str):
311-
bass = common.cleanedFlatNotation(bass)
312-
self.bass(pitch.Pitch(bass, octave=3), allow_add=True)
311+
bass_str = common.cleanedFlatNotation(bass)
312+
self.bass(pitch.Pitch(bass_str, octave=3), allow_add=True)
313313
elif bass is not None:
314314
self.bass(bass, allow_add=True)
315315

@@ -2267,9 +2267,9 @@ def findFigure(self):
22672267
>>> from xml.etree.ElementTree import fromstring as EL
22682268
>>> MP = musicxml.xmlToM21.MeasureParser()
22692269
2270-
>>> elStr = (r'<harmony><root><root-step>C</root-step></root><kind>dominant</kind>' +
2271-
... '<degree><degree-value>9</degree-value><degree-alter>-1</degree-alter>' +
2272-
... ' <degree-type>add</degree-type></degree></harmony>')
2270+
>>> elStr = ('<harmony><root><root-step>C</root-step></root><kind>dominant</kind>'
2271+
... '<degree><degree-value>9</degree-value><degree-alter>-1</degree-alter>'
2272+
... ' <degree-type>add</degree-type></degree></harmony>')
22732273
>>> mxHarmony = EL(elStr)
22742274
22752275
>>> cs = MP.xmlToChordSymbol(mxHarmony)
@@ -2283,10 +2283,10 @@ def findFigure(self):
22832283
<music21.pitch.Pitch B-3>,
22842284
<music21.pitch.Pitch D-4>)
22852285
2286-
>>> elStr = (r'<harmony><root><root-step>C</root-step></root><kind>major</kind>' +
2287-
... '<bass><bass-step>B</bass-step><bass-alter>-1</bass-alter></bass>' +
2288-
... '<degree><degree-value>2</degree-value><degree-alter>0</degree-alter>' +
2289-
... ' <degree-type>add</degree-type></degree></harmony>')
2286+
>>> elStr = ('<harmony><root><root-step>C</root-step></root><kind>major</kind>'
2287+
... '<bass><bass-step>B</bass-step><bass-alter>-1</bass-alter></bass>'
2288+
... '<degree><degree-value>2</degree-value><degree-alter>0</degree-alter>'
2289+
... ' <degree-type>add</degree-type></degree></harmony>')
22902290
>>> mxHarmony = EL(elStr)
22912291
22922292
>>> cs = MP.xmlToChordSymbol(mxHarmony)
@@ -2682,8 +2682,13 @@ def testHarmonyPreservesInversionAndBass(self):
26822682
self.assertEqual(explicitFm6.inversion(), 1)
26832683
self.assertEqual(explicitFm6.bass(find=False).name, 'A-')
26842684
self.assertEqual(explicitFm6.root(find=False).name, 'F')
2685-
self.assertLess(explicitFm6.bass(find=False).octave,
2686-
explicitFm6.root(find=False).octave)
2685+
fm6bassOctave = explicitFm6.bass(find=False).octave
2686+
fm6rootOctave = explicitFm6.root(find=False).octave
2687+
self.assertIsNotNone(fm6bassOctave)
2688+
self.assertIsNotNone(fm6rootOctave)
2689+
assert fm6bassOctave is not None
2690+
assert fm6rootOctave is not None
2691+
self.assertLess(fm6bassOctave, fm6rootOctave)
26872692

26882693
def testClassSortOrderHarmony(self):
26892694
'''
@@ -2836,7 +2841,6 @@ def runTestOnChord(self, xmlString, figure, pitches):
28362841
self.assertEqual(cs1.bass(), cs3.bass())
28372842

28382843
def testChordWithBass(self):
2839-
28402844
xmlString = '''
28412845
<harmony>
28422846
<root>

music21/humdrum/spineParser.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,10 @@ def parseEventListFromDataStream(
377377
378378
Returns eventList in addition to setting it as `self.eventList`.
379379
380-
>>> eventString = ('!!! COM: Beethoven, Ludwig van\n' +
381-
... '!! Not really a piece by Beethoven\n' +
382-
... '**kern\t**dynam\n' +
383-
... 'C4\tpp\n' +
380+
>>> eventString = ('!!! COM: Beethoven, Ludwig van\n'
381+
... '!! Not really a piece by Beethoven\n'
382+
... '**kern\t**dynam\n'
383+
... 'C4\tpp\n'
384384
... 'D8\t.\n')
385385
>>> hdc = humdrum.spineParser.HumdrumDataCollection(eventString)
386386
>>> hdc.maxSpines = 2
@@ -459,10 +459,10 @@ def parseProtoSpinesAndEventCollections(
459459
Returns a tuple of protoSpines and eventCollections in addition to
460460
setting it in the calling object.
461461
462-
>>> eventString = ('!!!COM: Beethoven, Ludwig van\n' +
463-
... '!! Not really a piece by Beethoven\n' +
464-
... '**kern\t**dynam\n' +
465-
... 'C4\tpp\n' +
462+
>>> eventString = ('!!!COM: Beethoven, Ludwig van\n'
463+
... '!! Not really a piece by Beethoven\n'
464+
... '**kern\t**dynam\n'
465+
... 'C4\tpp\n'
466466
... 'D8\t.\n')
467467
>>> hdc = humdrum.spineParser.HumdrumDataCollection(eventString)
468468
>>> hdc.maxSpines = 2
@@ -784,11 +784,11 @@ def insertGlobalEvents(self) -> None:
784784
# if self.spineCollection is None:
785785
# raise HumdrumException('parsing got no spine collections!')
786786
# elif self.spineCollection.spines is None:
787-
# raise HumdrumException('not a single spine in your data. Is this your problem? ' +
788-
# '(File a bug report if you ' +
787+
# raise HumdrumException('not a single spine in your data. Is this your problem? '
788+
# '(File a bug report if you '
789789
# 'have doubled checked your data)')
790790
# elif self.spineCollection.spines[0].stream is None:
791-
# raise HumdrumException('okay, you got at least one spine, but it does not have ' +
791+
# raise HumdrumException('okay, you got at least one spine, but it does not have '
792792
# 'a stream in it; (check your data or file a bug report)')
793793
# else:
794794
# masterStream = stream.Score()
@@ -2400,7 +2400,7 @@ def hdStringToNote(contents: str) -> note.GeneralNote:
24002400
elif '\\' in contents:
24012401
thisObject.stemDirection = 'down'
24022402

2403-
# 3.2.7 Duration +
2403+
# 3.2.7 Duration and
24042404
# 3.2.8 N-Tuplets
24052405

24062406
# TODO: SPEEDUP -- only search for rational after foundNumber.

0 commit comments

Comments
 (0)