From c6ae99a5e385a2088a758bc0bc2c997a76c6e646 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 28 Aug 2026 12:38:07 -1000 Subject: [PATCH 1/4] Drop the self-imports that existed only to dodge the shadow modules ModuleGather.getModule used to load each file as a separate top-level module, so a test's own module globals held a different copy of its classes than music21.spanner did. Tests worked around it by re-importing their own module -- `from music21 import spanner` inside spanner.Test -- which restored identity but also made the module read as though it were a foreign one. Now that the runner imports by fully-qualified name (#2014), the workaround is dead weight. Removes 90 self-imports across 21 modules and rewrites their references to the bare module-level names. Also drops three comments that only explained the workaround (bar.py's "avoid not same class error" plus its pylint disable, parallel.py's "we need the full path to the modules", iterator.py's noinspection), and re-aligns three continuation lines the shortened call names left over-indented. Not touched: clef.clefFromString's `from music21 import clef as myself`, which is a real dynamic lookup over the module's own namespace, not a test artifact. Verified with multiprocessTest (5299 tests) and testSingleCoreAll (5022), plus ruff, mypy, pylint, and a pycodestyle E12 pass held to its prior count. AI-assisted (Claude) --- music21/abcFormat/__init__.py | 9 +- music21/bar.py | 2 - music21/common/parallel.py | 3 - music21/configure.py | 17 ++- music21/duration.py | 6 +- music21/dynamics.py | 5 +- music21/freezeThaw.py | 21 ++-- music21/harmony.py | 44 ++++---- music21/instrument.py | 96 ++++++++--------- music21/layout.py | 3 +- music21/note.py | 6 +- music21/roman.py | 150 ++++++++++++--------------- music21/romanText/clercqTemperley.py | 3 +- music21/romanText/translate.py | 8 +- music21/sieve.py | 12 +-- music21/spanner.py | 106 +++++++------------ music21/stream/iterator.py | 4 +- music21/tablature.py | 3 +- music21/tempo.py | 62 +++++------ music21/variant.py | 15 +-- music21/volume.py | 20 ++-- 21 files changed, 245 insertions(+), 350 deletions(-) diff --git a/music21/abcFormat/__init__.py b/music21/abcFormat/__init__.py index 4c15bb734..7319a0050 100644 --- a/music21/abcFormat/__init__.py +++ b/music21/abcFormat/__init__.py @@ -3935,8 +3935,7 @@ def testBow(self): def testAcc(self): from music21.abcFormat import testFiles - from music21 import abcFormat - ah = abcFormat.ABCHandler() + ah = ABCHandler() ah.process(testFiles.accTest) # noinspection SpellCheckingInspection tokensCorrect = ''' @@ -4035,11 +4034,11 @@ def testAcc(self): j = 0 k = 0 for token in tokens: - if isinstance(token, abcFormat.ABCAccent): + if isinstance(token, ABCAccent): i += 1 - elif isinstance(token, abcFormat.ABCStraccent): + elif isinstance(token, ABCStraccent): j += 1 - elif isinstance(token, abcFormat.ABCTenuto): + elif isinstance(token, ABCTenuto): k += 1 self.assertEqual(i, 2) self.assertEqual(j, 2) diff --git a/music21/bar.py b/music21/bar.py index 05b1c35f0..57f02a449 100644 --- a/music21/bar.py +++ b/music21/bar.py @@ -408,8 +408,6 @@ def testSortOrder(self): def testFreezeThaw(self): from music21 import converter from music21 import stream - # pylint: disable=redefined-outer-name - from music21.bar import Barline # avoid not same class error b = Barline() self.assertNotIn('StyleMixin', b.classes) diff --git a/music21/common/parallel.py b/music21/common/parallel.py index d10c50933..438d2cf5c 100644 --- a/music21/common/parallel.py +++ b/music21/common/parallel.py @@ -272,11 +272,8 @@ def _countUnpacked(i: int, filename: str) -> bool: class Test(unittest.TestCase): - # pylint: disable=redefined-outer-name def x_figure_out_segfault_testMultiprocess(self) -> None: files = ['bach/bwv66.6', 'schoenberg/opus19', 'AcaciaReel'] - # for importing into testSingleCoreAll we need the full path to the modules - from music21.common.parallel import _countN, _countUnpacked output = runParallel(files, _countN) self.assertEqual(output, [165, 50, 131]) runParallel(files, diff --git a/music21/configure.py b/music21/configure.py index e5e3ad3c1..024af6d3c 100644 --- a/music21/configure.py +++ b/music21/configure.py @@ -1545,9 +1545,8 @@ def testConfigurationAssistant(self): class Test(unittest.TestCase): def testYesOrNo(self): - from music21 import configure - d = configure.YesOrNo(default=True, tryAgain=False, - promptHeader='Are you ready to continue?') + d = YesOrNo(default=True, tryAgain=False, + promptHeader='Are you ready to continue?') d.askUser('n') self.assertEqual(str(d.getResult()), 'False') d.askUser('y') @@ -1557,8 +1556,8 @@ def testYesOrNo(self): d.askUser('blah') # gets default self.assertEqual(str(d.getResult()), '') - d = configure.YesOrNo(default=None, tryAgain=False, - promptHeader='Are you ready to continue?') + d = YesOrNo(default=None, tryAgain=False, + promptHeader='Are you ready to continue?') d.askUser('n') self.assertEqual(str(d.getResult()), 'False') d.askUser('y') @@ -1569,13 +1568,11 @@ def testYesOrNo(self): self.assertEqual(str(d.getResult()), '') def testSelectFromList(self): - from music21 import configure - d = configure.SelectFromList(default=1) + d = SelectFromList(default=1) self.assertEqual(d._default, 1) def testSelectMusicXMLReaders(self): - from music21 import configure - d = configure.SelectMusicXMLReader() + d = SelectMusicXMLReader() # force request to user by returning no valid results def getValidResults(force=None): @@ -1585,7 +1582,7 @@ def getValidResults(force=None): d.askUser(force='n', skipIntro=True) # reject option to open in a browser post = d.getResult() # returns a bad condition b/c there are no options and user entered 'n' - self.assertIsInstance(post, configure.BadConditions) + self.assertIsInstance(post, BadConditions) def testMuseScoreNameRe(self): ''' diff --git a/music21/duration.py b/music21/duration.py index 5a7b27c6f..a0af8d046 100644 --- a/music21/duration.py +++ b/music21/duration.py @@ -3915,16 +3915,14 @@ def testAugmentOrDiminish(self): "DurationTuple(type='16th', dots=0, quarterLength=0.25)") def testUnlinkedTypeA(self): - from music21 import duration - - du = duration.Duration() + du = Duration() du.linked = False du.quarterLength = 5.0 du.type = 'quarter' self.assertEqual(du.quarterLength, 5.0) self.assertEqual(du.type, 'quarter') - d = duration.Duration() + d = Duration() self.assertTrue(d.linked) # note set d.linked = False d.type = 'quarter' diff --git a/music21/dynamics.py b/music21/dynamics.py index ecd20297a..146ea7978 100644 --- a/music21/dynamics.py +++ b/music21/dynamics.py @@ -430,13 +430,12 @@ def testBasic(self): def testCorpusDynamicsWedge(self): from music21 import corpus - from music21 import dynamics a = corpus.parse('opus41no1/movement2') # has dynamics! - b = a.parts[0].flatten().getElementsByClass(dynamics.Dynamic) + b = a.parts[0].flatten().getElementsByClass(Dynamic) self.assertEqual(len(b), 35) - b = a.parts[0].flatten().getElementsByClass(dynamics.DynamicWedge) + b = a.parts[0].flatten().getElementsByClass(DynamicWedge) self.assertEqual(len(b), 2) def testMusicxmlOutput(self): diff --git a/music21/freezeThaw.py b/music21/freezeThaw.py index 86cf877fe..3176ec6fc 100644 --- a/music21/freezeThaw.py +++ b/music21/freezeThaw.py @@ -1047,7 +1047,6 @@ def testFreezeThawCorpusFileWithSpanners(self): self.assertEqual(len(s.parts[0].measure(7).notes), 6) def x_testSimplePickle(self): - from music21 import freezeThaw from music21 import corpus c = corpus.parse('bwv66.6').parts[0].measure(0).notes @@ -1061,7 +1060,7 @@ def x_testSimplePickle(self): n1 = c[0] n2 = c[1] - sf = freezeThaw.StreamFreezer(c, fastButUnsafe=True) + sf = StreamFreezer(c, fastButUnsafe=True) sf.setupSerializationScaffold() for dummy in n1.sites.siteDict: pass @@ -1088,17 +1087,16 @@ def x_testSimplePickle(self): # s.show('t') def x_testFreezeThawPickle(self): - from music21 import freezeThaw from music21 import corpus c = corpus.parse('luca/gloria') # c.show('t') - sf = freezeThaw.StreamFreezer(c, fastButUnsafe=True) + sf = StreamFreezer(c, fastButUnsafe=True) d = sf.writeStr() # print(d) - st = freezeThaw.StreamThawer() + st = StreamThawer() st.openStr(d) s = st.stream @@ -1107,7 +1105,6 @@ def x_testFreezeThawPickle(self): pass def testFreezeThawSimpleVariant(self): - from music21 import freezeThaw from music21 import stream from music21 import note @@ -1126,15 +1123,14 @@ def testFreezeThawSimpleVariant(self): s.insert(0, v) - sf = freezeThaw.StreamFreezer(s) + sf = StreamFreezer(s) d = sf.writeStr() - st = freezeThaw.StreamThawer() + st = StreamThawer() st.openStr(d) s = st.stream def testFreezeThawVariant(self): - from music21 import freezeThaw from music21 import corpus from music21 import stream from music21 import note @@ -1156,14 +1152,14 @@ def testFreezeThawVariant(self): # test Variant is in stream unused_v1 = c.parts.first().getElementsByClass(variant.Variant).first() - sf = freezeThaw.StreamFreezer(c, fastButUnsafe=True) + sf = StreamFreezer(c, fastButUnsafe=True) # sf.v = v d = sf.writeStr() # print(d) # print('thawing.') - st = freezeThaw.StreamThawer() + st = StreamThawer() st.openStr(d) s = st.stream # s.show('lily.pdf') @@ -1176,7 +1172,6 @@ def testFreezeThawVariant(self): def testSerializationScaffoldA(self): from music21 import note from music21 import stream - from music21 import freezeThaw n1 = note.Note() @@ -1186,7 +1181,7 @@ def testSerializationScaffoldA(self): s1.append(n1) s2.append(n1) - sf = freezeThaw.StreamFreezer(s2, fastButUnsafe=False) + sf = StreamFreezer(s2, fastButUnsafe=False) sf.setupSerializationScaffold() # test safety diff --git a/music21/harmony.py b/music21/harmony.py index 3acc12e99..ec9dabb64 100644 --- a/music21/harmony.py +++ b/music21/harmony.py @@ -2634,8 +2634,7 @@ def realizeChordSymbolDurations(piece): class Test(unittest.TestCase): def testChordAttributes(self): - from music21 import harmony - cs = harmony.ChordSymbol('Cm') + cs = ChordSymbol('Cm') self.assertEqual(str(cs), '') self.assertEqual( str(cs.pitches), @@ -2644,15 +2643,13 @@ def testChordAttributes(self): self.assertTrue(cs.isConsonant()) def testBasic(self): - from music21 import harmony - h = harmony.Harmony() - hd = harmony.ChordStepModification('add', 4) + h = Harmony() + hd = ChordStepModification('add', 4) h.addChordStepModification(hd) self.assertEqual(len(h.chordStepModifications), 1) def testChordKindSetting(self): - from music21 import harmony - cs = harmony.ChordSymbol() + cs = ChordSymbol() cs.root('E-') cs.bass('B-', allow_add=True) cs.inversion(2, transposeOnSet=False) @@ -2717,38 +2714,37 @@ def testClassSortOrderHarmony(self): self.assertIs(n.getContextByClass('ChordSymbol'), cs) def testNoChord(self): - from music21 import harmony - nc = harmony.NoChord() + nc = NoChord() self.assertEqual('none', nc.chordKind) self.assertEqual('N.C.', nc.chordKindStr) self.assertEqual('N.C.', nc.figure) - nc = harmony.NoChord('NC') + nc = NoChord('NC') self.assertEqual('none', nc.chordKind) self.assertEqual('NC', nc.chordKindStr) self.assertEqual('NC', nc.figure) - nc = harmony.NoChord('None') + nc = NoChord('None') self.assertEqual('none', nc.chordKind) self.assertEqual('None', nc.chordKindStr) self.assertEqual('None', nc.figure) - nc = harmony.NoChord(kind='none') + nc = NoChord(kind='none') self.assertEqual('none', nc.chordKind) self.assertEqual('N.C.', nc.chordKindStr) self.assertEqual('N.C.', nc.figure) - nc = harmony.NoChord(kindStr='No Chord') + nc = NoChord(kindStr='No Chord') self.assertEqual('none', nc.chordKind) self.assertEqual('No Chord', nc.chordKindStr) self.assertEqual('No Chord', nc.figure) - nc = harmony.NoChord('NC', kindStr='No Chord') + nc = NoChord('NC', kindStr='No Chord') self.assertEqual('none', nc.chordKind) self.assertEqual('No Chord', nc.chordKindStr) self.assertEqual('NC', nc.figure) - nc = harmony.NoChord(root='C', bass='E', kind='none') + nc = NoChord(root='C', bass='E', kind='none') self.assertEqual('N.C.', nc.chordKindStr) self.assertEqual('N.C.', nc.figure) @@ -2761,9 +2757,8 @@ def testNoChord(self): self.assertEqual(0, len(nc.pitches)) def testInvalidRoots(self): - from music21 import harmony with self.assertRaises(ValueError) as context: - harmony.ChordSymbol('H-7') + ChordSymbol('H-7') self.assertEqual( str(context.exception), @@ -2772,7 +2767,7 @@ def testInvalidRoots(self): with self.assertRaises(ValueError) as context: # noinspection SpellCheckingInspection - harmony.ChordSymbol('Garg7') + ChordSymbol('Garg7') self.assertEqual( str(context.exception), @@ -2782,9 +2777,8 @@ def testInvalidRoots(self): ) def testInvalidSymbol(self): - from music21 import harmony c = chord.Chord(('A#', 'C', 'E')) - cs = harmony.chordSymbolFromChord(c) + cs = chordSymbolFromChord(c) self.assertEqual(cs.figure, 'Chord Symbol Cannot Be Identified') def testRegexEdgeCases(self): @@ -3257,15 +3251,14 @@ def testUpdatePitchesFalse(self): class TestExternal(unittest.TestCase): def testReadInXML(self): - from music21 import harmony from music21 import corpus from music21 import stream testFile = corpus.parse('leadSheet/fosterBrownHair.xml') # testFile.show('text') - testFile = harmony.realizeChordSymbolDurations(testFile) + testFile = realizeChordSymbolDurations(testFile) # testFile.show() - chordSymbols = testFile.flatten().getElementsByClass(harmony.ChordSymbol) + chordSymbols = testFile.flatten().getElementsByClass(ChordSymbol) s = stream.Stream() for cS in chordSymbols: @@ -3277,7 +3270,6 @@ def testReadInXML(self): # self.assertEqual(len(csChords), 40) def testChordRealization(self): - from music21 import harmony from music21 import corpus from music21 import note from music21 import stream @@ -3288,8 +3280,8 @@ def testChordRealization(self): # tests, and adjust 57 accordingly testFile = corpus.parse('demos/ComprehensiveChordSymbolsTestFile.xml') - testFile = harmony.realizeChordSymbolDurations(testFile) - chords = testFile.flatten().getElementsByClass(harmony.ChordSymbol) + testFile = realizeChordSymbolDurations(testFile) + chords = testFile.flatten().getElementsByClass(ChordSymbol) # testFile.show() s = stream.Stream() # i = 0 diff --git a/music21/instrument.py b/music21/instrument.py index 0d819a0a9..16772e6d2 100644 --- a/music21/instrument.py +++ b/music21/instrument.py @@ -2600,82 +2600,79 @@ def testMusicXMLExport(self): # s3.show() def testPartitionByInstrumentA(self): - from music21 import instrument from music21 import stream # basic case of instruments in Parts s = stream.Score() p1 = stream.Part() - p1.append(instrument.Piano()) + p1.append(Piano()) p2 = stream.Part() - p2.append(instrument.Piccolo()) + p2.append(Piccolo()) s.insert(0, p1) s.insert(0, p2) - post = instrument.partitionByInstrument(s) + post = partitionByInstrument(s) self.assertEqual(len(post), 2) - self.assertEqual(len(post.flatten().getElementsByClass(instrument.Instrument)), 2) + self.assertEqual(len(post.flatten().getElementsByClass(Instrument)), 2) # post.show('t') # one Stream with multiple instruments s = stream.Stream() - s.insert(0, instrument.PanFlute()) - s.insert(20, instrument.ReedOrgan()) + s.insert(0, PanFlute()) + s.insert(20, ReedOrgan()) - post = instrument.partitionByInstrument(s) + post = partitionByInstrument(s) self.assertEqual(len(post), 2) - self.assertEqual(len(post[instrument.Instrument]), 2) + self.assertEqual(len(post[Instrument]), 2) # post.show('t') def testPartitionByInstrumentB(self): - from music21 import instrument from music21 import stream # basic case of instruments in Parts s = stream.Score() p1 = stream.Part() - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note(), 6) p2 = stream.Part() - p2.append(instrument.Piccolo()) + p2.append(Piccolo()) p2.repeatAppend(note.Note(), 12) s.insert(0, p1) s.insert(0, p2) - post = instrument.partitionByInstrument(s) + post = partitionByInstrument(s) self.assertEqual(len(post), 2) - self.assertEqual(len(post[instrument.Instrument]), 2) + self.assertEqual(len(post[Instrument]), 2) self.assertEqual(len(post.parts[0].notes), 6) self.assertEqual(len(post.parts[1].notes), 12) def testPartitionByInstrumentC(self): - from music21 import instrument from music21 import stream # basic case of instruments in Parts s = stream.Score() p1 = stream.Part() - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note('a'), 6) # will go in next available offset - p1.append(instrument.AcousticGuitar()) + p1.append(AcousticGuitar()) p1.repeatAppend(note.Note('b'), 3) p2 = stream.Part() - p2.append(instrument.Piccolo()) + p2.append(Piccolo()) p2.repeatAppend(note.Note('c'), 2) - p2.append(instrument.Flute()) + p2.append(Flute()) p2.repeatAppend(note.Note('d'), 4) s.insert(0, p1) s.insert(0, p2) - post = instrument.partitionByInstrument(s) + post = partitionByInstrument(s) self.assertEqual(len(post), 4) # 4 instruments - self.assertEqual(len(post[instrument.Instrument]), 4) + self.assertEqual(len(post[Instrument]), 4) self.assertEqual(post.parts[0].getInstrument().instrumentName, 'Piano') self.assertEqual(len(post.parts[0].notes), 6) self.assertEqual(post.parts[1].getInstrument().instrumentName, 'Acoustic Guitar') @@ -2689,34 +2686,33 @@ def testPartitionByInstrumentC(self): # post.show('t') def testPartitionByInstrumentD(self): - from music21 import instrument from music21 import stream # basic case of instruments in Parts s = stream.Score() p1 = stream.Part() - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note('a'), 6) # will go in next available offset - p1.append(instrument.AcousticGuitar()) + p1.append(AcousticGuitar()) p1.repeatAppend(note.Note('b'), 3) - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note('e'), 5) p2 = stream.Part() - p2.append(instrument.Piccolo()) + p2.append(Piccolo()) p2.repeatAppend(note.Note('c'), 2) - p2.append(instrument.Flute()) + p2.append(Flute()) p2.repeatAppend(note.Note('d'), 4) - p2.append(instrument.Piano()) + p2.append(Piano()) p2.repeatAppend(note.Note('f'), 1) s.insert(0, p1) s.insert(0, p2) - post = instrument.partitionByInstrument(s) + post = partitionByInstrument(s) self.assertEqual(len(post), 4) # 4 instruments - self.assertEqual(len(post[instrument.Instrument]), 4) + self.assertEqual(len(post[Instrument]), 4) # piano spans are joined together self.assertEqual(post.parts[0].getInstrument().instrumentName, 'Piano') self.assertEqual(len(post.parts[0].notes), 12) @@ -2728,32 +2724,31 @@ def testPartitionByInstrumentD(self): # post.show('t') def testPartitionByInstrumentE(self): - from music21 import instrument from music21 import stream # basic case of instruments in Parts # s = stream.Score() p1 = stream.Part() - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note('a'), 6) # will go in next available offset - p1.append(instrument.AcousticGuitar()) + p1.append(AcousticGuitar()) p1.repeatAppend(note.Note('b'), 3) - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note('e'), 5) - p1.append(instrument.Piccolo()) + p1.append(Piccolo()) p1.repeatAppend(note.Note('c'), 2) - p1.append(instrument.Flute()) + p1.append(Flute()) p1.repeatAppend(note.Note('d'), 4) - p1.append(instrument.Piano()) + p1.append(Piano()) p1.repeatAppend(note.Note('f'), 1) s = p1 - post = instrument.partitionByInstrument(s) + post = partitionByInstrument(s) self.assertEqual(len(post), 4) # 4 instruments - self.assertEqual(len(post[instrument.Instrument]), 4) + self.assertEqual(len(post[Instrument]), 4) # piano spans are joined together self.assertEqual(post.parts[0].getInstrument().instrumentName, 'Piano') @@ -2767,16 +2762,15 @@ def testPartitionByInstrumentE(self): [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 9.0, 10.0, 11.0, 12.0, 13.0, 20.0]) def testPartitionByInstrumentF(self): - from music21 import instrument from music21 import stream s1 = stream.Stream() - s1.append(instrument.AcousticGuitar()) + s1.append(AcousticGuitar()) s1.append(note.Note()) - s1.append(instrument.Tuba()) + s1.append(Tuba()) s1.append(note.Note()) - post = instrument.partitionByInstrument(s1) + post = partitionByInstrument(s1) self.assertEqual(len(post), 2) # 4 instruments # def testPartitionByInstrumentDocTest(self): @@ -2803,14 +2797,12 @@ def testPartitionByInstrumentF(self): # p.makeRests(fillGaps=True, inPlace=True) def testLanguageChoice(self): - from music21 import instrument - # fromString testString = 'Klarinette' # German name # Works when language not specified - self.assertEqual(instrument.fromString(testString).instrumentName, + self.assertEqual(fromString(testString).instrumentName, testString) workingExamples = ['german', # Works with correct language for the term @@ -2818,7 +2810,7 @@ def testLanguageChoice(self): ] for langStr in workingExamples: - instrName = instrument.fromString(testString, language=langStr).instrumentName + instrName = fromString(testString, language=langStr).instrumentName self.assertEqual(instrName, testString) failingExamples = ['french', # Error when the language doesn't match the term @@ -2827,20 +2819,20 @@ def testLanguageChoice(self): for langStr in failingExamples: self.assertRaises(InstrumentException, - instrument.fromString, + fromString, testString, language=langStr) # getAllNamesForInstrument - inst = instrument.Flute() + inst = Flute() # Working example - self.assertEqual(instrument.getAllNamesForInstrument(inst, - language=SearchLanguage.ABBREVIATION), + self.assertEqual(getAllNamesForInstrument(inst, + language=SearchLanguage.ABBREVIATION), {'abbreviation': ['fl']}) # Error for unsupported language self.assertRaises(InstrumentException, - instrument.getAllNamesForInstrument, + getAllNamesForInstrument, inst, language='finnish') diff --git a/music21/layout.py b/music21/layout.py index 11dcf60f0..580c8b232 100644 --- a/music21/layout.py +++ b/music21/layout.py @@ -1660,9 +1660,8 @@ def testGetStaffLayoutFromStaff(self): We have had problems with attributes disappearing. ''' from music21 import corpus - from music21 import layout lt = corpus.parse('demos/layoutTest.xml') - ls = layout.divideByPages(lt, fastMeasures=True) + ls = divideByPages(lt, fastMeasures=True) hiddenStaff = ls.pages[0].systems[3].staves[1] self.assertTrue(repr(hiddenStaff).endswith('Staff 11: p.1, sys.4, st.2>'), diff --git a/music21/note.py b/music21/note.py index aaed8c01d..1f1fd4f6a 100644 --- a/music21/note.py +++ b/music21/note.py @@ -2077,14 +2077,12 @@ def testSingle(self): ''' Need to test direct note creation w/o stream ''' - from music21 import note - a = note.Note('D-3') + a = Note('D-3') a.quarterLength = 2.25 if self.show: a.show() def testBasic(self): - from music21 import note from music21 import stream a = stream.Stream() @@ -2093,7 +2091,7 @@ def testBasic(self): ('d-3', 2.5), ('c#6', 3.25), ('a--5', 0.5), ('f#2', 1.75), ('g-3', (4 / 3)), ('d#6', (2 / 3)) ]: - b = note.Note() + b = Note() b.quarterLength = qLen b.name = pitchName # Pylint going crazy here diff --git a/music21/roman.py b/music21/roman.py index 146f99a06..51041220c 100644 --- a/music21/roman.py +++ b/music21/roman.py @@ -4332,9 +4332,8 @@ def testYieldRemoveA(self): c.remove(e) def testScaleDegreesA(self): - from music21 import roman k = key.Key('f#') # 3-sharps minor - rn = roman.RomanNumeral('V', k) + rn = RomanNumeral('V', k) self.assertEqual(str(rn.key), 'f# minor') self.assertEqual( str(rn.pitches), @@ -4348,8 +4347,7 @@ def testScaleDegreesA(self): ) def testNeapolitanAndHalfDiminished(self): - from music21 import roman - alteredChordHalfDim3rdInv = roman.RomanNumeral( + alteredChordHalfDim3rdInv = RomanNumeral( 'bii/o42', scale.MajorScale('F')) self.assertEqual( [str(p) for p in alteredChordHalfDim3rdInv.pitches], @@ -4361,162 +4359,157 @@ def testNeapolitanAndHalfDiminished(self): self.assertEqual(cn, 'half-diminished seventh chord') def testOmittedFifth(self): - from music21 import roman c = chord.Chord('A3 E-4 G-4') k = key.Key('b-') - rnDim7 = roman.romanNumeralFromChord(c, k) + rnDim7 = romanNumeralFromChord(c, k) self.assertEqual(rnDim7.figure, 'viio7') def testAllFormsOfVII(self): - from music21 import roman - def p(c): return ' '.join([x.nameWithOctave for x in c.pitches]) k = key.Key('c') - rn = roman.RomanNumeral('viio', k) + rn = RomanNumeral('viio', k) self.assertEqual(p(rn), 'B4 D5 F5') - rn = roman.RomanNumeral('viio6', k) + rn = RomanNumeral('viio6', k) self.assertEqual(p(rn), 'D4 F4 B4') - rn = roman.RomanNumeral('viio64', k) + rn = RomanNumeral('viio64', k) self.assertEqual(p(rn), 'F4 B4 D5') - rn = roman.RomanNumeral('vii', k) + rn = RomanNumeral('vii', k) self.assertEqual(p(rn), 'B4 D5 F#5') - rn = roman.RomanNumeral('vii6', k) + rn = RomanNumeral('vii6', k) self.assertEqual(p(rn), 'D4 F#4 B4') - rn = roman.RomanNumeral('vii64', k) + rn = RomanNumeral('vii64', k) self.assertEqual(p(rn), 'F#4 B4 D5') - rn = roman.RomanNumeral('viio7', k) + rn = RomanNumeral('viio7', k) self.assertEqual(p(rn), 'B4 D5 F5 A-5') - rn = roman.RomanNumeral('viio65', k) + rn = RomanNumeral('viio65', k) self.assertEqual(p(rn), 'D4 F4 A-4 B4') - rn = roman.RomanNumeral('viio43', k) + rn = RomanNumeral('viio43', k) self.assertEqual(p(rn), 'F4 A-4 B4 D5') - rn = roman.RomanNumeral('viio42', k) + rn = RomanNumeral('viio42', k) self.assertEqual(p(rn), 'A-4 B4 D5 F5') - rn = roman.RomanNumeral('vii/o7', k) + rn = RomanNumeral('vii/o7', k) self.assertEqual(p(rn), 'B4 D5 F5 A5') # noinspection SpellCheckingInspection - rn = roman.RomanNumeral('viiø65', k) + rn = RomanNumeral('viiø65', k) self.assertEqual(p(rn), 'D4 F4 A4 B4') # noinspection SpellCheckingInspection - rn = roman.RomanNumeral('viiø43', k) + rn = RomanNumeral('viiø43', k) self.assertEqual(p(rn), 'F4 A4 B4 D5') - rn = roman.RomanNumeral('vii/o42', k) + rn = RomanNumeral('vii/o42', k) self.assertEqual(p(rn), 'A4 B4 D5 F5') - rn = roman.RomanNumeral('VII', k) + rn = RomanNumeral('VII', k) self.assertEqual(p(rn), 'B-4 D5 F5') - rn = roman.RomanNumeral('VII6', k) + rn = RomanNumeral('VII6', k) self.assertEqual(p(rn), 'D4 F4 B-4') - rn = roman.RomanNumeral('VII64', k) + rn = RomanNumeral('VII64', k) self.assertEqual(p(rn), 'F4 B-4 D5') - rn = roman.RomanNumeral('bVII', k) + rn = RomanNumeral('bVII', k) self.assertEqual(p(rn), 'B--4 D-5 F-5') - rn = roman.RomanNumeral('bVII6', k) + rn = RomanNumeral('bVII6', k) self.assertEqual(p(rn), 'D-4 F-4 B--4') - rn = roman.RomanNumeral('bVII64', k) + rn = RomanNumeral('bVII64', k) self.assertEqual(p(rn), 'F-4 B--4 D-5') - rn = roman.RomanNumeral('bvii', k) + rn = RomanNumeral('bvii', k) self.assertEqual(p(rn), 'B-4 D-5 F5') - rn = roman.RomanNumeral('bvii6', k) + rn = RomanNumeral('bvii6', k) self.assertEqual(p(rn), 'D-4 F4 B-4') - rn = roman.RomanNumeral('bvii64', k) + rn = RomanNumeral('bvii64', k) self.assertEqual(p(rn), 'F4 B-4 D-5') - rn = roman.RomanNumeral('bviio', k) + rn = RomanNumeral('bviio', k) self.assertEqual(p(rn), 'B-4 D-5 F-5') - rn = roman.RomanNumeral('bviio6', k) + rn = RomanNumeral('bviio6', k) self.assertEqual(p(rn), 'D-4 F-4 B-4') - rn = roman.RomanNumeral('bviio64', k) + rn = RomanNumeral('bviio64', k) self.assertEqual(p(rn), 'F-4 B-4 D-5') - rn = roman.RomanNumeral('#VII', k) + rn = RomanNumeral('#VII', k) self.assertEqual(p(rn), 'B4 D#5 F#5') - rn = roman.RomanNumeral('#vii', k) + rn = RomanNumeral('#vii', k) self.assertEqual(p(rn), 'B#4 D#5 F##5') - rn = roman.RomanNumeral('VII+', k) + rn = RomanNumeral('VII+', k) self.assertEqual(p(rn), 'B-4 D5 F#5') def testAllFormsOfVI(self): - from music21 import roman - def p(c): return ' '.join([x.nameWithOctave for x in c.pitches]) k = key.Key('c') - rn = roman.RomanNumeral('vio', k) + rn = RomanNumeral('vio', k) self.assertEqual(p(rn), 'A4 C5 E-5') - rn = roman.RomanNumeral('vio6', k) + rn = RomanNumeral('vio6', k) self.assertEqual(p(rn), 'C4 E-4 A4') - rn = roman.RomanNumeral('vio64', k) + rn = RomanNumeral('vio64', k) self.assertEqual(p(rn), 'E-4 A4 C5') - rn = roman.RomanNumeral('vi', k) + rn = RomanNumeral('vi', k) self.assertEqual(p(rn), 'A4 C5 E5') - rn = roman.RomanNumeral('vi6', k) + rn = RomanNumeral('vi6', k) self.assertEqual(p(rn), 'C4 E4 A4') - rn = roman.RomanNumeral('vi64', k) + rn = RomanNumeral('vi64', k) self.assertEqual(p(rn), 'E4 A4 C5') - rn = roman.RomanNumeral('vio7', k) + rn = RomanNumeral('vio7', k) self.assertEqual(p(rn), 'A4 C5 E-5 G-5') - rn = roman.RomanNumeral('vio65', k) + rn = RomanNumeral('vio65', k) self.assertEqual(p(rn), 'C4 E-4 G-4 A4') - rn = roman.RomanNumeral('vio43', k) + rn = RomanNumeral('vio43', k) self.assertEqual(p(rn), 'E-4 G-4 A4 C5') - rn = roman.RomanNumeral('vio42', k) + rn = RomanNumeral('vio42', k) self.assertEqual(p(rn), 'G-4 A4 C5 E-5') - rn = roman.RomanNumeral('viø7', k) + rn = RomanNumeral('viø7', k) self.assertEqual(p(rn), 'A4 C5 E-5 G5') - rn = roman.RomanNumeral('vi/o65', k) + rn = RomanNumeral('vi/o65', k) self.assertEqual(p(rn), 'C4 E-4 G4 A4') - rn = roman.RomanNumeral('vi/o43', k) + rn = RomanNumeral('vi/o43', k) self.assertEqual(p(rn), 'E-4 G4 A4 C5') - rn = roman.RomanNumeral('viø42', k) + rn = RomanNumeral('viø42', k) self.assertEqual(p(rn), 'G4 A4 C5 E-5') - rn = roman.RomanNumeral('VI', k) + rn = RomanNumeral('VI', k) self.assertEqual(p(rn), 'A-4 C5 E-5') - rn = roman.RomanNumeral('VI6', k) + rn = RomanNumeral('VI6', k) self.assertEqual(p(rn), 'C4 E-4 A-4') - rn = roman.RomanNumeral('VI64', k) + rn = RomanNumeral('VI64', k) self.assertEqual(p(rn), 'E-4 A-4 C5') - rn = roman.RomanNumeral('bVI', k) + rn = RomanNumeral('bVI', k) self.assertEqual(p(rn), 'A--4 C-5 E--5') - rn = roman.RomanNumeral('bVI6', k) + rn = RomanNumeral('bVI6', k) self.assertEqual(p(rn), 'C-4 E--4 A--4') - rn = roman.RomanNumeral('bVI64', k) + rn = RomanNumeral('bVI64', k) self.assertEqual(p(rn), 'E--4 A--4 C-5') - rn = roman.RomanNumeral('bvi', k) + rn = RomanNumeral('bvi', k) self.assertEqual(p(rn), 'A-4 C-5 E-5') - rn = roman.RomanNumeral('bvi6', k) + rn = RomanNumeral('bvi6', k) self.assertEqual(p(rn), 'C-4 E-4 A-4') - rn = roman.RomanNumeral('bvi64', k) + rn = RomanNumeral('bvi64', k) self.assertEqual(p(rn), 'E-4 A-4 C-5') - rn = roman.RomanNumeral('bvio', k) + rn = RomanNumeral('bvio', k) self.assertEqual(p(rn), 'A-4 C-5 E--5') - rn = roman.RomanNumeral('bvio6', k) + rn = RomanNumeral('bvio6', k) self.assertEqual(p(rn), 'C-4 E--4 A-4') - rn = roman.RomanNumeral('bvio64', k) + rn = RomanNumeral('bvio64', k) self.assertEqual(p(rn), 'E--4 A-4 C-5') - rn = roman.RomanNumeral('#VI', k) + rn = RomanNumeral('#VI', k) self.assertEqual(p(rn), 'A4 C#5 E5') - rn = roman.RomanNumeral('#vi', k) + rn = RomanNumeral('#vi', k) self.assertEqual(p(rn), 'A#4 C#5 E#5') - rn = roman.RomanNumeral('VI+', k) + rn = RomanNumeral('VI+', k) self.assertEqual(p(rn), 'A-4 C5 E5') def testRomanNumeralFromChordRaised67(self): @@ -4529,8 +4522,6 @@ def testRomanNumeralFromChordRaised67(self): This test was AI-assisted (Claude). ''' - from music21 import roman - k = key.Key('c') for pitchNames, expectedFigure, expectedRN in [ (('A-4', 'C5', 'E-5'), 'bVI', 'VI'), @@ -4545,16 +4536,16 @@ def testRomanNumeralFromChordRaised67(self): ]: with self.subTest(pitches=pitchNames): c = chord.Chord(pitchNames) - rn = roman.romanNumeralFromChord(c, k) + rn = romanNumeralFromChord(c, k) self.assertEqual(rn.figure, expectedFigure) self.assertEqual(rn.romanNumeral, expectedRN) # the figure must round-trip to the same pitch names under # the convention that romanNumeralFromChord itself uses. - roundTrip = roman.RomanNumeral( + roundTrip = RomanNumeral( rn.figure, k, - sixthMinor=roman.Minor67Default.CAUTIONARY, - seventhMinor=roman.Minor67Default.CAUTIONARY, + sixthMinor=Minor67Default.CAUTIONARY, + seventhMinor=Minor67Default.CAUTIONARY, ) self.assertEqual( [p_.name for p_ in roundTrip.pitches], @@ -4562,8 +4553,6 @@ def testRomanNumeralFromChordRaised67(self): ) def testAugmented(self): - from music21 import roman - def p(c): return ' '.join([x.nameWithOctave for x in c.pitches]) @@ -4573,7 +4562,7 @@ def test_numeral(country, figure_list, result, key_in='a'): for kStr in (key_in, key_in.upper()): key_obj = key.Key(kStr) rn_str = country + with_plus + figure - rn = roman.RomanNumeral(rn_str, key_obj) + rn = RomanNumeral(rn_str, key_obj) self.assertEqual(p(rn), result) @@ -4640,14 +4629,13 @@ def testSetFigureAgain(self): self.assertEqual(sharp_four.pitches, pitches_before) def testZeroForDiminished(self): - from music21 import roman - rn = roman.RomanNumeral('vii07', 'c') + rn = RomanNumeral('vii07', 'c') self.assertEqual([p.name for p in rn.pitches], ['B', 'D', 'F', 'A-']) - rn = roman.RomanNumeral('vii/07', 'c') + rn = RomanNumeral('vii/07', 'c') self.assertEqual([p.name for p in rn.pitches], ['B', 'D', 'F', 'A']) # However, when there is a '10' somewhere in the figure, don't replace # the 0 (this occurs in DCML corpora) - rn = roman.RomanNumeral('V7[add10]', 'c') + rn = RomanNumeral('V7[add10]', 'c') self.assertEqual([p.name for p in rn.pitches], ['G', 'B-', 'B', 'D', 'F']) def testIII7(self): diff --git a/music21/romanText/clercqTemperley.py b/music21/romanText/clercqTemperley.py index e3af1d3b3..1fa06a92d 100644 --- a/music21/romanText/clercqTemperley.py +++ b/music21/romanText/clercqTemperley.py @@ -1141,8 +1141,7 @@ class TestExternal(unittest.TestCase): show = True def testB(self) -> None: - from music21.romanText import clercqTemperley - s = clercqTemperley.CTSong(BlitzkriegBopCT) + s = CTSong(BlitzkriegBopCT) partObj = s.toPart() if self.show: partObj.show() diff --git a/music21/romanText/translate.py b/music21/romanText/translate.py index e02953481..0add26309 100644 --- a/music21/romanText/translate.py +++ b/music21/romanText/translate.py @@ -1575,7 +1575,6 @@ def testNoChord(self): def testUnprocessed(self): from music21 import converter - from music21.romanText import translate src = '''Note: Hello m1 G: IV || b3 d: III b4 NC varM1 I @@ -1583,7 +1582,7 @@ def testUnprocessed(self): ''' s = converter.parse(src, format='romantext') p = s.parts[0] - unprocessedElements = p[translate.RomanTextUnprocessedMetadata] + unprocessedElements = p[RomanTextUnprocessedMetadata] self.assertEqual(len(unprocessedElements), 3) note1, var1, note2 = unprocessedElements self.assertEqual(note1.tag, 'Note') @@ -1594,19 +1593,18 @@ def testUnprocessed(self): self.assertIn(' I', var1.data) def testUnprocessedWithAnacrusis(self): - from music21.romanText import translate src = ''' Time Signature: 4/4 m0 b4 f: i Note: Internal Note field after anacrusis. m1 V ''' - s = translate.romanTextToStreamScore(src) + s = romanTextToStreamScore(src) p = s.parts[0] self.assertEqual(len(p), 3) self.assertIsInstance(p[0], stream.Measure) self.assertEqual(p[0].paddingLeft, 3.0) - self.assertIsInstance(p[1], translate.RomanTextUnprocessedMetadata) + self.assertIsInstance(p[1], RomanTextUnprocessedMetadata) self.assertEqual(p[1].offset, 0.0) self.assertEqual(p[1].data, 'Internal Note field after anacrusis.') self.assertIsInstance(p[2], stream.Measure) diff --git a/music21/sieve.py b/music21/sieve.py index 8a35fa31e..b999fa5fc 100644 --- a/music21/sieve.py +++ b/music21/sieve.py @@ -2097,22 +2097,18 @@ def testSieve(self): '{-{13@3|13@5|13@7|13@9}&11@2}|{-{11@4|11@8}&13@9}|{13@0|13@1|13@6}') def testPitchSieveA(self): - from music21 import sieve - - s1 = sieve.PitchSieve('3@0|7@0', 'c2', 'c6') + s1 = PitchSieve('3@0|7@0', 'c2', 'c6') self.assertEqual(self.pitchOut(s1()), '[C2, E-2, F#2, G2, A2, C3, D3, E-3, F#3, A3, C4, E-4, ' 'E4, F#4, A4, B4, C5, E-5, F#5, A5, C6]') - s1 = sieve.PitchSieve('3@0|7@0', 'c2', 'c6', eld=2) + s1 = PitchSieve('3@0|7@0', 'c2', 'c6', eld=2) self.assertEqual(self.pitchOut(s1()), '[C2, D2, F#2, C3, E3, F#3, C4, F#4, C5, F#5, G#5, C6]') def testPitchSieveB(self): - from music21 import sieve - # microtonal elds - s1 = sieve.PitchSieve('1@0', 'c2', 'c6', eld=0.5) + s1 = PitchSieve('1@0', 'c2', 'c6', eld=0.5) self.assertEqual(self.pitchOut(s1()), '[C2, C~2, C#2, C#~2, D2, D~2, E-2, E`2, E2, E~2, F2, F~2, F#2, ' 'F#~2, G2, G~2, G#2, G#~2, A2, A~2, B-2, B`2, B2, B~2, C3, C~3, C#3, ' @@ -2122,7 +2118,7 @@ def testPitchSieveB(self): 'B`4, B4, B~4, C5, C~5, C#5, C#~5, D5, D~5, E-5, E`5, E5, E~5, F5, F~5, ' 'F#5, F#~5, G5, G~5, G#5, G#~5, A5, A~5, B-5, B`5, B5, B~5, C6]') - s1 = sieve.PitchSieve('3@0', 'c2', 'c6', eld=0.5) + s1 = PitchSieve('3@0', 'c2', 'c6', eld=0.5) self.assertEqual(self.pitchOut(s1()), '[C2, C#~2, E-2, E~2, F#2, G~2, A2, B`2, C3, C#~3, E-3, E~3, F#3, G~3, ' 'A3, B`3, C4, C#~4, E-4, E~4, F#4, G~4, A4, B`4, C5, C#~5, E-5, E~5, F#5, ' diff --git a/music21/spanner.py b/music21/spanner.py index 681f7e03c..6a04bd498 100644 --- a/music21/spanner.py +++ b/music21/spanner.py @@ -2404,10 +2404,9 @@ def testBasic(self): def testSpannerAnchorRepr(self): from music21 import stream - from music21 import spanner # SpannerAnchor with no activeSite - sa1 = spanner.SpannerAnchor() + sa1 = SpannerAnchor() self.assertEqual(repr(sa1), '') # SpannerAnchor with activeSite, but no duration @@ -2420,19 +2419,17 @@ def testSpannerAnchorRepr(self): self.assertEqual(repr(sa1), '') def testSpannerRepr(self): - from music21 import spanner - su1 = spanner.Slur() + su1 = Slur() self.assertEqual(repr(su1), '') def testSpannerFill(self): from music21 import stream from music21 import note - from music21 import spanner theNotes = [note.Note('A'), note.Note('B'), note.Note('C'), note.Note('D')] m = stream.Measure(theNotes) # Spanner with no fillElementTypes - sp = spanner.Spanner(theNotes[0], theNotes[3]) + sp = Spanner(theNotes[0], theNotes[3]) sp.fill(m) # should not have done anything noFillElements = [theNotes[0], theNotes[3]] @@ -2441,7 +2438,7 @@ def testSpannerFill(self): self.assertIs(el, noFillElements[i]) # Ottava with filledStatus == True - ott1 = spanner.Ottava(noFillElements) + ott1 = Ottava(noFillElements) ott1.filledStatus = True # pretend it has already been filled ott1.fill(m) # should not have done anything @@ -2459,20 +2456,20 @@ def testSpannerFill(self): self.assertIs(el, theNotes[i]) # Ottava with no elements - ott2 = spanner.Ottava() + ott2 = Ottava() ott2.fill(m) self.assertEqual(len(ott2), 0) # Ottava with only element not in searchStream expectedElements = [note.Note('E')] - ott3 = spanner.Ottava(expectedElements) + ott3 = Ottava(expectedElements) ott3.fill(m) self.assertEqual(len(ott3), 1) self.assertIs(ott3.getFirst(), expectedElements[0]) # Ottava with start element not in searchStream, end element is expectedElements = [note.Note('F'), m.notes[0]] - ott4 = spanner.Ottava(expectedElements) + ott4 = Ottava(expectedElements) ott4.fill(m) self.assertEqual(len(ott4), 2) for i, el in enumerate(ott4.getSpannedElements()): @@ -2480,40 +2477,38 @@ def testSpannerFill(self): # Ottava with endElement not in searchStream, startElement is expectedElements = [m.notes[0], note.Note('G')] - ott5 = spanner.Ottava(expectedElements) + ott5 = Ottava(expectedElements) ott5.fill(m) self.assertEqual(len(ott5), 2) for i, el in enumerate(ott5.getSpannedElements()): self.assertIs(el, expectedElements[i]) def testSpannerBundle(self): - from music21 import spanner from music21 import stream - su1 = spanner.Slur() + su1 = Slur() su1.idLocal = 1 - su2 = spanner.Slur() + su2 = Slur() su2.idLocal = 2 - sb = spanner.SpannerBundle() + sb = SpannerBundle() sb.append(su1) sb.append(su2) self.assertEqual(len(sb), 2) self.assertEqual(sb[0], su1) self.assertEqual(sb[1], su2) - su3 = spanner.Slur() - su4 = spanner.Slur() + su3 = Slur() + su4 = Slur() s = stream.Stream() s.append(su3) s.append(su4) - sb2 = spanner.SpannerBundle(list(s)) + sb2 = SpannerBundle(list(s)) self.assertEqual(len(sb2), 2) self.assertEqual(sb2[0], su3) self.assertEqual(sb2[1], su4) def testDeepcopySpanner(self): - from music21 import spanner from music21 import note # how slurs might be defined @@ -2535,7 +2530,7 @@ def testDeepcopySpanner(self): self.assertEqual(n1.getSpannerSites(), [su1, su2]) self.assertEqual(n3.getSpannerSites(), [su1, su2]) - sb1 = spanner.SpannerBundle([su1, su2]) + sb1 = SpannerBundle([su1, su2]) sb2 = copy.deepcopy(sb1) self.assertEqual(sb1[0].getSpannedElements(), [n1, n3]) self.assertEqual(sb2[0].getSpannedElements(), [n1, n3]) @@ -2544,7 +2539,6 @@ def testDeepcopySpanner(self): def testReplaceSpannedElement(self): from music21 import note - from music21 import spanner n1 = note.Note() n2 = note.Note() @@ -2552,7 +2546,7 @@ def testReplaceSpannedElement(self): n4 = note.Note() n5 = note.Note() - su1 = spanner.Slur() + su1 = Slur() su1.addSpannedElements([n1, n3]) self.assertEqual(su1.getSpannedElements(), [n1, n3]) @@ -2570,10 +2564,10 @@ def testReplaceSpannedElement(self): self.assertEqual(n2.getSpannerSites(), []) self.assertEqual(n1.getSpannerSites(), [su1]) - su2 = spanner.Slur() + su2 = Slur() su2.addSpannedElements([n3, n4]) - su3 = spanner.Slur() + su3 = Slur() su3.addSpannedElements([n4, n5]) # n1a = note.Note() @@ -2582,7 +2576,7 @@ def testReplaceSpannedElement(self): n4a = note.Note() # n5a = note.Note() - sb1 = spanner.SpannerBundle([su1, su2, su3]) + sb1 = SpannerBundle([su1, su2, su3]) self.assertEqual(len(sb1), 3) self.assertEqual(list(sb1), [su1, su2, su3]) @@ -2603,18 +2597,16 @@ def testReplaceSpannedElement(self): self.assertEqual(sb1[2].getSpannedElements(), [n4a, n5]) def testRepeatBracketA(self): - from music21 import spanner from music21 import stream m1 = stream.Measure() - rb1 = spanner.RepeatBracket(m1) + rb1 = RepeatBracket(m1) # if added again; it is not really added, it simply is ignored rb1.addSpannedElements(m1) self.assertEqual(len(rb1), 1) def testRepeatBracketB(self): from music21 import note - from music21 import spanner from music21 import stream from music21 import bar @@ -2630,19 +2622,19 @@ def testRepeatBracketB(self): m3.repeatAppend(note.Note('g#4'), 4) m3.rightBarline = bar.Repeat(direction='end') p.append(m3) - p.append(spanner.RepeatBracket(m3, number=1)) + p.append(RepeatBracket(m3, number=1)) m4 = stream.Measure() m4.repeatAppend(note.Note('a4'), 4) m4.rightBarline = bar.Repeat(direction='end') p.append(m4) - p.append(spanner.RepeatBracket(m4, number=2)) + p.append(RepeatBracket(m4, number=2)) m5 = stream.Measure() m5.repeatAppend(note.Note('b4'), 4) m5.rightBarline = bar.Repeat(direction='end') p.append(m5) - p.append(spanner.RepeatBracket(m5, number=3)) + p.append(RepeatBracket(m5, number=3)) m6 = stream.Measure() m6.repeatAppend(note.Note('c#5'), 4) @@ -2654,7 +2646,6 @@ def testRepeatBracketB(self): # noinspection DuplicatedCode def testRepeatBracketC(self): from music21 import note - from music21 import spanner from music21 import stream from music21 import bar @@ -2671,7 +2662,7 @@ def testRepeatBracketC(self): m3.repeatAppend(note.Note('g#4'), 4) m3.rightBarline = bar.Repeat(direction='end') p.append(m3) - rb1 = spanner.RepeatBracket(number=1) + rb1 = RepeatBracket(number=1) rb1.addSpannedElements(m2, m3) self.assertEqual(len(rb1), 2) p.insert(0, rb1) @@ -2680,7 +2671,7 @@ def testRepeatBracketC(self): m4.repeatAppend(note.Note('a4'), 4) m4.rightBarline = bar.Repeat(direction='end') p.append(m4) - p.append(spanner.RepeatBracket(m4, number=2)) + p.append(RepeatBracket(m4, number=2)) m5 = stream.Measure() m5.repeatAppend(note.Note('b4'), 4) @@ -2699,7 +2690,6 @@ def testRepeatBracketC(self): # noinspection DuplicatedCode def testRepeatBracketD(self): from music21 import note - from music21 import spanner from music21 import stream from music21 import bar @@ -2716,7 +2706,7 @@ def testRepeatBracketD(self): m3.repeatAppend(note.Note('g#4'), 4) m3.rightBarline = bar.Repeat(direction='end') p.append(m3) - rb1 = spanner.RepeatBracket(number=1) + rb1 = RepeatBracket(number=1) rb1.addSpannedElements(m2, m3) self.assertEqual(len(rb1), 2) p.insert(0, rb1) @@ -2730,7 +2720,7 @@ def testRepeatBracketD(self): m5.rightBarline = bar.Repeat(direction='end') p.append(m5) - rb2 = spanner.RepeatBracket(number=2) + rb2 = RepeatBracket(number=2) rb2.addSpannedElements(m4, m5) self.assertEqual(len(rb2), 2) p.insert(0, rb2) @@ -2748,7 +2738,7 @@ def testRepeatBracketD(self): m8.rightBarline = bar.Repeat(direction='end') p.append(m8) - rb3 = spanner.RepeatBracket(number=3) + rb3 = RepeatBracket(number=3) rb3.addSpannedElements(m6, m8) self.assertEqual(len(rb3), 2) p.insert(0, rb3) @@ -2770,7 +2760,7 @@ def testRepeatBracketD(self): m12.rightBarline = bar.Repeat(direction='end') p.append(m12) - rb4 = spanner.RepeatBracket(number=4) + rb4 = RepeatBracket(number=4) rb4.addSpannedElements(m9, m10, m11, m12) self.assertEqual(len(rb4), 4) p.insert(0, rb4) @@ -2799,7 +2789,6 @@ def testRepeatBracketD(self): def testRepeatBracketE(self): from music21 import note - from music21 import spanner from music21 import stream from music21 import bar @@ -2815,19 +2804,19 @@ def testRepeatBracketE(self): m3.repeatAppend(note.Note('g#4'), 1) m3.rightBarline = bar.Repeat(direction='end') p.append(m3) - p.append(spanner.RepeatBracket(m3, number=1)) + p.append(RepeatBracket(m3, number=1)) m4 = stream.Measure(number=4) m4.repeatAppend(note.Note('a4'), 1) m4.rightBarline = bar.Repeat(direction='end') p.append(m4) - p.append(spanner.RepeatBracket(m4, number=2)) + p.append(RepeatBracket(m4, number=2)) m5 = stream.Measure(number=5) m5.repeatAppend(note.Note('b4'), 1) m5.rightBarline = bar.Repeat(direction='end') p.append(m5) - p.append(spanner.RepeatBracket(m5, number=3)) + p.append(RepeatBracket(m5, number=3)) m6 = stream.Measure(number=6) m6.repeatAppend(note.Note('c#5'), 1) @@ -2868,7 +2857,6 @@ def testOttavaShiftA(self): from music21 import stream from music21 import note from music21 import chord - from music21.spanner import Ottava # need to do it this way for classSet s = stream.Stream() s.repeatAppend(chord.Chord(['c-3', 'g4']), 12) # s.repeatAppend(note.Note(), 12) @@ -2920,10 +2908,9 @@ def testOttavaShiftB(self): ''' from music21 import stream from music21 import note - from music21 import spanner s = stream.Stream() n = note.Note('c4') - sp = spanner.Ottava(n) + sp = Ottava(n) s.append(n) s.append(sp) # s.show() @@ -2972,15 +2959,14 @@ def testCrescendoA(self): def testLineA(self): from music21 import stream from music21 import note - from music21 import spanner s = stream.Stream() s.repeatAppend(note.Note(), 12) n1 = s.notes[0] n2 = s.notes[len(s.notes) // 2] n3 = s.notes[-1] - sp1 = spanner.Line(n1, n2, startTick='up', lineType='dotted') - sp2 = spanner.Line(n2, n3, startTick='down', lineType='dashed', + sp1 = Line(n1, n2, startTick='up', lineType='dotted') + sp2 = Line(n2, n3, startTick='down', lineType='dashed', endHeight=40) s.append(sp1) s.append(sp2) @@ -2992,7 +2978,6 @@ def testLineA(self): def testLineB(self): from music21 import stream from music21 import note - from music21 import spanner s = stream.Stream() s.repeatAppend(note.Note(), 12) @@ -3002,8 +2987,8 @@ def testLineB(self): n3 = s.notes[0] n4 = s.notes[2] - sp1 = spanner.Line(n1, n2, startTick='up', endTick='down', lineType='solid') - sp2 = spanner.Line(n3, n4, startTick='arrow', endTick='none', lineType='solid') + sp1 = Line(n1, n2, startTick='up', endTick='down', lineType='solid') + sp2 = Line(n3, n4, startTick='arrow', endTick='none', lineType='solid') s.append(sp1) s.append(sp2) @@ -3019,7 +3004,6 @@ def testLineB(self): def testGlissandoA(self): from music21 import stream from music21 import note - from music21 import spanner s = stream.Stream() s.repeatAppend(note.Note(), 3) @@ -3030,8 +3014,8 @@ def testGlissandoA(self): n1 = s.notes[0] n2 = s.notes[len(s.notes) // 2] n3 = s.notes[-1] - sp1 = spanner.Glissando(n1, n2) - sp2 = spanner.Glissando(n2, n3) + sp1 = Glissando(n1, n2) + sp2 = Glissando(n2, n3) sp2.lineType = 'dashed' s.append(sp1) s.append(sp2) @@ -3045,7 +3029,6 @@ def testGlissandoA(self): def testGlissandoB(self): from music21 import stream from music21 import note - from music21 import spanner s = stream.Stream() s.repeatAppend(note.Note(), 12) @@ -3055,7 +3038,7 @@ def testGlissandoB(self): # note: this does not support glissandi between non-adjacent notes n1 = s.notes[0] n2 = s.notes[1] - sp1 = spanner.Glissando(n1, n2) + sp1 = Glissando(n1, n2) sp1.lineType = 'solid' sp1.label = 'gliss.' s.append(sp1) @@ -3086,7 +3069,6 @@ def testGlissandoB(self): def testOneElementSpanners(self): from music21 import note - from music21.spanner import Spanner n1 = note.Note() sp = Spanner() @@ -3099,7 +3081,6 @@ def testOneElementSpanners(self): def testRemoveSpanners(self): from music21 import stream from music21 import note - from music21.spanner import Spanner, Slur p = stream.Part() m1 = stream.Measure() @@ -3123,7 +3104,6 @@ def testFreezeSpanners(self): from music21 import stream from music21 import note from music21 import converter - from music21.spanner import Slur p = stream.Part() m1 = stream.Measure() @@ -3143,7 +3123,6 @@ def testFreezeSpanners(self): def testDeepcopyJustSpannerAndNotes(self): from music21 import note from music21 import clef - from music21.spanner import Spanner n1 = note.Note('g') n2 = note.Note('f#') @@ -3162,7 +3141,6 @@ def testDeepcopySpannerInStreamNotNotes(self): from music21 import note from music21 import clef from music21 import stream - from music21.spanner import Spanner n1 = note.Note('g') n2 = note.Note('f#') @@ -3185,7 +3163,6 @@ def testDeepcopyNotesInStreamNotSpanner(self): from music21 import note from music21 import clef from music21 import stream - from music21.spanner import Spanner n1 = note.Note('g') n2 = note.Note('f#') @@ -3209,7 +3186,6 @@ def testDeepcopyNotesInStreamNotSpanner(self): def testDeepcopyNotesAndSpannerInStream(self): from music21 import note from music21 import stream - from music21.spanner import Spanner n1 = note.Note('G4') n2 = note.Note('F#4') @@ -3234,7 +3210,6 @@ def testDeepcopyNotesAndSpannerInStream(self): def testDeepcopyStreamWithSpanners(self): from music21 import note from music21 import stream - from music21.spanner import Slur n1 = note.Note() su1 = Slur((n1,)) @@ -3258,7 +3233,6 @@ def testDeepcopyStreamWithSpanners(self): def testGetSpannedElementIds(self): from music21 import note - from music21.spanner import Spanner n1 = note.Note('g') n2 = note.Note('f#') diff --git a/music21/stream/iterator.py b/music21/stream/iterator.py index 95118c114..3686214b2 100644 --- a/music21/stream/iterator.py +++ b/music21/stream/iterator.py @@ -2132,8 +2132,6 @@ def testCurrentHierarchyOffsetReset(self): def testAddingFiltersMidRecursiveIteration(self): from music21 import stream - # noinspection PyUnresolvedReferences - from music21.stream.iterator import RecursiveIterator as ImportedRecursiveIterator m = stream.Measure() r = note.Rest() n = note.Note() @@ -2149,7 +2147,7 @@ def testAddingFiltersMidRecursiveIteration(self): self.assertIs(p0, p) child = sIter.childRecursiveIterator - self.assertIsInstance(child, ImportedRecursiveIterator) + self.assertIsInstance(child, RecursiveIterator) diff --git a/music21/tablature.py b/music21/tablature.py index cf529a6d8..2638e8771 100644 --- a/music21/tablature.py +++ b/music21/tablature.py @@ -363,8 +363,7 @@ def testStupidFretNote(self): self.assertEqual(FretNote().string, None) def testFretNoteWeirdRepr(self): - from music21 import tablature - weirdFretNote = tablature.FretNote(6, 133) + weirdFretNote = FretNote(6, 133) expectedRepr = '' diff --git a/music21/tempo.py b/music21/tempo.py index 6eb003b83..9cf0bb0bd 100644 --- a/music21/tempo.py +++ b/music21/tempo.py @@ -1370,8 +1370,7 @@ def testUnicode(self): self.assertEqual(mm.number, 144) def testTempoTextStyle(self): - from music21 import tempo - tm = tempo.TempoText('adagio') + tm = TempoText('adagio') self.assertEqual(tm.style.absoluteY, 45) self.assertEqual(tm.style.fontStyle, 'bold') tm.style.absoluteY = 33 @@ -1435,8 +1434,7 @@ def testTempoTextStyle(self): self.assertIs(tm.style, te4.style) # check for linked styles def testMetronomeMarkA(self): - from music21 import tempo - mm = tempo.MetronomeMark() + mm = MetronomeMark() mm.number = 56 # should implicitly set text self.assertEqual(mm.text, 'adagio') self.assertTrue(mm.textImplicit) @@ -1447,7 +1445,7 @@ def testMetronomeMarkA(self): self.assertEqual(mm.referent.quarterLength, 1.0) # setting the text first - mm = tempo.MetronomeMark() + mm = MetronomeMark() mm.text = 'presto' mm.referent = duration.Duration(3.0) self.assertEqual(mm.text, 'presto') @@ -1480,13 +1478,12 @@ def testMetronomeMarkB(self): self.assertFalse(mm.textImplicit) def testMetronomeModulationA(self): - from music21 import tempo # need to create a mm without a speed # want to say that an eighth is becoming the speed of a sixteenth - mm1 = tempo.MetronomeMark(referent=0.5, number=120) - mm2 = tempo.MetronomeMark(referent='16th') + mm1 = MetronomeMark(referent=0.5, number=120) + mm2 = MetronomeMark(referent='16th') - mmod1 = tempo.MetricModulation() + mmod1 = MetricModulation() mmod1.oldMetronome = mm1 mmod1.newMetronome = mm2 @@ -1497,8 +1494,8 @@ def testMetronomeModulationA(self): + '>') # we can get the same result by using setEqualityByReferent() - mm1 = tempo.MetronomeMark(referent=0.5, number=120) - mmod1 = tempo.MetricModulation() + mm1 = MetronomeMark(referent=0.5, number=120) + mmod1 = MetricModulation() mmod1.oldMetronome = mm1 # will automatically set right mm, as presently is None mmod1.setOtherByReferent(referent='16th') @@ -1512,7 +1509,6 @@ def testMetronomeModulationA(self): self.assertEqual(mmod1.newMetronome.getQuarterBPM(), 30.0) def testGetPreviousMetronomeMarkA(self): - from music21 import tempo from music21 import stream # test getting basic metronome marks @@ -1520,9 +1516,9 @@ def testGetPreviousMetronomeMarkA(self): m1 = stream.Measure() m1.repeatAppend(note.Note(quarterLength=1), 4) m2 = copy.deepcopy(m1) - mm1 = tempo.MetronomeMark(number=56, referent=0.25) + mm1 = MetronomeMark(number=56, referent=0.25) m1.insert(0, mm1) - mm2 = tempo.MetronomeMark(number=150, referent=0.5) + mm2 = MetronomeMark(number=150, referent=0.5) m2.insert(0, mm2) p.append([m1, m2]) self.assertEqual(str(mm2.getPreviousMetronomeMark()), @@ -1530,7 +1526,6 @@ def testGetPreviousMetronomeMarkA(self): # p.show() def testGetPreviousMetronomeMarkB(self): - from music21 import tempo from music21 import stream # test using a tempo text, will return a default metronome mark if possible @@ -1538,9 +1533,9 @@ def testGetPreviousMetronomeMarkB(self): m1 = stream.Measure() m1.repeatAppend(note.Note(quarterLength=1), 4) m2 = copy.deepcopy(m1) - mm1 = tempo.TempoText('slow') + mm1 = TempoText('slow') m1.insert(0, mm1) - mm2 = tempo.MetronomeMark(number=150, referent=0.5) + mm2 = MetronomeMark(number=150, referent=0.5) m2.insert(0, mm2) p.append([m1, m2]) self.assertEqual(str(mm2.getPreviousMetronomeMark()), @@ -1548,7 +1543,6 @@ def testGetPreviousMetronomeMarkB(self): # p.show() def testGetPreviousMetronomeMarkC(self): - from music21 import tempo from music21 import stream # test using a metric modulation @@ -1558,15 +1552,15 @@ def testGetPreviousMetronomeMarkC(self): m2 = copy.deepcopy(m1) m3 = copy.deepcopy(m2) - mm1 = tempo.MetronomeMark('slow') + mm1 = MetronomeMark('slow') m1.insert(0, mm1) - mm2 = tempo.MetricModulation() - mm2.oldMetronome = tempo.MetronomeMark(referent=1, number=52) + mm2 = MetricModulation() + mm2.oldMetronome = MetronomeMark(referent=1, number=52) mm2.setOtherByReferent(referent='16th') m2.insert(0, mm2) - mm3 = tempo.MetronomeMark(number=150, referent=0.5) + mm3 = MetronomeMark(number=150, referent=0.5) m3.insert(0, mm3) p.append([m1, m2, m3]) @@ -1580,17 +1574,16 @@ def testSetReferentA(self): Test setting referents directly via context searches. ''' from music21 import stream - from music21 import tempo p = stream.Part() m1 = stream.Measure() m1.repeatAppend(note.Note(quarterLength=1), 4) m2 = copy.deepcopy(m1) m3 = copy.deepcopy(m2) - mm1 = tempo.MetronomeMark(number=92) + mm1 = MetronomeMark(number=92) m1.insert(0, mm1) - mm2 = tempo.MetricModulation() + mm2 = MetricModulation() m2.insert(0, mm2) p.append([m1, m2, m3]) @@ -1604,15 +1597,14 @@ def testSetReferentA(self): # p.show() def testSetReferentB(self): - from music21 import tempo from music21 import stream s = stream.Stream() - mm1 = tempo.MetronomeMark(number=60) + mm1 = MetronomeMark(number=60) s.append(mm1) s.repeatAppend(note.Note(quarterLength=1), 2) s.repeatAppend(note.Note(quarterLength=0.5), 4) - mmod1 = tempo.MetricModulation() + mmod1 = MetricModulation() mmod1.oldReferent = 0.5 # can use Duration objects mmod1.newReferent = 'quarter' # can use Duration objects s.append(mmod1) @@ -1626,7 +1618,7 @@ def testSetReferentB(self): s.append(note.Note()) s.repeatAppend(note.Note(quarterLength=1.5), 2) - mmod2 = tempo.MetricModulation() + mmod2 = MetricModulation() mmod2.oldReferent = 1.5 mmod2.newReferent = 'quarter' # can use Duration objects s.append(mmod2) @@ -1640,15 +1632,14 @@ def testSetReferentB(self): # s.show() def testSetReferentC(self): - from music21 import tempo from music21 import stream s = stream.Stream() - mm1 = tempo.MetronomeMark(number=60) + mm1 = MetronomeMark(number=60) s.append(mm1) s.repeatAppend(note.Note(quarterLength=1), 2) s.repeatAppend(note.Note(quarterLength=0.5), 4) - mmod1 = tempo.MetricModulation() + mmod1 = MetricModulation() s.append(mmod1) mmod1.oldReferent = 0.5 # can use Duration objects mmod1.newReferent = 'quarter' # can use Duration objects @@ -1661,7 +1652,7 @@ def testSetReferentC(self): s.append(note.Note()) s.repeatAppend(note.Note(quarterLength=1.5), 2) - mmod2 = tempo.MetricModulation() + mmod2 = MetricModulation() s.append(mmod2) mmod2.oldReferent = 1.5 mmod2.newReferent = 'quarter' # can use Duration objects @@ -1674,15 +1665,14 @@ def testSetReferentC(self): # s.show() def testSetReferentD(self): - from music21 import tempo from music21 import stream s = stream.Stream() - mm1 = tempo.MetronomeMark(number=60) + mm1 = MetronomeMark(number=60) s.append(mm1) s.repeatAppend(note.Note(quarterLength=1), 2) s.repeatAppend(note.Note(quarterLength=0.5), 4) - mmod1 = tempo.MetricModulation() + mmod1 = MetricModulation() s.append(mmod1) # even with we have no assigned metronome, update context will create mmod1.updateByContext() diff --git a/music21/variant.py b/music21/variant.py index 17e2184e3..f365d25af 100644 --- a/music21/variant.py +++ b/music21/variant.py @@ -2530,8 +2530,7 @@ def makeVariantBlocks(s): ''' Unknown and undocumented. Used only in lily/translate -- for musicdiff. ''' - from music21 import variant - variantsToBeDone = s.getElementsByClass(variant.Variant) + variantsToBeDone = s.getElementsByClass(Variant) for v in variantsToBeDone: startOffset = s.elementOffset(v) @@ -2541,7 +2540,7 @@ def makeVariantBlocks(s): includeEndBoundary=False, mustFinishInSpan=False, mustBeginInSpan=True, - classList=[variant.Variant]) + classList=[Variant]) for cV in conflictingVariants: oldReplacementDuration = cV.replacementQuarterLength if s.elementOffset(cV) == startOffset: @@ -2633,14 +2632,12 @@ def testVariantClassA(self): self.assertTrue(v1.getElementsByClass(stream.Measure)) def testDeepCopyVariantA(self): - from music21 import variant - s = stream.Stream() s.repeatAppend(note.Note('G4'), 8) vn1 = note.Note('F#4') vn2 = note.Note('A-4') - v1 = variant.Variant() + v1 = Variant() v1.insert(0, vn1) v1.insert(0, vn2) v1Copy = copy.deepcopy(v1) @@ -2660,7 +2657,7 @@ def testDeepCopyVariantA(self): # test functionality on a deepcopy sCopy = copy.deepcopy(s) - self.assertEqual(len(sCopy.getElementsByClass(variant.Variant)), 1) + self.assertEqual(len(sCopy.getElementsByClass(Variant)), 1) self.assertEqual(self.pitchOut(sCopy.pitches), '[G4, G4, G4, G4, G4, G4, G4, G4]') sCopy.activateVariants(inPlace=True) @@ -2668,13 +2665,11 @@ def testDeepCopyVariantA(self): '[G4, G4, G4, G4, G4, F#4, A-4, G4, G4]') def testDeepCopyVariantB(self): - from music21 import variant - s = stream.Stream() s.repeatAppend(note.Note('G4'), 8) vn1 = note.Note('F#4') vn2 = note.Note('A-4') - v1 = variant.Variant() + v1 = Variant() v1.insert(0, vn1) v1.insert(0, vn2) s.insert(5, v1) diff --git a/music21/volume.py b/music21/volume.py index 1b798c7ef..6b08dcd51 100644 --- a/music21/volume.py +++ b/music21/volume.py @@ -508,10 +508,9 @@ class Test(unittest.TestCase): def testBasic(self): import gc - from music21 import volume n1 = note.Note('G#4') - v = volume.Volume(client=n1) + v = Volume(client=n1) self.assertEqual(v.client, n1) del n1 gc.collect() @@ -521,7 +520,6 @@ def testBasic(self): def testGetContextSearchA(self): from music21 import stream - from music21 import volume s = stream.Stream() d1 = dynamics.Dynamic('mf') @@ -530,7 +528,7 @@ def testGetContextSearchA(self): s.insert(2, d2) n1 = note.Note('g') - v1 = volume.Volume(client=n1) + v1 = Volume(client=n1) s.insert(4, n1) # can get dynamics from volume object @@ -556,10 +554,9 @@ def testGetContextSearchB(self): def testDeepCopyA(self): import copy - from music21 import volume n1 = note.Note() - v1 = volume.Volume() + v1 = Volume() v1.velocity = 111 v1.client = n1 @@ -572,9 +569,7 @@ def testDeepCopyA(self): def testGetRealizedA(self): - from music21 import volume - - v1 = volume.Volume(velocity=64) + v1 = Volume(velocity=64) self.assertEqual(v1.getRealizedStr(), '0.5') d1 = dynamics.Dynamic('p') @@ -589,7 +584,7 @@ def testGetRealizedA(self): # if vel is at max, can scale down with a dynamic - v1 = volume.Volume(velocity=127) + v1 = Volume(velocity=127) d1 = dynamics.Dynamic('fff') self.assertEqual(v1.getRealizedStr(useDynamicContext=d1), '1.0') @@ -620,7 +615,6 @@ def testGetRealizedB(self): def testRealizeVolumeA(self): from music21 import stream - from music21 import volume s = stream.Stream() s.repeatAppend(note.Note('g3'), 16) @@ -637,7 +631,7 @@ def testRealizeVolumeA(self): self.assertEqual(match, ['0.71'] * 16) # calling realize will set all to new cached values - volume.realizeVolume(s) + realizeVolume(s) match = [n.volume.cachedRealizedStr for n in s.notes] self.assertEqual(match, ['0.35', '0.35', '0.5', '0.5', '0.64', '0.64', '0.99', '0.99', @@ -666,7 +660,7 @@ def testRealizeVolumeA(self): self.assertEqual(match, [None] * 16) # can set velocity with realized values - volume.realizeVolume(s, setAbsoluteVelocity=True) + realizeVolume(s, setAbsoluteVelocity=True) match = [n.volume.velocity for n in s.notes] self.assertEqual(match, [45, 45, 63, 63, 81, 81, 126, 126, 99, 99, 127, 127, 27, 27, 99, 99]) From e57c658fdd9b32b288a5e1f7123ccf1306a79ace Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 28 Aug 2026 12:50:15 -1000 Subject: [PATCH 2/4] Remove the last self-references: clef's own module, two doctests clefFromString imported its own module to enumerate the clef classes by name; globals() is the same namespace without the import. The doctests in configure.Dialog._rawQueryPrepareHeader and tempo.TempoText imported music21 (or configure) before using it, which the pytest plugin already supplies -- it injects music21 and everything in its __all__ into the doctest namespace. base.py keeps its four `>>> import music21` lines, which are there to show the fully-qualified path rather than to make the example run. TempoText's docstring was a bare example with no prose; says now what the class is for. AI-assisted (Claude) --- music21/clef.py | 8 +++----- music21/configure.py | 1 - music21/tempo.py | 9 +++++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/music21/clef.py b/music21/clef.py index 3a85fc7b5..b01d0977c 100644 --- a/music21/clef.py +++ b/music21/clef.py @@ -824,14 +824,12 @@ def clefFromString(clefString, octaveShift=0) -> Clef: else: lineNum = False elif len(xnStr) > 2: - from music21 import clef as myself xnLower = xnStr.lower() - for x in dir(myself): - if 'Clef' not in x: + for className, objType in globals().items(): + if 'Clef' not in className: continue - if xnLower != x.lower() and xnLower + 'clef' != x.lower(): + if className.lower() not in (xnLower, xnLower + 'clef'): continue - objType = getattr(myself, x) if isinstance(objType, type): return objType() diff --git a/music21/configure.py b/music21/configure.py index 024af6d3c..772cee6ab 100644 --- a/music21/configure.py +++ b/music21/configure.py @@ -364,7 +364,6 @@ def _rawQueryPrepareHeader(self, msg=''): ''' Prepare the header, given a string. - >>> from music21 import configure >>> d = configure.Dialog() >>> d._rawQueryPrepareHeader('test') 'test' diff --git a/music21/tempo.py b/music21/tempo.py index 9cf0bb0bd..bba4a40a8 100644 --- a/music21/tempo.py +++ b/music21/tempo.py @@ -181,8 +181,10 @@ def getPreviousMetronomeMark(self): # ------------------------------------------------------------------------------ class TempoText(TempoIndication): ''' - >>> import music21 - >>> tm = music21.tempo.TempoText('adagio') + TempoText is a TempoIndication that uses words (not metronome numbers) + to indicate tempo. + + >>> tm = tempo.TempoText('adagio') >>> tm >>> print(tm.text) @@ -206,8 +208,7 @@ def text(self): Get or set the text as a string. Setting is also the primary way that the stored TextExpression object is created. - >>> import music21 - >>> tm = music21.tempo.TempoText('adagio') + >>> tm = tempo.TempoText('adagio') >>> tm.text 'adagio' >>> tm.getTextExpression() From 303bcebd925ccd66ad1120c2f26be451a9852fce Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 28 Aug 2026 12:52:18 -1000 Subject: [PATCH 3/4] Match clef classes by inheritance, not by name substring The name scan `if 'Clef' not in className` also matched ClefException, so clefFromString('clefexception') built and returned an exception object. Filter on issubclass(Clef) instead; every clef class in the module ends in 'Clef', so the clefs found are unchanged. AI-assisted (Claude) --- music21/clef.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/music21/clef.py b/music21/clef.py index b01d0977c..4debb4b54 100644 --- a/music21/clef.py +++ b/music21/clef.py @@ -825,13 +825,11 @@ def clefFromString(clefString, octaveShift=0) -> Clef: lineNum = False elif len(xnStr) > 2: xnLower = xnStr.lower() - for className, objType in globals().items(): - if 'Clef' not in className: + for className, classObj in globals().items(): + if not isinstance(classObj, type) or not issubclass(classObj, Clef): continue - if className.lower() not in (xnLower, xnLower + 'clef'): - continue - if isinstance(objType, type): - return objType() + if className.lower() in (xnLower, xnLower + 'clef'): + return classObj() raise ClefException('Could not find clef ' + xnStr) else: From e673c59cda92c3bf095b35317a77aa81b34e253c Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Fri, 28 Aug 2026 12:59:24 -1000 Subject: [PATCH 4/4] Bump clef.py's copyright; say when a sweep should not bump one clef.py is the only file in this branch whose change stands on its own -- the other twenty are a mechanical removal of dead imports, and bumping twenty copyright banners would bury the diff under them. AI-assisted (Claude) --- AGENTS.md | 2 ++ music21/clef.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index c61555b62..6b9738c6f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,8 @@ - Imports: standard library first, then music21 modules, one per line, alphabetical. - New modules open with the `# Name: / # Purpose: / # Authors: / # Copyright: / # License:` banner (copy a neighboring module's), then the module docstring, then imports. Update the Copyright date end to current year when changing the module. + When a file is edited only incidentally, as one of many touched by a sweep, leave its + Copyright alone; bump only the files the change is really about. - No `print()`. Use `environLocal = environment.Environment('moduleName')` and `environLocal.printDebug(...)`, or `environLocal.warn(...)` when the user should hear about it every time. `test/toggleDebug.py` switches debug output on and off. diff --git a/music21/clef.py b/music21/clef.py index 4debb4b54..7ff0c6c80 100644 --- a/music21/clef.py +++ b/music21/clef.py @@ -6,7 +6,7 @@ # Christopher Ariza # Michael Bodenbach # -# Copyright: Copyright © 2009-2024 Michael Scott Asato Cuthbert +# Copyright: Copyright © 2009-2026 Michael Scott Asato Cuthbert # License: BSD, see license.txt # ------------------------------------------------------------------------------ '''