Source code for music21.stream.streamStatus
# -----------------------------------------------------------------------------
# Name: streamStatus.py
# Purpose: Functionality for reporting on the notational status of streams
#
# Authors: Joséphine Wolf Oberholtzer
#
# Copyright: Copyright © 2013 Michael Scott Asato Cuthbert
# License: BSD, see license.txt
# -----------------------------------------------------------------------------
from __future__ import annotations
import unittest
from music21 import environment
from music21.common.misc import defaultDeepcopy
from music21.common.objects import SlottedObjectMixin
environLocal = environment.Environment(__file__)
# -----------------------------------------------------------------------------
[docs]
class StreamStatus(SlottedObjectMixin):
'''
An object that stores the current notation state for the client stream.
Separates out tasks such as whether notation has been made, etc.
>>> s = stream.Stream()
>>> ss = s.streamStatus
>>> ss
<music21.stream.streamStatus.StreamStatus object at 0x...>
>>> s.streamStatus.client is s
True
Copying of StreamStatus and surrounding Streams
>>> import copy
>>> ss2 = copy.deepcopy(ss)
>>> ss2.client is None
True
>>> s2 = copy.deepcopy(s)
>>> s2.streamStatus
<music21.stream.streamStatus.StreamStatus object at 0x...>
>>> s2.streamStatus is ss
False
>>> s2.streamStatus.client is s2
True
'''
# CLASS VARIABLES #
__slots__ = (
'_accidentals',
'_beams',
'_concertPitch',
'_dirty',
'_enharmonics',
'_measures',
'_ornaments',
'_rests',
'_ties',
'_tuplets',
'client',
)
# INITIALIZER #
def __init__(self, client=None):
self._accidentals = None
self._beams = None
self._concertPitch = None
self._dirty = None
self._enharmonics = None
self._measures = None
self._ornaments = None
self._rests = None
self._ties = None
self._tuplets = None
self.client = client
# SPECIAL METHODS #
def __deepcopy__(self, memo=None):
'''
Manage deepcopying by creating a new reference to the same object.
leaving out the client
'''
return defaultDeepcopy(self, memo, ignoreAttributes={'client'})
# PUBLIC METHODS #
[docs]
def haveAccidentalsBeenMade(self):
'''
If Accidentals.displayStatus is None for all contained pitches, it as
assumed that accidentals have not been set for display and/or
makeAccidentals has not been run. If any Accidental has displayStatus
other than None, this method returns True, regardless of if
makeAccidentals has actually been run.
'''
for p in self.client.pitches:
if p.accidental is not None:
if p.accidental.displayStatus is not None:
return True
return False
[docs]
def haveBeamsBeenMade(self):
'''
If any Note in this Stream has .beams defined, it as assumed that Beams
have not been set and/or makeBeams has not been run. If any Beams
exist, this method returns True, regardless of if makeBeams has
actually been run.
'''
for n in self.client.recurse(classFilter=('NotRest',), restoreActiveSites=False):
if n.beams is not None and n.beams.beamsList:
return True
return False
[docs]
def haveTupletBracketsBeenMade(self):
'''
If any GeneralNote in this Stream is a tuplet, then check to
see if any of them have a first Tuplet with type besides None
return True. Otherwise, return False if there is a tuplet. Return None if
no Tuplets.
>>> s = stream.Stream()
>>> s.streamStatus.haveTupletBracketsBeenMade() is None
True
>>> s.append(note.Note())
>>> s.streamStatus.haveTupletBracketsBeenMade() is None
True
>>> nTuplet = note.Note(quarterLength=1/3)
>>> s.append(nTuplet)
>>> s.streamStatus.haveTupletBracketsBeenMade()
False
>>> nTuplet.duration.tuplets[0].type = 'start'
>>> s.streamStatus.haveTupletBracketsBeenMade()
True
'''
foundTuplet = False
for n in self.client.recurse(classFilter='GeneralNote', restoreActiveSites=False):
if n.duration.tuplets:
foundTuplet = True
if n.duration.tuplets[0].type is not None:
return True
if foundTuplet:
return False
else:
return None
# PUBLIC PROPERTIES #
@property
def accidentals(self):
if self._accidentals is None:
self._accidentals = self.haveAccidentalsBeenMade()
return self._accidentals
@accidentals.setter
def accidentals(self, expr):
if expr is not None:
self._accidentals = bool(expr)
else:
self._accidentals = None
@property
def beams(self):
if self._beams is None:
self._beams = self.haveBeamsBeenMade()
return self._beams
@beams.setter
def beams(self, expr):
if expr is not None:
self._beams = bool(expr)
else:
self._beams = None
@property
def tuplets(self):
if self._tuplets is None:
self._tuplets = self.haveTupletBracketsBeenMade()
# If there were no tuplet durations,
# tuplet brackets don't need to be made.
if self._tuplets is None:
self._tuplets = True
return self._tuplets
@tuplets.setter
def tuplets(self, expr):
if expr is not None:
self._tuplets = bool(expr)
else:
self._tuplets = None
# -----------------------------------------------------------------------------
class Test(unittest.TestCase):
'''
Note: most Stream tests are found in stream.tests
'''
def testHaveBeamsBeenMadeAfterDeepcopy(self):
import copy
from music21 import stream
from music21 import note
m = stream.Measure()
c = note.Note('C4', type='quarter')
m.append(c)
d1 = note.Note('D4', type='eighth')
d2 = note.Note('D4', type='eighth')
m.append([d1, d2])
e3 = note.Note('E4', type='eighth')
e4 = note.Note('E4', type='eighth')
m.append([e3, e4])
d1.beams.append('start')
d2.beams.append('stop')
self.assertTrue(m.streamStatus.haveBeamsBeenMade())
mm = copy.deepcopy(m)
self.assertTrue(mm.streamStatus.haveBeamsBeenMade())
mm.streamStatus.beams = False
mmm = copy.deepcopy(mm)
self.assertFalse(mmm.streamStatus.beams)
# m.show()
# -----------------------------------------------------------------------------
if __name__ == '__main__':
import music21
music21.mainTest(Test)