Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 23 additions & 22 deletions music21/analysis/reduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,20 @@ def __init__(self, **keywords):
self._chordReduction = None # store a chordal reduction of available


def _setScore(self, value):
@property
def score(self):
'''
Get or set the Score. Setting the score set a deepcopy of the score; the score
set here will not be altered.

>>> s = corpus.parse('bwv66.6')
>>> sr = analysis.reduction.ScoreReduction()
>>> sr.score = s
'''
return self._score

@score.setter
def score(self, value):
if not isinstance(value, stream.Stream):
raise ScoreReductionException('cannot set a non Stream')
if value.hasPartLikeStreams:
Expand All @@ -223,20 +236,16 @@ def _setScore(self, value):
self._score = s
self._score.setDerivationMethod('ScoreReduction', recurse=True)

def _getScore(self):
return self._score

score = property(_getScore, _setScore, doc='''
Get or set the Score. Setting the score set a deepcopy of the score; the score
set here will not be altered.

>>> s = corpus.parse('bwv66.6')
>>> sr = analysis.reduction.ScoreReduction()
>>> sr.score = s
''')

@property
def chordReduction(self):
'''
Get or set a Chord reduction as a Stream or Score. Setting the this values
set a deepcopy of the reduction; the reduction set here will not be altered.
'''
return self._chordReduction

def _setChordReduction(self, value):
@chordReduction.setter
def chordReduction(self, value):
if not isinstance(value, stream.Stream):
raise ScoreReductionException('cannot set a non Stream')
if value.hasPartLikeStreams():
Expand All @@ -247,14 +256,6 @@ def _setChordReduction(self, value):
s.insert(0, copy.deepcopy(value))
self._chordReduction = s

def _getChordReduction(self):
return self._chordReduction

chordReduction = property(_getChordReduction, _setChordReduction, doc='''
Get or set a Chord reduction as a Stream or Score. Setting the this values
set a deepcopy of the reduction; the reduction set here will not be altered.
''')



def _extractReductionEvents(self, score, removeAfterParsing=True):
Expand Down
24 changes: 12 additions & 12 deletions music21/articulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,27 +170,27 @@ class name without the leading letter lowercase.
className = self.__class__.__name__
return common.camelCaseToHyphen(className, replacement=' ')

def _getVolumeShift(self):
@property
def volumeShift(self):
'''
Get or set the volumeShift of this Articulation. This value, between -1 and 1,
that is used to shift the final Volume of the object it is attached to.

>>> at1 = articulations.StrongAccent()
>>> at1.volumeShift > 0.1
True
'''
return self._volumeShift

def _setVolumeShift(self, value):
@volumeShift.setter
def volumeShift(self, value):
# value should be between 0 and 1
if value > 1:
value = 1
elif value < -1:
value = -1
self._volumeShift = value

volumeShift = property(_getVolumeShift, _setVolumeShift, doc='''
Get or set the volumeShift of this Articulation. This value, between -1 and 1,
that is used to shift the final Volume of the object it is attached to.


>>> at1 = articulations.StrongAccent()
>>> at1.volumeShift > 0.1
True
''')

# ------------------------------------------------------------------------------
class LengthArticulation(Articulation):
'''
Expand Down
18 changes: 9 additions & 9 deletions music21/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,9 @@ def _reprInternal(self):
return f'type={self.type}'


def _getType(self):
return self._type

def _setType(self, value):
self._type = standardizeBarType(value)

type = property(_getType, _setType,
doc='''
@property
def type(self):
'''
Get and set the Barline type property.

>>> b = bar.Barline()
Expand All @@ -171,7 +166,12 @@ def _setType(self, value):
>>> b.type = 'light-light'
>>> b.type
'double'
''')
'''
return self._type

@type.setter
def type(self, value):
self._type = standardizeBarType(value)

def musicXMLBarStyle(self):
'''
Expand Down
158 changes: 78 additions & 80 deletions music21/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1307,10 +1307,9 @@ def purgeOrphans(self, excludeStorageStreams=True) -> None:
orphans.append(id(s))
for i in orphans:
self.sites.removeById(i)
p = self._getActiveSite() # this can be simplified.
p = self.activeSite
if p is not None and id(p) == i:
# noinspection PyArgumentList
self._setActiveSite(None)
self.activeSite = None

def purgeLocations(self, rescanIsDead=False) -> None:
'''
Expand Down Expand Up @@ -2419,20 +2418,48 @@ def previous(self,
# -------------------------------------------------------------------------
# properties

def _getActiveSite(self):
@property
def activeSite(self):
'''
A reference to the most-recent object used to
contain this object. In most cases, this will be a
Stream or Stream sub-class. In most cases, an object's
activeSite attribute is automatically set when the
object is attached to a Stream.


>>> n = note.Note('C#4')
>>> p = stream.Part()
>>> p.insert(20.0, n)
>>> n.activeSite is p
True
>>> n.offset
20.0

>>> m = stream.Measure()
>>> m.insert(10.0, n)
>>> n.activeSite is m
True
>>> n.offset
10.0
>>> n.activeSite = p
>>> n.offset
20.0
'''
# can be None
if WEAKREF_ACTIVE:
if self._activeSite is None: # leave None
return None
else: # even if current activeSite is not a weakref, this will work
# environLocal.printDebug(['_getActiveSite() called:',
# environLocal.printDebug(['activeSite getter called:',
# 'self._activeSite', self._activeSite])
return common.unwrapWeakref(self._activeSite)
else: # pragma: no cover
return self._activeSite

def _setActiveSite(self, site: stream.Stream|None):
# environLocal.printDebug(['_setActiveSite() called:', 'self', self, 'site', site])
@activeSite.setter
def activeSite(self, site: stream.Stream|None):
# environLocal.printDebug(['activeSite setter called:', 'self', self, 'site', site])

# NOTE: this is a performance intensive call
if site is not None:
Expand Down Expand Up @@ -2461,35 +2488,6 @@ def _setActiveSite(self, site: stream.Stream|None):
else: # pragma: no cover
self._activeSite = site

activeSite = property(_getActiveSite,
_setActiveSite,
doc='''
A reference to the most-recent object used to
contain this object. In most cases, this will be a
Stream or Stream sub-class. In most cases, an object's
activeSite attribute is automatically set when the
object is attached to a Stream.


>>> n = note.Note('C#4')
>>> p = stream.Part()
>>> p.insert(20.0, n)
>>> n.activeSite is p
True
>>> n.offset
20.0

>>> m = stream.Measure()
>>> m.insert(10.0, n)
>>> n.activeSite is m
True
>>> n.offset
10.0
>>> n.activeSite = p
>>> n.offset
20.0
''')

@property
def offset(self) -> OffsetQL:
'''
Expand Down Expand Up @@ -2826,24 +2824,9 @@ def informSites(self, changedInformation=None):
# noinspection PyCallingNonCallable
s.coreElementsChanged(updateIsFlat=False, keepIndex=True)

def _getPriority(self):
return self._priority

def _setPriority(self, value):
'''
value is an int.

Informs all sites of the change.
@property
def priority(self):
'''
if not isinstance(value, int):
raise ElementException('priority values must be integers.')
if self._priority != value:
self._priority = value
self.informSites({'changedElement': 'priority', 'priority': value})

priority = property(_getPriority,
_setPriority,
doc='''
Get and set the priority integer value.

Priority specifies the order of processing from left (lowest number)
Expand Down Expand Up @@ -2872,7 +2855,21 @@ def _setPriority(self, value):
>>> a.priority = 'high'
Traceback (most recent call last):
music21.base.ElementException: priority values must be integers.
''')
'''
return self._priority

@priority.setter
def priority(self, value):
'''
value is an int.

Informs all sites of the change.
'''
if not isinstance(value, int):
raise ElementException('priority values must be integers.')
if self._priority != value:
self._priority = value
self.informSites({'changedElement': 'priority', 'priority': value})

# -------------------------------------------------------------------------
# display and writing
Expand Down Expand Up @@ -3948,31 +3945,9 @@ def beatStrength(self) -> float:
except Music21ObjectException:
return float('nan')

def _getSeconds(self) -> float:
from music21 import tempo
# do not search if duration is zero
if self.duration.quarterLength == 0.0:
return 0.0

ti = self.getContextByClass(tempo.TempoIndication)
if ti is None:
return float('nan')
mm = ti.getSoundingMetronomeMark()
# once we have mm, simply pass in this duration
return mm.durationToSeconds(self.duration)

def _setSeconds(self, value: int|float) -> None:
from music21 import tempo
ti = self.getContextByClass(tempo.TempoIndication)
if ti is None:
raise Music21ObjectException('this object does not have a TempoIndication in Sites')
mm = ti.getSoundingMetronomeMark()
self.duration = mm.secondsToDuration(value)
for s in self.sites.get(excludeNone=True):
if self in s.elements:
s.coreElementsChanged() # highest time is changed.

seconds = property(_getSeconds, _setSeconds, doc='''
@property
def seconds(self) -> float:
'''
Get or set the duration of this object in seconds, assuming
that this object has a :class:`~music21.tempo.MetronomeMark`
or :class:`~music21.tempo.MetricModulation`
Expand Down Expand Up @@ -4051,7 +4026,30 @@ def _setSeconds(self, value: int|float) -> None:
'half'

* Changed in v6.3: return `nan` instead of raising an exception.
''')
'''
from music21 import tempo
# do not search if duration is zero
if self.duration.quarterLength == 0.0:
return 0.0

ti = self.getContextByClass(tempo.TempoIndication)
if ti is None:
return float('nan')
mm = ti.getSoundingMetronomeMark()
# once we have mm, simply pass in this duration
return mm.durationToSeconds(self.duration)

@seconds.setter
def seconds(self, value: int|float) -> None:
from music21 import tempo
ti = self.getContextByClass(tempo.TempoIndication)
if ti is None:
raise Music21ObjectException('this object does not have a TempoIndication in Sites')
mm = ti.getSoundingMetronomeMark()
self.duration = mm.secondsToDuration(value)
for s in self.sites.get(excludeNone=True):
if self in s.elements:
s.coreElementsChanged() # highest time is changed.


# ------------------------------------------------------------------------------
Expand Down
3 changes: 1 addition & 2 deletions music21/common/numberTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from functools import cache
import math
from math import isclose, gcd
import numbers
import random
from typing import overload, TYPE_CHECKING
import unittest
Expand Down Expand Up @@ -358,7 +357,7 @@ def opFrac(num: OffsetQLIn) -> OffsetQL:
raise TypeError(f'Cannot convert num: {num}')


def mixedNumeral(expr: numbers.Real,
def mixedNumeral(expr: int|float|Fraction,
limitDenominator: int = defaults.limitOffsetDenominator) -> str:
'''
Returns a string representing a mixedNumeral form of a number
Expand Down
13 changes: 7 additions & 6 deletions music21/converter/subConverters.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,17 @@ def parseFile(self,

return self.stream

def _getStream(self):
@property
def stream(self):
'''
Returns or sets the stream in the converter. Must be defined for subConverter to work.
'''
return self._stream

def _setStream(self, newStream):
@stream.setter
def stream(self, newStream):
self._stream = newStream

stream = property(_getStream, _setStream, doc='''
Returns or sets the stream in the converter. Must be defined for subConverter to work.
''')

def checkShowAbility(self, **keywords) -> bool:
'''
return bool on whether the *system* is
Expand Down
Loading
Loading