From 6cf1a0d776f40f9d1f7b4d6a7e36c9a2d3dfc3b8 Mon Sep 17 00:00:00 2001 From: Michael Scott Asato Cuthbert Date: Wed, 12 Oct 2022 09:38:22 -1000 Subject: [PATCH] music21objects must instantiate w/o defaults --- music21/abcFormat/__init__.py | 3 + music21/alpha/analysis/fixer.py | 4 + music21/alpha/analysis/hasher.py | 3 + music21/alpha/analysis/ornamentRecognizer.py | 4 + music21/alpha/analysis/search.py | 3 + music21/analysis/discrete.py | 3 + music21/analysis/reduction.py | 3 + music21/analysis/transposition.py | 3 + music21/analysis/windowed.py | 3 + music21/articulations.py | 3 + music21/bar.py | 3 + music21/beam.py | 4 +- music21/braille/objects.py | 4 +- music21/features/base.py | 1 - music21/humdrum/spineParser.py | 109 +++++++++---------- music21/prebase.py | 4 + music21/romanText/translate.py | 4 +- music21/search/serial.py | 4 +- music21/spanner.py | 4 + music21/test/commonTest.py | 4 +- music21/tie.py | 4 +- music21/voiceLeading.py | 13 +-- 22 files changed, 118 insertions(+), 72 deletions(-) diff --git a/music21/abcFormat/__init__.py b/music21/abcFormat/__init__.py index ff0abe1a10..7f2a822899 100644 --- a/music21/abcFormat/__init__.py +++ b/music21/abcFormat/__init__.py @@ -3439,6 +3439,9 @@ def readstr(self, strSrc: str, number: int | None = None) -> ABCHandler: # ------------------------------------------------------------------------------ class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testTokenization(self): from music21.abcFormat import testFiles diff --git a/music21/alpha/analysis/fixer.py b/music21/alpha/analysis/fixer.py index d336ae9174..07ec080985 100644 --- a/music21/alpha/analysis/fixer.py +++ b/music21/alpha/analysis/fixer.py @@ -504,6 +504,10 @@ def __init__(self, changes, midiStream, omrStream): super().__init__(changes, midiStream, omrStream, recognizer) class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) + def measuresEqual(self, m1, m2): ''' Returns a tuple of (True/False, reason) diff --git a/music21/alpha/analysis/hasher.py b/music21/alpha/analysis/hasher.py index de70294c59..0c7c9d2e3b 100644 --- a/music21/alpha/analysis/hasher.py +++ b/music21/alpha/analysis/hasher.py @@ -585,6 +585,9 @@ def __new__(cls, tupEls): class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def _approximatelyEqual(self, a, b, sig_fig=2): ''' diff --git a/music21/alpha/analysis/ornamentRecognizer.py b/music21/alpha/analysis/ornamentRecognizer.py index 82ab0e6b8f..99a680f0b0 100644 --- a/music21/alpha/analysis/ornamentRecognizer.py +++ b/music21/alpha/analysis/ornamentRecognizer.py @@ -262,6 +262,10 @@ def __init__( self.isInverted = isInverted class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) + def testRecognizeTurn(self): # set up experiment testConditions = [] diff --git a/music21/alpha/analysis/search.py b/music21/alpha/analysis/search.py index de652f297f..4e0c64d163 100644 --- a/music21/alpha/analysis/search.py +++ b/music21/alpha/analysis/search.py @@ -251,6 +251,9 @@ def findConsecutiveScale(source, targetScale, degreesRequired=5, # ------------------------------------------------------------------------------ class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testFindConsecutiveScaleA(self): sc = scale.MajorScale('a4') diff --git a/music21/analysis/discrete.py b/music21/analysis/discrete.py index ccc4e5225c..3023abcd9f 100644 --- a/music21/analysis/discrete.py +++ b/music21/analysis/discrete.py @@ -1413,6 +1413,9 @@ def analysisClassFromMethodName(method: str) -> type[DiscreteAnalysis] | None: class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testKeyAnalysisKrumhansl(self): from music21 import converter diff --git a/music21/analysis/reduction.py b/music21/analysis/reduction.py index 78e5038257..e1bdab51f2 100644 --- a/music21/analysis/reduction.py +++ b/music21/analysis/reduction.py @@ -891,6 +891,9 @@ def getGraphHorizontalBarWeightedData(self): # ------------------------------------------------------------------------------ class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testExtractionA(self): from music21 import analysis diff --git a/music21/analysis/transposition.py b/music21/analysis/transposition.py index 8bfecc6c40..640983817f 100644 --- a/music21/analysis/transposition.py +++ b/music21/analysis/transposition.py @@ -191,6 +191,9 @@ def getPitchesOfDistinctTranspositions(self): # ------------------------------------------------------------------------------ class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testConstructTranspositionChecker(self): p = [pitch.Pitch('D#')] diff --git a/music21/analysis/windowed.py b/music21/analysis/windowed.py index 904e7a9f72..51c538ce8f 100644 --- a/music21/analysis/windowed.py +++ b/music21/analysis/windowed.py @@ -363,6 +363,9 @@ def process(self, subStream): class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testBasic(self): from music21 import corpus diff --git a/music21/articulations.py b/music21/articulations.py index 7c3cccb048..9570b0393b 100644 --- a/music21/articulations.py +++ b/music21/articulations.py @@ -662,6 +662,9 @@ class HandbellIndication(TechnicalIndication): # ------------------------------------------------------------------------------ class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testBasic(self): a = FretBend() diff --git a/music21/bar.py b/music21/bar.py index 2756c1ea57..cc774a0bbe 100644 --- a/music21/bar.py +++ b/music21/bar.py @@ -375,6 +375,9 @@ def getTextExpression(self, prefix='', postfix='x'): # ------------------------------------------------------------------------------ class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testSortOrder(self): from music21 import stream diff --git a/music21/beam.py b/music21/beam.py index 0470645f7b..2d3b83c917 100644 --- a/music21/beam.py +++ b/music21/beam.py @@ -702,7 +702,9 @@ def setByNumber(self, number, type, direction=None): # type is okay @ReservedAs class Test(unittest.TestCase): - pass + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) # ----------------------------------------------------------------------------- diff --git a/music21/braille/objects.py b/music21/braille/objects.py index dc4cab3c33..c412bd2d8f 100644 --- a/music21/braille/objects.py +++ b/music21/braille/objects.py @@ -79,7 +79,9 @@ class BrailleExplicitNoteExtraSmaller(BrailleExplicitNoteLength): # ------------------------------------------------------------------------------ class Test(unittest.TestCase): - pass + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) if __name__ == '__main__': diff --git a/music21/features/base.py b/music21/features/base.py index 330df373ef..8326e2ef02 100644 --- a/music21/features/base.py +++ b/music21/features/base.py @@ -1279,7 +1279,6 @@ def getIndex(featureString, extractorType=None): class Test(unittest.TestCase): def testStreamFormsA(self): - from music21 import features self.maxDiff = None diff --git a/music21/humdrum/spineParser.py b/music21/humdrum/spineParser.py index 9e98b0cca5..671423afcb 100644 --- a/music21/humdrum/spineParser.py +++ b/music21/humdrum/spineParser.py @@ -685,7 +685,6 @@ def insertGlobalEvents(self): Insert the Global Events (GlobalReferenceLines and GlobalCommentLines) into an appropriate place in the outer Stream. - Run after self.spineCollection.createMusic21Streams(). Is run automatically by self.parse(). uses self.spineCollection.getOffsetsAndPrioritiesByPosition() @@ -737,31 +736,31 @@ def insertGlobalEvents(self): if appendList: self.stream.coreElementsChanged() -# @property -# def stream(self): -# if self._storedStream is not None: -# return self._storedStream -# if self.parsedLines is False: -# self.parse() -# -# if self.spineCollection is None: -# raise HumdrumException('parsing got no spine collections!') -# elif self.spineCollection.spines is None: -# raise HumdrumException('not a single spine in your data... um, not my problem! ' + -# '(well, maybe it is...file a bug report if you ' + -# 'have doubled checked your data)') -# elif self.spineCollection.spines[0].stream is None: -# raise HumdrumException('okay, you got at least one spine, but it ain\'t got ' + -# 'a stream in it; (check your data or file a bug report)') -# else: -# masterStream = stream.Score() -# for thisSpine in self.spineCollection: -# thisSpine.stream.id = 'spine_' + str(thisSpine.id) -# for thisSpine in self.spineCollection: -# if thisSpine.parentSpine is None and thisSpine.spineType == 'kern': -# masterStream.insert(thisSpine.stream) -# self._storedStream = masterStream -# return masterStream + # @property + # def stream(self): + # if self._storedStream is not None: + # return self._storedStream + # if self.parsedLines is False: + # self.parse() + # + # if self.spineCollection is None: + # raise HumdrumException('parsing got no spine collections!') + # elif self.spineCollection.spines is None: + # raise HumdrumException('not a single spine in your data... um, not my problem! ' + + # '(well, maybe it is...file a bug report if you ' + + # 'have doubled checked your data)') + # elif self.spineCollection.spines[0].stream is None: + # raise HumdrumException('okay, you got at least one spine, but it ain\'t got ' + + # 'a stream in it; (check your data or file a bug report)') + # else: + # masterStream = stream.Score() + # for thisSpine in self.spineCollection: + # thisSpine.stream.id = 'spine_' + str(thisSpine.id) + # for thisSpine in self.spineCollection: + # if thisSpine.parentSpine is None and thisSpine.spineType == 'kern': + # masterStream.insert(thisSpine.stream) + # self._storedStream = masterStream + # return masterStream def parseMetadata(self, s=None): ''' @@ -2499,7 +2498,6 @@ def kernTandemToObject(tandem): This method converts them to music21 objects. - >>> m = humdrum.spineParser.kernTandemToObject('*M3/1') >>> m @@ -2619,8 +2617,8 @@ def kernTandemToObject(tandem): class MiscTandem(base.Music21Object): - def __init__(self, tandem=''): - super().__init__() + def __init__(self, tandem='', **keywords): + super().__init__(**keywords) self.tandem = tandem def _reprInternal(self): @@ -2631,16 +2629,14 @@ class SpineComment(base.Music21Object): ''' A Music21Object that represents a comment in a single spine. - >>> sc = humdrum.spineParser.SpineComment('! this is a spine comment') >>> sc >>> sc.comment 'this is a spine comment' ''' - - def __init__(self, comment=''): - super().__init__() + def __init__(self, comment='', **keywords): + super().__init__(**keywords) commentPart = re.sub(r'^!+\s?', '', comment) self.comment = commentPart @@ -2652,16 +2648,14 @@ class GlobalComment(base.Music21Object): ''' A Music21Object that represents a comment for the whole score - >>> sc = humdrum.spineParser.GlobalComment('!! this is a global comment') >>> sc >>> sc.comment 'this is a global comment' ''' - - def __init__(self, comment=''): - super().__init__() + def __init__(self, comment='', **keywords): + super().__init__(**keywords) commentPart = re.sub(r'^!!+\s?', '', comment) commentPart = commentPart.strip() self.comment = commentPart @@ -2713,8 +2707,8 @@ class GlobalReference(base.Music21Object): False ''' - def __init__(self, codeOrAll='', valueOrNone=None): - super().__init__() + def __init__(self, codeOrAll='', valueOrNone=None, **keywords): + super().__init__(**keywords) codeOrAll = re.sub(r'^!!!+', '', codeOrAll) codeOrAll = codeOrAll.strip() if valueOrNone is None and ':' in codeOrAll: @@ -2816,7 +2810,7 @@ def __init__(self, codeOrAll='', valueOrNone=None): 'EED': 'electronicEditor', # electronic editor 'ENC': 'electronicEncoder', # electronic encoder (person) 'END': '', # encoding date - 'EMD': '', # electronic document modification description (one per modificiation) + 'EMD': '', # electronic document modification description (one per modification) 'EEV': '', # electronic edition version 'EFL': '', # file number e.g. '1/4' for one of four 'EST': '', # encoding status (free form, normally eliminated prior to distribution) @@ -2864,6 +2858,9 @@ def _reprInternal(self): class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) def testLoadMazurka(self): # hf1 = HumdrumFile('d:/web/eclipse/music21misc/mazurka06-2.krn') @@ -2871,22 +2868,22 @@ def testLoadMazurka(self): hf1 = HumdrumDataCollection(testFiles.mazurka6) hf1.parse() - # hf1 = HumdrumFile('d:/web/eclipse/music21misc/ojibway.krn') - # for thisEventCollection in hf1.eventCollections: - # ev = thisEventCollection.getSpineEvent(0).contents - # if ev is not None: - # print(ev) - # else: - # print('NONE') - - # for mySpine in hf1.spineCollection: - # print('\n\n***NEW SPINE: No. ' + str(mySpine.id) + ' parentSpine: ' - # + str(mySpine.parentSpine) + ' childSpines: ' + str(mySpine.childSpines)) - # print(mySpine.spineType) - # for childSpinesSpine in mySpine.childSpinesSpines(): - # print(str(childSpinesSpine.id) + ' *** testing spineCollection code ***') - # for thisEvent in mySpine: - # print(thisEvent.contents) + # hf1 = HumdrumFile('d:/web/eclipse/music21misc/ojibway.krn') + # for thisEventCollection in hf1.eventCollections: + # ev = thisEventCollection.getSpineEvent(0).contents + # if ev is not None: + # print(ev) + # else: + # print('NONE') + # + # for mySpine in hf1.spineCollection: + # print('\n\n***NEW SPINE: No. ' + str(mySpine.id) + ' parentSpine: ' + # + str(mySpine.parentSpine) + ' childSpines: ' + str(mySpine.childSpines)) + # print(mySpine.spineType) + # for childSpinesSpine in mySpine.childSpinesSpines(): + # print(str(childSpinesSpine.id) + ' *** testing spineCollection code ***') + # for thisEvent in mySpine: + # print(thisEvent.contents) spine5 = hf1.spineCollection.getSpineById(5) self.assertEqual(spine5.id, 5) self.assertEqual(spine5.parentSpine.id, 1) diff --git a/music21/prebase.py b/music21/prebase.py index 20b1f31210..0c0dac7176 100644 --- a/music21/prebase.py +++ b/music21/prebase.py @@ -283,6 +283,10 @@ def _reprInternal(self) -> str: class Test(unittest.TestCase): + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) + def test_reprInternal(self): from music21.base import Music21Object b = Music21Object() diff --git a/music21/romanText/translate.py b/music21/romanText/translate.py index 60c070a053..9034e39d1c 100644 --- a/music21/romanText/translate.py +++ b/music21/romanText/translate.py @@ -167,8 +167,8 @@ class RomanTextUnprocessedToken(base.ElementWrapper): class RomanTextUnprocessedMetadata(base.Music21Object): - def __init__(self, tag='', data=''): - super().__init__() + def __init__(self, tag='', data='', **keywords): + super().__init__(**keywords) self.tag = tag self.data = data diff --git a/music21/search/serial.py b/music21/search/serial.py index b536fa578c..4af3eca966 100644 --- a/music21/search/serial.py +++ b/music21/search/serial.py @@ -76,8 +76,8 @@ class ContiguousSegmentOfNotes(base.Music21Object): _DOC_ORDER = ['startMeasureNumber', 'startOffset', 'zeroCenteredTransformationsFromMatched', 'originalCenteredTransformationsFromMatched'] - def __init__(self, segment=None, containerStream=None, partNumber=0): - super().__init__() + def __init__(self, segment=None, containerStream=None, partNumber=0, **keywords): + super().__init__(**keywords) self.segment = segment self.containerStream = containerStream self.partNumber = partNumber diff --git a/music21/spanner.py b/music21/spanner.py index 4bee99eb13..cad581a7aa 100644 --- a/music21/spanner.py +++ b/music21/spanner.py @@ -1889,6 +1889,10 @@ def setUp(self): from music21.musicxml.m21ToXml import GeneralObjectExporter self.GEX = GeneralObjectExporter() + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) + def xmlStr(self, obj): xmlBytes = self.GEX.parse(obj) return xmlBytes.decode('utf-8') diff --git a/music21/test/commonTest.py b/music21/test/commonTest.py index e8f2fb663d..6784e0cbde 100644 --- a/music21/test/commonTest.py +++ b/music21/test/commonTest.py @@ -50,7 +50,9 @@ def testCopyAll(testInstance: unittest.TestCase, globals_: typing.Dict[str, typi try: # see if obj can be made w/o args instance = obj() - except TypeError: + except TypeError as te: + if issubclass(obj, music21.base.Music21Object): + raise TypeError('Define Music21Objects to be instantiated without initial args') continue try: diff --git a/music21/tie.py b/music21/tie.py index d71a87372a..9abecda4e9 100644 --- a/music21/tie.py +++ b/music21/tie.py @@ -147,7 +147,9 @@ def _reprInternal(self): class Test(unittest.TestCase): - pass + def testCopyAndDeepcopy(self): + from music21.test.commonTest import testCopyAll + testCopyAll(self, globals()) # ------------------------------------------------------------------------------ diff --git a/music21/voiceLeading.py b/music21/voiceLeading.py index 15d5bcfa6a..e4d32fafcd 100644 --- a/music21/voiceLeading.py +++ b/music21/voiceLeading.py @@ -1793,7 +1793,7 @@ class VerticalityNTuplet(base.Music21Object): motion and music theory elements such as passing tones ''' - def __init__(self, listOfVerticalities, **keywords): + def __init__(self, listOfVerticalities=None, **keywords): super().__init__(**keywords) self.verticalities = listOfVerticalities @@ -1816,7 +1816,7 @@ class VerticalityTriplet(VerticalityNTuplet): ''' a collection of three Verticalities ''' - def __init__(self, listOfVerticalities, **keywords): + def __init__(self, listOfVerticalities=None, **keywords): super().__init__(listOfVerticalities, **keywords) self.tnlsDict = {} # defaultdict(int) # Three Note Linear Segments @@ -1928,7 +1928,7 @@ class NNoteLinearSegment(base.Music21Object): [, , ] ''' - def __init__(self, noteList, **keywords): + def __init__(self, noteList=None, **keywords): super().__init__(**keywords) self._noteList = [] for value in noteList: @@ -2320,7 +2320,7 @@ class NChordLinearSegmentException(exceptions21.Music21Exception): class NObjectLinearSegment(base.Music21Object): - def __init__(self, objectList, **keywords): + def __init__(self, objectList=None, **keywords): super().__init__(**keywords) self.objectList = objectList @@ -2329,7 +2329,7 @@ def _reprInternal(self): class NChordLinearSegment(NObjectLinearSegment): - def __init__(self, chordList, **keywords): + def __init__(self, chordList=None, **keywords): super().__init__(chordList, **keywords) self._chordList = [] for value in chordList: @@ -2368,7 +2368,7 @@ def _reprInternal(self): return f'chordList={self.chordList}' class TwoChordLinearSegment(NChordLinearSegment): - def __init__(self, chordList, chord2=None, **keywords): + def __init__(self, chordList=None, chord2=None, **keywords): if isinstance(chordList, (list, tuple)): if len(chordList) != 2: # pragma: no cover raise ValueError( @@ -2404,7 +2404,6 @@ def bassInterval(self): # ------------------------------------------------------------------------------ class Test(unittest.TestCase): - def testInstantiateEmptyObject(self): ''' test instantiating an empty VoiceLeadingQuartet