
    rh'                      % S r SSKJr  SSKJr  SSKrSSKrSSKrSSKJ	r	  SSK
r
SSKJrJr  SSKrSSKrSSKJr  SSKJr  SS	KJr  SS
KJrJrJr  SSKJr  SSKJr  SSKJr  SSKJr  \R>                  (       a  SSKJ r   SSKJ!r!  SSKJ"r"  \RF                  " S5      r$\RJ                  r&Sr'\RP                  S   r)\RP                  S   r* " S S\RV                  5      r, " S S\RV                  5      r-0 SS_SS_SS_S S!_S"S#_S$S%_S&S'_S(S)_S*S+_S,S-_S.S/_S0S1_S2S3_S4S5_S6S7_S8S9_S:S;_r.S<\/S='   0 S'S"_S%S$_S#S&_S!S(_SS*_SS,_SS._S>S0_S?S2_S@S4_SAS6_SBS8_S;S:_S)S _S+S_S-S_S/S_r0SC\/SD'   \1" \2" \0Rg                  5       5      5      r4SE\/SF'   / SGQr5SH\/SI'   SJr6SK\/SL'   SMr7SK\/SN'    " SO SP\Rp                  5      r9SQ r:SySR jr;SySS jr<SzST jr=S{SU jr> S| S}SW jjr?    S~SX jr@SV\64     SSY jjrA\	" SZ5      SS[ j5       rB   S       SS\ jjrCSS] jrD " S^ S_\Rp                  5      rE0 rFS`\/Sa'   0 rGSb\/Sc'   SSSd jjrHSSe jrI " Sf Sg\R                  5      rK " Sh Si\R                  \5      rL " Sj Sk\R                  R                  \L5      rO " Sl Sm\L5      rP " Sn So\P5      rQ " Sp Sq5      rR " Sr Ss\R                  5      rT " St Su\R                  5      rU\L\K\P\>\R/rVSv\/Sw'   \WSx:X  a  SSKr\R                  " \U5        gg)a	  
The duration module contains  :class:`~music21.duration.Duration` objects
(among other objects and functions).  Duration objects are a fundamental
component of :class:`~music21.note.Note` and all Music21Objects, such as
:class:`~music21.meter.TimeSignature` objects.

Containers such as :class:`~music21.stream.Stream` and
:class:`~music21.stream.Score` also have durations which are equal to the
position of the ending of the last object in the Stream.

Music21 Durations are almost always measured in Quarter Notes, so an eighth
note has a duration of 0.5.  Different Duration-like objects support objects
such as grace notes which take no duration on the page, have a short (but real)
duration when played, and have a duration-type representation when performed.

Example usage:

>>> d = duration.Duration()
>>> d.quarterLength = 0.5
>>> d.type
'eighth'

>>> d.type = 'whole'
>>> d.quarterLength
4.0

>>> d.quarterLength = 0.166666666
>>> d.type
'16th'

>>> d.tuplets[0].numberNotesActual
3

>>> d.tuplets[0].numberNotesNormal
2
    )annotations)IterableN)	lru_cache)infisnan)common)SlottedObjectMixin)opFrac)OffsetQL
OffsetQLInDocOrder)defaults)environment)exceptions21)prebase)basenotestreamduration)r      )startstop	startStopFN)numbertypebothNc                      \ rS rSrSrg)DurationExceptionT    N__name__
__module____qualname____firstlineno____static_attributes__r"       J/home/james-whalen/.local/lib/python3.13/site-packages/music21/duration.pyr    r    T       r)   r    c                      \ rS rSrSrg)TupletExceptionX   r"   Nr#   r"   r)   r*   r-   r-   X   r+   r)   r-   duplex-maximag      P@maximag      @@longag      0@breveg       @wholeg      @halfg       @quarter      ?eighth      ?16th      ?32ndg      ?64thg      ?128thg      ?256thg      ?512thg      ?1024thg      p?2048thg      `?zero        zdict[str, float]typeToDurationg      `@g      p@g      @g      @g      @zdict[float, str]typeFromNumDictzlist[float]typeFromNumDictKeys)r/   r0   r1   r2   r3   r4   r5   r7   r9   r;   r<   r=   r>   r?   r@   rA   z	list[str]ordinalTypeFromNum)               tuple[int, ...]defaultTupletNumerators)-rH   rI   rJ   rK   rL                  %   )   +   /   5   ;   =   C   G   I   O   S   Y   a   e   g   k   m   q                                                   extendedTupletNumeratorsc                  *    \ rS rSr% S\S'   S\S'   Srg)QuarterLengthConversion   ztuple[DurationTuple]
componentszTuplet | Nonetupletr"   N)r$   r%   r&   r'   __annotations__r(   r"   r)   r*   ry   ry      s    $$r)   ry   c                   [        U [        5      (       a'  / nU  H  nUR                  [        U5      5        M     U$ U n[	        US5      (       a  UR
                  b  UR
                  (       d&  UR                  UR                  UR                  SSS4$ UR                  UR                  UR                  UR
                  S   R                  UR
                  S   R                  UR
                  S   R                  R                  4$ )a  
DEPRECATED and to be removed in v10.

A simple data representation of most Duration objects. Processes a single
Duration or a List of Durations, returning a single or list of unitSpecs.

A unitSpec is a tuple of qLen, durType, dots, tupleNumerator,
tupletDenominator, and tupletType (assuming top and bottom tuplets are the
same).

This function does not deal with nested tuplets, etc.

>>> aDur = duration.Duration()
>>> aDur.quarterLength = 3
>>> duration.unitSpec(aDur)
(3.0, 'half', 1, None, None, None)

>>> bDur = duration.Duration()
>>> bDur.quarterLength = 1.125
>>> duration.unitSpec(bDur)
(1.125, 'complex', 0, None, None, None)

>>> cDur = duration.Duration()
>>> cDur.quarterLength = 0.3333333
>>> duration.unitSpec(cDur)
(Fraction(1, 3), 'eighth', 0, 3, 2, 'eighth')

>>> duration.unitSpec([aDur, bDur, cDur])
[(3.0, 'half', 1, None, None, None),
 (1.125, 'complex', 0, None, None, None),
 (Fraction(1, 3), 'eighth', 0, 3, 2, 'eighth')]
tupletsNr   )
isinstancelistappendunitSpechasattrr   quarterLengthr   dotsnumberNotesActualnumberNotesNormaldurationNormal)durationObjectOrObjectsretdOs      r*   r   r      s    B )400)BJJx|$ *
$I&&2::+=RZZ$$bggrwwdDII$$GGGGJJqM33JJqM33JJqM00557 7r)   c                    U [         ;  a  [        SU  35      e[         R                  U 5      nUS:X  a  [        SU  35      e[         US-
     $ )aC  
Given a type (such as 16th or quarter), return the next larger type.

>>> duration.nextLargerType('16th')
'eighth'

>>> duration.nextLargerType('whole')
'breve'

>>> duration.nextLargerType('duplex-maxima')
Traceback (most recent call last):
music21.duration.DurationException: cannot get the next larger of duplex-maxima
zcannot get the next larger of r   r   rG   r    indexdurTypethisOrdinals     r*   nextLargerTyper      sZ     (("@	 JKK$**73Ka"@	 JKKkAo..r)   c                    U [         ;  a  [        SU  35      e[         R                  U 5      nUS:X  a  [        SU  35      e[         US-      $ )ae  
Given a type (such as 16th or quarter), return the next smaller type.

>>> duration.nextSmallerType('16th')
'32nd'
>>> duration.nextSmallerType('whole')
'half'
>>> duration.nextSmallerType('1024th')
'2048th'
>>> duration.nextSmallerType('2048th')
Traceback (most recent call last):
music21.duration.DurationException: cannot get the next smaller of 2048th
zcannot get the next smaller of    r   r   r   s     r*   nextSmallerTyper      sZ     (("A' KLL$**73Kb"A' KLLkAo..r)   c                T  ^  U 4S jnT (       d  U" T 5      e[        T [        R                  5      (       a  ST -  nO[        ST -  5      nU[        ;   a  [        U   S4$ ST -  nST -  n[
         H(  nUS:X  a  M  X5s=:  a  U:  d  M  O  M  [        U   S4s  $    T S:  a  gU" T 5      e)	a  
Returns a two-unit tuple consisting of

1. The type string ("quarter") that is smaller than or equal to the
quarterLength of provided.

2. Boolean, True or False, whether the conversion was exact.

>>> duration.quarterLengthToClosestType(0.5)
('eighth', True)
>>> duration.quarterLengthToClosestType(0.75)
('eighth', False)
>>> duration.quarterLengthToClosestType(1.8)
('quarter', False)

Some extremely close types will return True for exact conversion:

>>> duration.quarterLengthToClosestType(2.0000000000000001)
('half', True)

Very long durations are fine:

>>> duration.quarterLengthToClosestType(129.99)
('duplex-maxima', False)

Durations smaller than 2048th note raise a DurationException

>>> qL = duration.typeToDuration['2048th']
>>> qL
0.001953125

>>> qL = qL * 0.75
>>> duration.quarterLengthToClosestType(qL)
Traceback (most recent call last):
music21.duration.DurationException: Cannot return types smaller than 2048th;
    qLen was: 0.00146484375
c                &   > [        SST 3-   5      $ )Nz)Cannot return types smaller than 2048th; z
qLen was: )r    )
qLen_innerqLens    r*   raise_it,quarterLengthToClosestType.<locals>.raise_it0  s"     !L$.tf"5"6 7 	7r)      T   r   F   )r/   F)r   	fractionsFractionr
   rE   rF   )r   r   noteLengthType
lowerBound
upperBoundnumDicts   `     r*   quarterLengthToClosestTyper   
  s    L7 tn $	**++TD) (/66X
X
*G!|2
22'0%88	 + #:+tnr)   c                \    U (       d  g[        U 5      u  pU(       d  [        SU  S35      eU$ )a  
Return a type if there exists a type that is exactly equal to the
duration of the provided quarterLength. Similar to
quarterLengthToClosestType() but this
function only returns exact matches.

>>> duration.convertQuarterLengthToType(2)
'half'
>>> duration.convertQuarterLengthToType(0.125)
'32nd'
>>> duration.convertQuarterLengthToType(0.33333)
Traceback (most recent call last):
music21.duration.DurationException: cannot convert quarterLength 0.33333 exactly to type
rB   zcannot convert quarterLength z exactly to type)r   r    )r   durationTypematchs      r*   convertQuarterLengthToTyper   O  s<     4T:L+D61ABD 	Dr)   r   c                    [        US-   5       H6  nU [        R                  " U5      -  n [        U5      u  pEU(       d  M3  X$4s  $    g! [         a     MH  f = f)a`  
Given a quarterLength, determine if there is a dotted
(or non-dotted) type that exactly matches. Returns a pair of
(numDots, type) or (False, False) if no exact matches are found.

Returns a maximum of four dots by default.

>>> duration.dottedMatch(3.0)
(1, 'half')
>>> duration.dottedMatch(1.75)
(2, 'quarter')

This value is not equal to any dotted note length

>>> duration.dottedMatch(1.6)
(False, False)

maxDots can be lowered for certain searches

>>> duration.dottedMatch(1.875)
(3, 'quarter')
>>> duration.dottedMatch(1.875, 2)
(False, False)

>>> duration.dottedMatch(0.00001, 2)
(False, False)

r   FF)ranger   dotMultiplierr   r    )r   maxDotsr   preDottedLengthr   r   s         r*   dottedMatchr   f  se    > gk"!5!5d!;;	7HNG 5?" # 	 ! 		s   A


AAc                   [         R                  R                  S[        U 5      -  5      R	                  [
        5      nUnUR                  UR                  :  a<  UR                  UR                  :  a!  US-  nUR                  UR                  :  a  M!  O^UR                  UR                  S-  :  aA  UR                  UR                  S-  :  a$  US-  nUR                  UR                  S-  :  a  M$  [        XR                  -  5      u  p4[        US9n[        X-  5      n[        UR                  UR                  UUSS9U4$ )as  
Slow, last chance function that returns a tuple of a single tuplet, probably with a non
power of 2 denominator (such as 7:6) that represents the quarterLength and the
DurationTuple that should be used to express the note.

This could be a double-dotted note, but also a tuplet:

>>> duration.quarterLengthToNonPowerOf2Tuplet(7)
(<music21.duration.Tuplet 8/7/quarter>, DurationTuple(type='breve', dots=0, quarterLength=8.0))

>>> duration.quarterLengthToNonPowerOf2Tuplet(7/16)
(<music21.duration.Tuplet 8/7/64th>, DurationTuple(type='eighth', dots=0, quarterLength=0.5))

>>> duration.quarterLengthToNonPowerOf2Tuplet(7/3)
(<music21.duration.Tuplet 12/7/16th>, DurationTuple(type='whole', dots=0, quarterLength=4.0))

And of course:

>>> duration.quarterLengthToNonPowerOf2Tuplet(1)
(<music21.duration.Tuplet 1/1/quarter>,
 DurationTuple(type='quarter', dots=0, quarterLength=1.0))
r      r   Tr   r   durationActualr   frozen)r   r   
from_floatfloatlimit_denominatorDENOM_LIMIT	numeratordenominatorr   DurationdurationTupleFromQuarterLengthTuplet)r   qFracqFracOrgclosestSmallerTypeunused_matchtupletDurationrepresentativeDurations          r*    quarterLengthToNonPowerOf2Tupletr     s&   2 ))!eDk/:LL[YEH***oo 1 11AIE oo 1 11	5,,q0	0oo 1 1A 55AIE oo 1 1A 55 (B$IZIZBZ'[$#56N;E<LMU__%*%6%6"0"0	
 -. .r)   c                   / n/ n[         R                  5        H  u  pVUR                  Xe45        M     UR                  5         [	        U 5      n U H  u  pxU H  n	[	        Xy-  5      n
[        SU	5       Hg  n[         HZ  n[        R                  " U5      n[	        X-  U-  5      nX:X  d  M0  [        X5      n[        U	UUUSS9nUR                  U5          Me     Mi     [        U5      U:  d  M    O   [        U5      U:  d  M    U$    U$ )a  
Returns a list of possible Tuplet objects for a
given `qLen` (quarterLength). As there may be more than one
possible solution, the `maxToReturn` integer specifies the
maximum number of values returned.

Searches for numerators specified in duration.defaultTupletNumerators
(3, 5, 7, 11, 13). Does not return dotted tuplets, nor nested tuplets.

Note that 4:3 tuplets won't be found, but will be found as dotted notes
by dottedMatch.


>>> duration.quarterLengthToTuplet(0.33333333)
[<music21.duration.Tuplet 3/2/eighth>, <music21.duration.Tuplet 3/1/quarter>]

>>> duration.quarterLengthToTuplet(0.20)
[<music21.duration.Tuplet 5/4/16th>,
 <music21.duration.Tuplet 5/2/eighth>,
 <music21.duration.Tuplet 5/1/quarter>]


By specifying only 1 `maxToReturn`, a single-length list containing the
Tuplet with the smallest type will be returned.

>>> duration.quarterLengthToTuplet(0.3333333, 1)
[<music21.duration.Tuplet 3/2/eighth>]

>>> tup = duration.quarterLengthToTuplet(0.3333333, 1)[0]
>>> tup.tupletMultiplier()
Fraction(2, 3)
r   Tr   )rD   itemsr   sortr
   r   POSSIBLE_DOTS_IN_TUPLETSr   r   durationTupleFromTypeDotsr   len)r   maxToReturntupletNumeratorspostdurationToTypekeyvalue	typeValuetypeKeyiqLenBasemnumberOfDotstupletMultiplierqLenCandidater   	newTuplets                    r*   quarterLengthToTupletr     s   J DN$**,
ul+ -$<D,	!Aim,H1a[$<L'-';';L'I$$*8<:J+J$KM$,)B7)Y$*Q=>:H:H26	%-	 I. %= !  4yK') "* t9#K5 -4 Kr)   i   c           	     "    U S:  a  SU -  nOSn[         U   n[        US5      n[        U4S5      $ ! [         a     Of = f[	        U 5      u  pBUSLa  [        X$5      n[        U4S5      $ U S:X  a  [        SS5      n[        U4S5      $ [        U 5      n  [        U 5      u  pV[        U5        O&! [         a    [        [        SSU S94S5      s $ f = f[        U S5      nU(       a  [        US   R                  4US   5      $ [        US5      /n[        U [        U   -
  5      n	[        S	5       H  n
[	        U	5      u  pBUSLa3  [        X$5      nUR                  U5        [        [        U5      S5      s  $  [        U	5      u  pVO! [         a       O1f = fU	[        U   -
  n	[        US5      nUR                  U5        M      [!        U 5      u  pO&! [         a    [        [        SSU S94S5      s $ f = fS
Ul        [        U4U5      $ )a  
Returns a 2-element namedtuple of (components, tuplet)

Components is a tuple of DurationTuples (normally one) that
add up to the qLen when multiplied by the tuplet multiplier.

Tuplet is a single :class:`~music21.duration.Tuplet` that adjusts all components.

(All quarterLengths can, technically, be notated as a single unit
given a complex enough tuplet, as a last resort will look up to 199 as a tuplet type).

>>> duration.quarterConversion(2)
QuarterLengthConversion(components=(DurationTuple(type='half', dots=0, quarterLength=2.0),),
    tuplet=None)

>>> duration.quarterConversion(0.5)
QuarterLengthConversion(components=(DurationTuple(type='eighth', dots=0, quarterLength=0.5),),
    tuplet=None)

Dots are supported

>>> duration.quarterConversion(3)
QuarterLengthConversion(components=(DurationTuple(type='half', dots=1, quarterLength=3.0),),
    tuplet=None)

>>> duration.quarterConversion(6.0)
QuarterLengthConversion(components=(DurationTuple(type='whole', dots=1, quarterLength=6.0),),
    tuplet=None)

Double and triple dotted half note.

>>> duration.quarterConversion(3.5)
QuarterLengthConversion(components=(DurationTuple(type='half', dots=2, quarterLength=3.5),),
    tuplet=None)

>>> duration.quarterConversion(3.75)
QuarterLengthConversion(components=(DurationTuple(type='half', dots=3, quarterLength=3.75),),
    tuplet=None)

A triplet quarter note, lasting 0.6666 qLen
Or, a quarter that is 1/3 of a half.
Or, a quarter that is 2/3 of a quarter.

>>> duration.quarterConversion(2/3)
QuarterLengthConversion(components=(DurationTuple(type='quarter', dots=0, quarterLength=1.0),),
    tuplet=<music21.duration.Tuplet 3/2/quarter>)
>>> tup = duration.quarterConversion(2/3).tuplet
>>> tup
<music21.duration.Tuplet 3/2/quarter>
>>> tup.durationActual
DurationTuple(type='quarter', dots=0, quarterLength=1.0)


A triplet eighth note, where 3 eights are in the place of 2.
Or, an eighth that is 1/3 of a quarter
Or, an eighth that is 2/3 of eighth

>>> duration.quarterConversion(1/3)
QuarterLengthConversion(components=(DurationTuple(type='eighth', dots=0, quarterLength=0.5),),
    tuplet=<music21.duration.Tuplet 3/2/eighth>)

A half that is 1/3 of a whole, or a triplet half note.
Or, a half that is 2/3 of a half

>>> duration.quarterConversion(4/3)
QuarterLengthConversion(components=(DurationTuple(type='half', dots=0, quarterLength=2.0),),
    tuplet=<music21.duration.Tuplet 3/2/half>)

>>> duration.quarterConversion(1/6)
QuarterLengthConversion(components=(DurationTuple(type='16th', dots=0, quarterLength=0.25),),
    tuplet=<music21.duration.Tuplet 3/2/16th>)


A sixteenth that is 1/5 of a quarter
Or, a sixteenth that is 4/5ths of a 16th

>>> duration.quarterConversion(1/5)
QuarterLengthConversion(components=(DurationTuple(type='16th', dots=0, quarterLength=0.25),),
    tuplet=<music21.duration.Tuplet 5/4/16th>)


A 16th that is  1/7th of a quarter
Or, a 16th that is 4/7 of a 16th

>>> duration.quarterConversion(1/7)
QuarterLengthConversion(components=(DurationTuple(type='16th', dots=0, quarterLength=0.25),),
    tuplet=<music21.duration.Tuplet 7/4/16th>)

A 4/7ths of a whole note, or
A quarter that is 4/7th of a quarter

>>> duration.quarterConversion(4/7)
QuarterLengthConversion(components=(DurationTuple(type='quarter', dots=0, quarterLength=1.0),),
                        tuplet=<music21.duration.Tuplet 7/4/quarter>)

If a duration is not containable in a single unit, this method
will break off the largest type that fits within this type
and recurse, adding as many units as necessary.

>>> duration.quarterConversion(2.5)
QuarterLengthConversion(components=(DurationTuple(type='half', dots=0, quarterLength=2.0),
                                    DurationTuple(type='eighth', dots=0, quarterLength=0.5)),
                        tuplet=None)


Since tuplets apply to the entire Duration (since v2), expect some odder tuplets for unusual
values that should probably be split generally:

>>> duration.quarterConversion(7/3)
QuarterLengthConversion(components=(DurationTuple(type='whole', dots=0, quarterLength=4.0),),
    tuplet=<music21.duration.Tuplet 12/7/16th>)

Note that because this method is cached, the tuplet returned will be reused, so
it should generally be copied before assigning.

>>> duration.quarterConversion(1/3).tuplet is duration.quarterConversion(1/3).tuplet
True


This is a very close approximation:

>>> duration.quarterConversion(0.18333333333333)
QuarterLengthConversion(components=(DurationTuple(type='16th', dots=0, quarterLength=0.25),),
    tuplet=<music21.duration.Tuplet 15/11/256th>)

>>> duration.quarterConversion(0.0)
QuarterLengthConversion(components=(DurationTuple(type='zero', dots=0, quarterLength=0.0),),
    tuplet=None)


>>> duration.quarterConversion(99.0)
QuarterLengthConversion(components=(DurationTuple(type='inexpressible',
                                                  dots=0,
                                                  quarterLength=99.0),),
                        tuplet=None)
r   r   NFrB   inexpressible)r   r   r   r   r   T)rE   r   ry   KeyErrorr   r
   r   r   r    DurationTupler   r   rD   r   r   tupler   r   )r   qLenDictr   dtr   r   r   tupleCandidatesr{   qLenRemainderr   r|   	components                r*   quarterConversionr     sl   Z!84xHH!(+&w2&ud33 
  %MDe&w5&ud33qy&vq1&ud33 $<DS+Ed+K()* S&?;<DH)J (LMQS 	SS ,D!4O&Q..0A
 	
 ,,>BCJ 4.1C"DDEM 1X#M2%*79Bb!*5+<dCC	/I-/X,  		%7I(JJ&'91=" $S<TB	 S&?;<DH)J (LMQS 	SS
 FM"I<88sB   /2 
??B0 0 CC<F


FF	G  G:9G:c                n   U [         ;   a
  [         U    nO[        SU  S35      eUnUb:  [        U5      S:  a+  U H$  nUS:  d  M  U[        R                  " U5      -  nM&     OU[        R                  " U5      -  nUb6  U(       a/  [        U5      nU H  n[        XWR                  5       -  5      nM      U$ )a  
Given a rhythm type (`dType`), number of dots (`dots`), an optional list of
Tuplet objects (`tuplets`), and a (very) optional list of
Medieval dot groups (`dotGroups`), return the equivalent quarter length.

>>> duration.convertTypeToQuarterLength('whole')
4.0
>>> duration.convertTypeToQuarterLength('16th')
0.25
>>> duration.convertTypeToQuarterLength('quarter', 2)
1.75

>>> tup = duration.Tuplet(numberNotesActual=5, numberNotesNormal=4)
>>> duration.convertTypeToQuarterLength('quarter', 0, [tup])
Fraction(4, 5)
>>> duration.convertTypeToQuarterLength('quarter', 1, [tup])
Fraction(6, 5)

>>> tup = duration.Tuplet(numberNotesActual=3, numberNotesNormal=4)
>>> duration.convertTypeToQuarterLength('quarter', 0, [tup])
Fraction(4, 3)

Also can handle those rare medieval dot groups
(such as dotted-dotted half notes that take a full measure of 9/8.
Conceptually, these are dotted-(dotted-half) notes.  See
trecento.trecentoCadence for more information
).
>>> duration.convertTypeToQuarterLength('half', dots=1, dotGroups=[1, 1])
4.5

Unknown values raise `DurationException`:

>>> duration.convertTypeToQuarterLength('minim')
Traceback (most recent call last):
music21.duration.DurationException: no such type (minim) available for conversion
zno such type (z) available for conversionr   r   )rD   r    r   r   r   r
   r   )dTyper   r   	dotGroupsdurationFromType	qtrLength	innerDotstups           r*   convertTypeToQuarterLengthr     s    V )%0UG#=>@ 	@ +I Y!!3"I1}V11)<<	 # 	V))$//	w9%	Cy+?+?+AABI r)   c                x    Sn[         R                  5        H  u  p#X:X  d  M  Un  O   Uc  [        SU  35      eU$ )aL  
Convert a duration type string (`dType`) to a numerical scalar representation that shows
how many of that duration type fits within a whole note.

>>> duration.convertTypeToNumber('quarter')
4.0
>>> duration.convertTypeToNumber('half')
2.0
>>> duration.convertTypeToNumber('1024th')
1024.0
>>> duration.convertTypeToNumber('maxima')
0.125

These other types give these results:

>>> duration.convertTypeToNumber('zero')
0.0
>>> duration.convertTypeToNumber('complex')
Traceback (most recent call last):
music21.duration.DurationException: Could not determine durationNumber from complex
N(Could not determine durationNumber from )rE   r   r    )r   
dTypeFoundnumtypeNames       r*   convertTypeToNumberr   -  sM    , J(..0J	 1
 "J5' RSSr)   c                  J    \ rS rSr% S\S'   S\S'   S\S'   S r\S	 5       rS
rg)r   iO  strr   intr   r   r   c                2    [        U R                  U-  5      $ N)r   r   )selfamountToScales     r*   augmentOrDiminishDurationTuple.augmentOrDiminishT  s    -d.@.@=.PQQr)   c                     [         R                  U R                  5      $ ! [         a    [	        SU R                   35      ef = f)aP  
Converts type to an ordinal number where maxima = 1 and 1024th = 14;
whole = 4 and quarter = 6.  Based on duration.ordinalTypeFromNum

>>> a = duration.DurationTuple('whole', 0, 4.0)
>>> a.ordinal
4

>>> b = duration.DurationTuple('maxima', 0, 32.0)
>>> b.ordinal
1

>>> c = duration.DurationTuple('1024th', 0, 1/256)
>>> c.ordinal
14
r   )rG   r   r   
ValueErrorr    r   s    r*   ordinalDurationTuple.ordinalW  sK    $	H%++DII66 	H#:499+FH H	Hs	   ! #Ar"   N)	r$   r%   r&   r'   r}   r   propertyr  r(   r"   r)   r*   r   r   O  s.    
I
IR H Hr)   r   z$dict[tuple[str, int], DurationTuple]_durationTupleCacheTypeDotszdict[OffsetQL, DurationTuple] _durationTupleCacheQuarterLengthc                     [         U    $ ! [         aF    [        U 5      n [        U 5      u  pUSLa  [	        X!U 5      nU[         U '   Us $ [	        SSU 5      s $ f = f)a  
Returns a DurationTuple for a given quarter length
if the ql can be expressed as a type and number of dots
(no tuplets, no complex duration, etc.).  If it can't be expressed,
returns an "inexpressible" DurationTuple.

>>> dt = duration.durationTupleFromQuarterLength(3.0)
>>> dt
DurationTuple(type='half', dots=1, quarterLength=3.0)

If it's not possible, we return an "inexpressible" type:

>>> dt = duration.durationTupleFromQuarterLength(2.5)
>>> dt
DurationTuple(type='inexpressible', dots=0, quarterLength=2.5)
Fr   r   )r  r   r
   r   r   )qlr   r   nts       r*   r   r   t  sh    "
9/33 9BZ#B%wb1B35,R0I !R889s    >AAAc                    X4n [         U   $ ! [         ac     [        U    [        R                  " U5      -  nO'! [        [
        4 a  n[        SU  35      UeSnAff = f[        XU5      nU[         U'   Us $ f = f)a  
Returns a DurationTuple (which knows its quarterLength) for
a given type and dots (no tuplets)

>>> dt = duration.durationTupleFromTypeDots('quarter', 0)
>>> dt
DurationTuple(type='quarter', dots=0, quarterLength=1.0)
>>> dt2 = duration.durationTupleFromTypeDots('quarter', 0)
>>> dt is dt2
True

Also with keyword arguments.

>>> dt = duration.durationTupleFromTypeDots(durType='zero', dots=0)
>>> dt
DurationTuple(type='zero', dots=0, quarterLength=0.0)

Unknown values raise `DurationException`:

>>> dt = duration.durationTupleFromTypeDots(durType='minim', dots=0)
Traceback (most recent call last):
music21.duration.DurationException: Unknown type: minim

OMIT_FROM_DOCS

>>> dt in duration._durationTupleCacheTypeDots.values()
True
zUnknown type: N)r  r   rD   r   r   
IndexErrorr    r   )r   r   tpr	  er
  s         r*   r   r     s    : B*2.. 		(6+?+?+EEB*% 	# 	*	 7"-*,#B'		s/    
A; :A;A
AAA;:A;c            
         \ rS rSrSr    SSSSSSSSS	S
.                       SS jjjrS S jrS rS rS!S jr	 S"     S#S jjr
S$S jrS%S jrS%S jr\S&S j5       r\R                   S'S j5       r\S&S j5       r\R                   S(S j5       r\S 5       r\S 5       r\R                   S 5       r\S 5       r\R                   S 5       rSrg))r   i  a  
A tuplet object is a representation of a musical tuplet (like a triplet).
It expresses a ratio that modifies duration values and are stored in
Duration objects in a "tuple" (immutable list; since there can be nested
tuplets) in the duration's .tuplets property.

The primary representation uses two pairs of note numbers and durations.

The first pair of note numbers and durations describes the representation
within the tuplet, or the value presented by the context. This is called
"actual." In a standard 8th note triplet this would be 3, eighth, meaning
that a complete collection of this tuplet will be visually represented as
three eighth notes.  These
attributes are `numberNotesActual`, `durationActual`.

The second pair of note numbers and durations describes the space that
would have been occupied in a normal context. This is called "normal." In a
standard 8th note triplet this would be 2, eighth, meaning that a complete
collection of notes under this tuplet will occupy the space of two eighth notes.
These attributes are
`numberNotesNormal`, `durationNormal`.

If duration values are not provided then `durationActual` and `durationNormal` are
left as None -- meaning that it is unspecified what the duration that completes the
tuplet is.  And this tuplet just represents a Ratio.
PRIOR TO v4 `durationActual` and `durationNormal` were assumed to be eighths.

If only one duration, either `durationActual` or `durationNormal`, is
provided, both are set to the same value.

Note that this is a duration modifier, or a generator of ratios to scale
quarterLength values in Duration objects.

>>> myTup = duration.Tuplet(numberNotesActual=5, numberNotesNormal=4)
>>> print(myTup.tupletMultiplier())
4/5

We know that it is 5 in the place of 4, but 5 what in the place of 4 what?

>>> myTup.durationActual is None
True
>>> myTup
<music21.duration.Tuplet 5/4>

But we can change that:

>>> myTup.setDurationType('eighth')
>>> myTup.durationActual
DurationTuple(type='eighth', dots=0, quarterLength=0.5)
>>> myTup
<music21.duration.Tuplet 5/4/eighth>


In this case, the tupletMultiplier is a float because it can be expressed
as a binary number:

>>> myTup2 = duration.Tuplet(8, 5)
>>> tm = myTup2.tupletMultiplier()
>>> tm
0.625

Here, six sixteenth notes occupy the space of four sixteenth notes.

>>> myTup2 = duration.Tuplet(6, 4, '16th')
>>> print(myTup2.durationActual.type)
16th
>>> print(myTup2.durationNormal.type)
16th

>>> print(myTup2.tupletMultiplier())
2/3

Tuplets may be frozen, in which case they become immutable. Tuplets
which are attached to Durations are automatically frozen.  Otherwise
a tuplet could change without the attached duration knowing about it,
which would be a real problem.

>>> myTup.frozen = True
>>> myTup.tupletActual = [3, 2]
Traceback (most recent call last):
music21.duration.TupletException: A frozen tuplet (or one attached to a duration)
    has immutable length.

>>> myHalf = duration.Duration('half')
>>> myHalf.appendTuplet(myTup2)
>>> myTup2.tupletActual = [5, 4]
Traceback (most recent call last):
music21.duration.TupletException: A frozen tuplet (or one attached to a duration)
    has immutable length.

Note that if you want to create a note with a simple Tuplet attached to it,
you can just change the quarterLength of the note:

>>> myNote = note.Note('C#4')
>>> myNote.duration.quarterLength = 0.8
>>> myNote.duration.quarterLength
Fraction(4, 5)
>>> myNote.duration.fullName
'Quarter Quintuplet (4/5 QL)'

>>> myNote.duration.tuplets
(<music21.duration.Tuplet 5/4/quarter>,)

OMIT_FROM_DOCS
We should also have a tupletGroup spanner.

object that groups note objects into larger groups.
# TODO: use __setattr__ to freeze all properties, and make a metaclass
# exceptions: tuplet type, tuplet id: things that don't affect length
Nr   r   Tabover   F)tupletIdnestedLevelr   bracket	placementtupletActualShowtupletNormalShowr   c               <   SU l         S U l        S U l        XPl        X`l        Xl        Ub  Uc  UnOUc  Ub  UnUbZ  [        U[        5      (       a  [        US5      U l	        O3[        U[        5      (       a  [        US   US   5      U l	        OX0l	        X l        UbZ  [        U[        5      (       a  [        US5      U l        O3[        U[        5      (       a  [        US   US   5      U l        OX@l        Xpl        Xl        Xl        Xl        Xl        Xl         g )NFr   r   )r   _durationNormal_durationActualr  r  r   r   r   r   r   r   r   r   r   r  r  r  r  )r   r   r   r   r   r  r  r   r  r  r  r  r   keywordss                 r*   __init__Tuplet.__init__.  s*   "  4837 !& '8%.*@+N#(B+N %.#..&?PQ&R#NE22&?q@Q@Nq@Q'S# '5#  '8%.#..&?PQ&R#NE22&?q@Q@Nq@Q'S# '5#( !%	7>6?3C3C r)   c                    [        U[        5      (       d  [        $ S H"  n[        XS5      n[        XS5      nX4:w  d  M"    g   g)a  
Two Tuplets are equal if their numbers are equal and durations are equal.

Visual details (type, bracket, placement, tupletActualShow, etc.) do
not matter.

>>> triplet1 = duration.Tuplet(3, 2)
>>> triplet2 = duration.Tuplet(3, 2)
>>> triplet1 == triplet2
True
>>> quadruplet = duration.Tuplet(4, 3)
>>> triplet1 == quadruplet
False
>>> triplet3 = duration.Tuplet(3, 2, 'half')
>>> triplet1 == triplet3
False
)r   r   r   r   NFT)r   r   NotImplementedgetattr)r   otherattrmyAttr	otherAttrs        r*   __eq__Tuplet.__eq__  sI    $ %((!!9DT.FT2I"9 r)   c                    U R                   < SU R                  < 3nU R                  b  USU R                  R                   3-  nU$ )N/)r   r   r   r   )r   base_reps     r*   _reprInternalTuplet._reprInternal  sO    ,,/q1G1G0JK*!D//44566Hr)   c                8    U R                   SL a  [        S5      eg )NTzEA frozen tuplet (or one attached to a duration) has immutable length.)r   r-   r  s    r*   _checkFrozenTuplet._checkFrozen  s%    ;;$!WY Y r)   c                   US:  d  [        S5      e[        R                  " U 5      nSUl        UR                  b   UR                  R                  U5      Ul        UR                  b   UR                  R                  U5      Ul        U$ )a  
Given a number greater than zero,
multiplies the current quarterLength of the
duration by the number and resets the components
for the duration (by default).  Or if inPlace is
set to False, returns a new duration that has
the new length.

# TODO: add inPlace setting.

>>> a = duration.Tuplet()
>>> a.setRatio(6, 2)
>>> a.tupletMultiplier()
Fraction(1, 3)
>>> a.setDurationType('eighth')
>>> a.durationActual
DurationTuple(type='eighth', dots=0, quarterLength=0.5)

>>> c = a.augmentOrDiminish(0.5)
>>> c.durationActual
DurationTuple(type='16th', dots=0, quarterLength=0.25)

>>> c.tupletMultiplier()
Fraction(1, 3)

Raises ValueError if `amountToScale` is negative.

>>> a.augmentOrDiminish(-1)
Traceback (most recent call last):
ValueError: amountToScale must be greater than zero
r   'amountToScale must be greater than zeroF)r  copydeepcopyr   r   r   r   )r   r   r   s      r*   r   Tuplet.augmentOrDiminish  s    @ q FGG }}T" *##55!#  *##55!#  r)   c                    U R                  5         [        R                  " U5      (       a   [        U[        5      (       d  [        U5      n[        X5      U l        [        X5      U l        g)a  
Set both durationActual and durationNormal from either a string type or
a quarterLength.  optional dots can add dots to a string type (or I suppose
a quarterLength.)

>>> a = duration.Tuplet()
>>> a.tupletMultiplier()
Fraction(2, 3)
>>> a.totalTupletLength()
1.0
>>> a.setDurationType('half')
>>> a.durationNormal
DurationTuple(type='half', dots=0, quarterLength=2.0)
>>> a.tupletMultiplier()
Fraction(2, 3)
>>> a.totalTupletLength()
4.0
>>> a.setDurationType('half', dots=1)
>>> a.durationNormal
DurationTuple(type='half', dots=1, quarterLength=3.0)
>>> a.totalTupletLength()
6.0

>>> a.setDurationType(2.0)
>>> a.totalTupletLength()
4.0
>>> a.setDurationType(4.0)
>>> a.totalTupletLength()
8.0

N)	r,  r   isNumr   r   r   r   r   r   )r   r   r   s      r*   setDurationTypeTuplet.setDurationType  sP    H 	<<  GS)A)A09G7F7Fr)   c                <    U R                  5         Xl        X l        g)af  
Set the ratio of actual divisions to represented in normal divisions.
A triplet is 3 actual in the time of 2 normal.

>>> a = duration.Tuplet()
>>> a.tupletMultiplier()
Fraction(2, 3)
>>> a.setRatio(6, 2)
>>> a.numberNotesActual
6
>>> a.numberNotesNormal
2
>>> a.tupletMultiplier()
Fraction(1, 3)

One way of expressing 6/4-ish triplets without numbers:

>>> a = duration.Tuplet()
>>> a.setRatio(3, 1)
>>> a.durationActual = duration.durationTupleFromTypeDots('quarter', 0)
>>> a.durationNormal = duration.durationTupleFromTypeDots('half', 0)
>>> a.tupletMultiplier()
Fraction(2, 3)
>>> a.totalTupletLength()
2.0
N)r,  r   r   )r   actualnormals      r*   setRatioTuplet.setRatio(  s    6 	!'!'r)   c                    U R                   nU R                  b  U R                  R                  nOSn[        X-  5      $ )a  
The total duration in quarter length of the tuplet as defined,
assuming that enough notes existed to fill all entire tuplet as defined.

For instance, 3 quarters in the place of 2 quarters = 2.0
5 half notes in the place of a 2 dotted half notes = 6.0
(In the end it's only the denominator that matters)

If durationActual or durationNormal are None, then they will be
assumed to be eighth notes (for the basic 3:2 eighth-note triplet)

>>> a = duration.Tuplet()
>>> a.totalTupletLength()
1.0

>>> a.numberNotesActual = 3
>>> a.numberNotesNormal = 2
>>> a.setDurationType('half')
>>> a.totalTupletLength()
4.0

Let's make it five halfs in the place of four:

>>> a.setRatio(5, 4)
>>> a.setDurationType('half')
>>> a.totalTupletLength()
8.0

Now five halfs in the place of two whole notes (same thing):

>>> a.setRatio(5, 2)
>>> a.totalTupletLength()
4.0
>>> a.durationNormal = duration.durationTupleFromTypeDots('whole', 0)
>>> a.totalTupletLength()
8.0
r8   )r   r   r   r
   )r   ndurationNormalQuarterLengths      r*   totalTupletLengthTuplet.totalTupletLengthG  sB    L ""**.*=*=*K*K'*-'a566r)   c                    U R                   b  U R                   R                  nOSnU R                  5       n[        X!U R                  -  -  5      $ )a  
Get a Fraction() by which to scale the duration that
this Tuplet is associated with.

>>> myTuplet = duration.Tuplet()
>>> myTuplet.tupletMultiplier()
Fraction(2, 3)
>>> myTuplet.tupletActual = [5, duration.Duration('eighth')]
>>> myTuplet.numberNotesActual
5
>>> myTuplet.durationActual.type
'eighth'
>>> print(myTuplet.tupletMultiplier())
2/5
>>> myTuplet.numberNotesNormal = 4
>>> print(myTuplet.tupletMultiplier())
4/5
r8   )r   r   r?  r
   r   )r   lengthActualttls      r*   r   Tuplet.tupletMultipliert  sM    & *..<<LL$$&cD,B,BBCDDr)   c                    U R                   $ )ak  
durationActual is a DurationTuple that represents the notes that are
actually present and counted in a tuplet.  For instance, in a 7
dotted-eighth in the place of 2 double-dotted quarter notes tuplet,
the duration actual would be this:

>>> d = duration.Tuplet(7, 2)
>>> print(d.durationActual)
None
>>> d.durationActual = duration.Duration('eighth', dots=1)

Notice that the Duration object gets converted to a DurationTuple.

>>> d.durationActual
DurationTuple(type='eighth', dots=1, quarterLength=0.75)

>>> d.durationActual = 'quarter'
>>> d.durationActual
DurationTuple(type='quarter', dots=0, quarterLength=1.0)
)r  r  s    r*   r   Tuplet.durationActual      , ###r)   c                   U R                  5         [        U[        5      (       d  Uc  Xl        g [        U[        5      (       ap  [        UR                  5      S:  a&  [        R                  " U5      nUR                  5         [        UR                  UR                  UR                  5      U l        g [        U[        5      (       a  [        USS9U l        g g Nr   r   )r   )r,  r   r   r  r   r   r{   r0  r1  consolidater   r   r   r   r   )r   dAs     r*   r   rF    s    b-((BJ#% H%%2==!A%]]2& #0"''2CSCS#TD C  #<Ra#HD  !r)   c                    U R                   $ )av  
durationNormal is a DurationTuple that represents the notes that
would be present in the space normally (if there were no tuplets).  For instance, in a 7
dotted-eighth in the place of 2 double-dotted quarter notes tuplet,
the durationNormal would be:

>>> d = duration.Tuplet(7, 2)
>>> print(d.durationNormal)
None
>>> d.durationNormal = duration.Duration('quarter', dots=2)

Notice that the Duration object gets converted to a DurationTuple:

>>> d.durationNormal
DurationTuple(type='quarter', dots=2, quarterLength=1.75)

>>> d.durationNormal = 'half'
>>> d.durationNormal
DurationTuple(type='half', dots=0, quarterLength=2.0)
)r  r  s    r*   r   Tuplet.durationNormal  rG  r)   c                   U R                  5         [        U[        5      (       d  Uc  Xl        g [        U[        5      (       ap  [        UR                  5      S:  a&  [        R                  " U5      nUR                  5         [        UR                  UR                  UR                  5      U l        g [        U[        5      (       a  [        USS9U l        g g rI  )r,  r   r   r  r   r   r{   r0  r1  rJ  r   r   r   r   r   )r   dNs     r*   r   rM    s    b-((BJ#% H%%2==!A%]]2& #0"''2CSCS#TD C  #<Ra#HD  !r)   c                    U R                   nU R                  nUS:X  a  US:X  a  gUS:X  a  US;   a  gUS:X  a  US:X  a  g	US
:X  a  US:X  a  g[        R                  " USS9nSU SU U 3$ )a|  
Return the most complete representation of this tuplet in a readable
form.

>>> tup = duration.Tuplet(numberNotesActual=5, numberNotesNormal=2)
>>> tup.fullName
'Quintuplet'

>>> tup = duration.Tuplet(numberNotesActual=3, numberNotesNormal=2)
>>> tup.fullName
'Triplet'

>>> tup = duration.Tuplet(numberNotesActual=17, numberNotesNormal=14)
>>> tup.fullName
'Tuplet of 17/14ths'
rH   r   TripletrI   )r   r   
Quintuplet   r   	SextupletrJ   	SeptupletT)pluralz
Tuplet of r'  )r   r   r   ordinalAbbreviation)r   	numActual	numNormalordStrs       r*   fullNameTuplet.fullName  s    & **	**	 >i1n!^	V 3!^	Q!^	Q++IdCI;a	{6(;;r)   c                2    U R                   U R                  /$ )zK
Get or set a two element list of number notes actual and duration
actual.
)r   r   r  s    r*   tupletActualTuplet.tupletActual  s     &&(;(;<<r)   c                B    U R                  5         Uu  U l        U l        g r   )r,  r   r   r   tupLists     r*   r^  r_        6=3 3r)   c                2    U R                   U R                  4$ )zK
Get or set a two element list of number notes actual and duration
normal.
)r   r   r  s    r*   tupletNormalTuplet.tupletNormal	  s     %%t':':::r)   c                B    U R                  5         Uu  U l        U l        g r   )r,  r   r   ra  s     r*   re  rf    rc  r)   )r  r  r  r   r   r   r  r   r   r  r  r  r  r   )rH   r   NN)r   r   r   r   r   7DurationTuple | Duration | str | tuple[str, int] | Noner   rh  r  r   r  r   r   
TupletTyper  zt.Literal[True, False, 'slur']r  zt.Literal['above', 'below']r  TupletShowOptionsr  rj  r   boolreturnrk  )r   zint | floatr   )r   z&str | int | float | fractions.Fractionr   r   rm  None)r8  r   r9  r   rm  ro  rm  r   )rm  DurationTuple | None)rK  %DurationTuple | Duration | str | None)rO  rr  )r$   r%   r&   r'   __doc__r  r$  r)  r,  r   r5  r:  r?  r   r  r   setterr   r[  r^  re  r(   r"   r)   r*   r   r     s   m` "#!"JNJNf 2618.6.2ff f H	f
 Hf f f f 0f /f ,f ,f fX>Y6v )G1)G )G 
	)GV(>+7ZE6 $ $. I I $ $. 
I 
I < <B = = > > ; ; > >r)   r   c                     \ rS rSrSrSrSrSSS.r S5SS	SSSSS
.             S6S jjjrS r	S r
S rS rS7S jrS8S jr\" \\5      rSS. S9S jjrS:S jrS;S jrS<S jrS rS=S jrS r S; S>S jjrS7S jrS rS rSS.S jrS  r\S?S! j5       r\R>                  S@S" j5       r\SAS# j5       r \ R>                  SBS$ j5       r \SCS% j5       r!\!R>                  SDS& j5       r!\SES' j5       r"\S7S( j5       r#\SFS) j5       r$\SGS* j5       r%SHS+ jr&SIS, jr'\" \&\'S-S.9r(\SJS/ j5       r)\)R>                  SKS0 j5       r)SHS1 jr*\SES2 j5       r+\+R>                  SLS3 j5       r+S4r,g)Mr   i  a  
Durations are one of the most important objects in music21. A Duration
represents a span of musical time measurable in terms of quarter notes (or
in advanced usage other units). For instance, "57 quarter notes" or "dotted
half tied to quintuplet sixteenth note" or simply "quarter note."

A Duration object is made of one or more immutable DurationTuple objects stored on the
`components` list. A Duration created by setting `quarterLength` sets the attribute
:attr:`expressionIsInferred` to True, which indicates that callers
(such as :meth:`~music21.stream.makeNotation.splitElementsToCompleteTuplets`)
can express this Duration using another combination of components that sums to the
`quarterLength`. Otherwise, `expressionIsInferred` is set to False, indicating that
components are not allowed to mutate.

Multiple DurationTuples in a single Duration may be used to express tied
notes, or may be used to split duration across barlines or beam groups.
Some Duration objects are not expressible as a single notation unit.

Duration objects are not Music21Objects.

If a single argument is passed to Duration() and it is a string, then it is
assumed to be a type, such as 'half', 'eighth', or '16th', etc.  If that
single argument is a number then it is assumed to be a quarterLength (2 for
half notes, 0.5 for eighth notes, 0.75 for dotted eighth notes, 0.333333333
for a triplet eighth, etc.).  If one or more named arguments are passed
then the Duration() is configured according to those arguments.  Supported
arguments are 'type', 'dots', 'quarterLength', or 'components'.

Example 1: a triplet eighth configured by quarterLength:

>>> d = duration.Duration(0.333333333)
>>> d.type
'eighth'

>>> d.tuplets
(<music21.duration.Tuplet 3/2/eighth>,)

Example 2: A Duration made up of multiple
:class:`music21.duration.DurationTuple` objects automatically configured by
the specified quarterLength.

>>> d2 = duration.Duration(0.625)
>>> d2.type
'complex'

>>> d2.components
(DurationTuple(type='eighth', dots=0, quarterLength=0.5),
 DurationTuple(type='32nd', dots=0, quarterLength=0.125))

>>> d2.expressionIsInferred
True

Example 3: A Duration configured by keywords.

>>> d3 = duration.Duration(type='half', dots=2)
>>> d3.quarterLength
3.5
>>> d3.expressionIsInferred
False
F)_linked_components
_qtrLength_tuplets_componentsNeedUpdating_quarterLengthNeedsUpdating_typeNeedsUpdating_unlinkedType
_dotGroupsexpressionIsInferredclienta  
             Boolean indicating whether this duration was created from a
             number rather than a type and thus can be changed to another
             expression.  For instance the duration of 0.5 is generally
             an eighth note, but in the middle of a triplet group might be
             better written as a dotted-eighth triplet.  If expressionIsInferred
             is True then `music21` can change it according to complex.  If
             False, then the type, dots, and tuplets are considered immutable.

             >>> d = duration.Duration(0.5)
             >>> d.expressionIsInferred
             True

             >>> d = duration.Duration('eighth')
             >>> d.expressionIsInferred
             False
             a"  
            A duration's "client" is the object that holds this
            duration as a property.  It is informed whenever the duration changes.

            >>> n = note.Note('C#5', type='whole')
            >>> d = n.duration
            >>> d.client is n
            True
            )r  r  Nr   )r   r   r   durationTupler{   r  c                 S U l         SU l        SU l        SU l        S U l        SU l        SU l        SU l        SU l        SU l        SU l	        SU l
        Ubu  [        U[        [        [        R                  45      (       a  Uc  UnOE[        U[         5      (       a  Uc  UnO*[        U["        5      (       a  Uc  UnO[%        SU S35      eUb  U R'                  USS9  Ub)  [(        R*                  " [,        ["        S	4   U5      U l        Ub  [1        X#5      n	U R'                  U	SS9  OUb  X@l        SU l
        Xpl         g )
NFrn  r"   rC   TzCannot parse argument z or conflicts with keywords_skipInform.)r  rz  r{  r|  r}  r~  ry  rx  rw  rv  r  r   r   r   r   r   r   r   	TypeErroraddDurationTupletcastr   r{   r   r   )
r   typeOrDurationr   r   r   r  r{   r  r  r
  s
             r*   r  Duration.__init__  sW     04',$+0("''++/.0$' 79 ,1($)!%.3y7I7I*J   - 5 .NC00T\%NM::}?T .,^,<<WX  $!!-T!B!ffU=#+=%>
KDO *46B!!"$!7&!.(,D% r)   c                   [        U5      [        U 5      La  gU R                  UR                  :w  a  g[        U R                  5      [        UR                  5      :w  a  gU R                  (       d  gU R                   UR                   :w  a  gU R                  UR                  :w  a  gU R
                  UR
                  :w  a  gU R                  UR                  :w  a  gU R                  UR                  :w  a  gg)a  
Two durations are the same if their type, dots, tuplets, and
quarterLength are all the same.

>>> aDur = duration.Duration('quarter')
>>> bDur = duration.Duration('16th')
>>> cDur = duration.Duration('16th')
>>> aDur == bDur
False
>>> aDur != bDur
True

>>> cDur == bDur
True

>>> dDur = duration.Duration(0.0)
>>> eDur = duration.Duration(0.0)
>>> dDur == eDur
True

>>> tupDur1 = duration.Duration(2 / 3)
>>> tupDur2 = duration.Duration(2 / 3)
>>> tupDur1 == tupDur2
True

>>> graceDur1 = tupDur1.getGraceDuration()
>>> graceDur1 == tupDur1
False
>>> graceDur2 = tupDur2.getGraceDuration()
>>> graceDur1 == graceDur2
True

Link status must be the same:

>>> tupDur1.linked = False
>>> tupDur1 == tupDur2
False
FT)r   	isComplexr   r{   r   r   r   linked)r   r   s     r*   r$  Duration.__eq__  s    N ;d4j(>>U__,t3u'7'7#8899

"99

"<<5==(!4!44;;%,,&r)   c                    U R                   SL a  [        U R                  5      $ SU R                   SU R                   3$ )NTzunlinked type:z quarterLength:)r  r   r   r   r  s    r*   r)  Duration._reprInternal  s=    ;;$t))**#DII;od>P>P=QRRr)   c                   U R                   (       a  [        R                  " XS1S9$ [        U R                  5      S:X  aL  U R
                  S:X  a<  U R                  SL a-  U R                  (       d  U R                  U R                  S   S9$ U R                  (       d@  U R
                  S:X  a0  U R                  (       d  U R                  SL a  U R                  5       $ [        R                  " XS1S9$ )z!
Don't copy client when creating
r  )ignoreAttributesr   rn  Tr   )r  )	rz  r   defaultDeepcopyr   rw  r~  rv  ry  	__class__r   memos     r*   __deepcopy__Duration.__deepcopy__  s     ''))$zRR  !Q&OOt+LLD(>>0@0@0C>DD""//T)mm,,$&>>##))$zRRr)   c                (   SU l         U R                  (       as  U R                  (       ab  [        U R                  5      n[        UR                  5      U l        UR                  b&  [        R                  " UR                  5      4U l
        SU l        g)zt
This method will re-construct components and thus is not good if the
components are already configured as you like
FN)r{  r  r  r   rx  r   r{   r|   r0  r1  r   rz  )r   qlcs     r*   _updateComponentsDuration._updateComponents)  sb     ,1(;;444#DOO4C#CNN3DOzz% $cjj 9;',$r)   c                    U R                   $ )a  
Gets or sets the `.linked` property -- if linked (default) then type, dots, tuplets are
always coherent with quarterLength.  If not, then they are separate.

>>> d = duration.Duration(0.5)
>>> d.linked
True

Linked durations change other values when one changes:

>>> d.type = '16th'
>>> d.quarterLength
0.25

Unlinked values do not:

>>> d.linked = False
>>> d.type = 'half'
>>> d.quarterLength
0.25
)rv  r  s    r*   
_getLinkedDuration._getLinked8  s    , ||r)   c                
   US;  a  [        SU 35      eU R                  (       a  U R                  5         USL a!  U R                  SL a  U R                  U l        O"USL a  U R                  SL a  SU l        SU l        Xl        g )N)TFz&Linked can only be True or False, not FT)r  r{  _updateQuarterLengthrv  r   r}  rz  r   r   s     r*   
_setLinkedDuration._setLinkedP  sw    %DUGLMM++%%'E>dlld2!%Dd]t||u4/3D,+/D(r)   r  c               $   U R                   (       a  U R                  5         [        U[        5      (       a;  [	        UR
                  5      (       a  [        S5      eU R                  U4-   U l        Oo[        U[        5      (       a)  UR                   H  nU R                  U4-   U l        M     O1[        U5      R                   H  nU R                  U4-   U l        M     U R                  (       a  SU l        U(       d  U R                  5         gg)a  
Add a DurationTuple or a Duration's components to this Duration.
Does not simplify the Duration.  For instance, adding two
quarter notes results in two tied quarter notes, not one half note.
See `consolidate` below for more info on how to do that.

>>> a = duration.Duration('quarter')
>>> b = duration.durationTupleFromTypeDots('quarter', 0)
>>> a.addDurationTuple(b)
>>> a.quarterLength
2.0
>>> a.type
'complex'
,Invalid quarterLength for DurationTuple: nanTN)rz  r  r   r   r   r   r  rw  r   r{   r  r{  informClient)r   durr  cs       r*   r  Duration.addDurationTuple_  s    $ ''""$c=))S&&'' !OPP#//3&8DX&&^^#'#3#3qd#:  $ c]--#'#3#3qd#:  . ;;/3D, r)   c                <    SUl         U R                  U4-   U l        g)av  
Adds a new Tuplet to a Duration, sets the Tuplet's .frozen state to True,
and then informs the client (Note) that the duration has changed.

>>> tup = duration.Tuplet(3, 2)
>>> d = duration.Duration(1.0)
>>> d.appendTuplet(tup)
>>> d.quarterLength
Fraction(2, 3)
>>> t2 = duration.Tuplet(5, 4)
>>> d.appendTuplet(t2)
>>> d.quarterLength
Fraction(8, 15)
>>> tup.frozen
True
TN)r   ry  r   )r   r   s     r*   appendTupletDuration.appendTuplet  s    "  	}}	|3r)   c                .   US:  d  [        S5      e[        R                  " U 5      nU(       aK  / nUR                   H#  nUR	                  UR                  U5      5        M%     XCl        SU l        SU l        U$ SUl        U R                  U-  Ul	        U$ )a  
Given a number greater than zero, creates a new Duration object
after
multiplying the current quarterLength of the
duration by the number and resets the components
for the duration (by default).

Returns a new duration that has
the new length.

>>> aDur = duration.Duration()
>>> aDur.quarterLength = 1.5  # dotted quarter
>>> cDur = aDur.augmentOrDiminish(2)
>>> cDur.quarterLength
3.0
>>> cDur.type
'half'
>>> cDur.dots
1

`aDur` is not changed:

>>> aDur
<music21.duration.Duration 1.5>

A complex duration that cannot be expressed as a single notehead (component)

>>> bDur = duration.Duration()
>>> bDur.quarterLength = 2.125  # requires components
>>> bDur.quarterLength
2.125
>>> len(bDur.components)
2
>>> bDur.components
(DurationTuple(type='half', dots=0, quarterLength=2.0),
 DurationTuple(type='32nd', dots=0, quarterLength=0.125))


By default, when augmenting or diminishing, we will delete any
unusual components or tuplets:

>>> dDur = duration.Duration(1.5)
>>> dDur.appendTuplet(duration.Tuplet(3, 2))
>>> dDur
<music21.duration.Duration 1.0>
>>> dDur.dots
1
>>> dDur.tuplets
(<music21.duration.Tuplet 3/2>,)

>>> eDur = dDur.augmentOrDiminish(2)
>>> eDur
<music21.duration.Duration 2.0>
>>> eDur.dots
0
>>> eDur.tuplets
()

>>> eRetain = dDur.augmentOrDiminish(2, retainComponents=True)
>>> eRetain
<music21.duration.Duration 2.0>
>>> eRetain.dots
1
>>> eRetain.tuplets
(<music21.duration.Tuplet 3/2>,)

>>> fDur = duration.Duration(1.0)
>>> fDur.addDurationTuple(duration.DurationTuple('quarter', 0, 1.0))
>>> fDur
<music21.duration.Duration 2.0>
>>> fDur.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),
 DurationTuple(type='quarter', dots=0, quarterLength=1.0))

>>> gDur = fDur.augmentOrDiminish(0.5)
>>> gDur.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),)

>>> gRetain = fDur.augmentOrDiminish(0.5, retainComponents=True)
>>> gRetain.components
(DurationTuple(type='eighth', dots=0, quarterLength=0.5),
 DurationTuple(type='eighth', dots=0, quarterLength=0.5))

Negative values raise ValueError:

>>> fDur.augmentOrDiminish(-1)
Traceback (most recent call last):
ValueError: amountToScale must be greater than zero
r   r/  Tr"   )
r  r0  r1  r{   r   r   r|  r{  r   r   )r   r   retainComponentsr   newComponentsds         r*   r   Duration.augmentOrDiminish  s    t q FGG}}T"M__$$Q%8%8%GH %+O&*D#/3D,
  DL!%!3!3m!CDr)   c                \    SU l         SU l        SU l        SU l        U R	                  5         g)aC  
Permit all components to be removed.
This is needed for resetting to zero duration.

>>> a = duration.Duration()
>>> a.quarterLength = 6
>>> a.type
'whole'
>>> a.components
(DurationTuple(type='whole', dots=1, quarterLength=6.0),)

>>> a.clear()

>>> a.dots
0
>>> a.components
()
>>> a.type
'zero'
>>> a.quarterLength
0.0
rn  r"   FTN)r~  rw  rz  r{  r  r  s    r*   clearDuration.clear  s/    . ',$+/(r)   c                   [        U5      nU R                  (       d  [        S5      eXR                  :  a  [	        S5      eUS:  a  [	        S5      eUS:X  a  U R                  S   $ XR                  :X  a  U R                  S   $ Sn[        U R                  5       H%  u  p4[        X$R                  -   5      nX!:  d  M#  Us  $    [        S5      e)aM  
returns the index number of the duration component sounding at
the given quarter position.

Note that for 0 and the last value, the object is returned.


>>> components = []
>>> components.append(duration.Duration('quarter'))
>>> components.append(duration.Duration('quarter'))
>>> components.append(duration.Duration('quarter'))

>>> a = duration.Duration()
>>> a.components = components
>>> a.quarterLength
3.0
>>> a.componentIndexAtQtrPosition(0.5)
0
>>> a.componentIndexAtQtrPosition(1.5)
1
>>> a.componentIndexAtQtrPosition(2.5)
2


this is odd behavior:

e.g. given d1, d2, d3 as 3 quarter notes and
self.components = [d1, d2, d3]

then

self.componentIndexAtQtrPosition(1.5) == d2
self.componentIndexAtQtrPosition(2.0) == d3
self.componentIndexAtQtrPosition(2.5) == d3

Currently sometimes returns the component itself.  Changing in v7.
z5Need components to run getComponentIndexAtQtrPositionz)position is after the end of the durationr   z,position is before the start of the durationrC   z.Could not match quarterLength within an index.)r
   r{   r    r   r  	enumerate)r   quarterPositioncurrentPositionr   r   s        r*   componentIndexAtQtrPosition$Duration.componentIndexAtQtrPosition"  s    L !1#GI I///;= = Q>@ @
 a??1%% 2 22??2&&%doo6LA$_7N7N%NOO0 7  <> 	>r)   c                    SUs=::  a  [        U R                  5      :  d-  O  [        SU S3S[        U R                  5      S-
   3-   5      eU R                  SU n[        [	        U Vs/ s H  o3R
                  PM     sn5      5      $ s  snf )ar  
For a valid component index value, this returns the quarter note offset
at which that component would start.

This does not handle fractional arguments.

>>> components = []
>>> qdt = duration.DurationTuple('quarter', 0, 1.0)
>>> components.append(qdt)
>>> components.append(qdt)
>>> components.append(qdt)

>>> a = duration.Duration()
>>> a.components = components
>>> a.quarterLength
3.0
>>> a.componentStartTime(0)
0.0
>>> a.componentStartTime(1)
1.0
>>> a.componentStartTime(3)
Traceback (most recent call last):
IndexError: invalid component index value 3 submitted;
            value must be an integer between 0 and 2
r   zinvalid component index value  z2submitted; value must be an integer between 0 and r   N)r   r{   r  r   sumr   )r   componentIndexr{   r  s       r*   componentStartTimeDuration.componentStartTimee  s    4 ^:c$//&::00@BFs4??G[^_G_F`abc c ___n5
S:>:a//:>?@@>s   +Bc                r    [        U R                  5      S:X  a  g[        U R                  5      nU/U l        g)a  
Given a Duration with multiple components, consolidate into a single
Duration. This can only be based on quarterLength; this is
destructive: information is lost from components.

This cannot be done for all Durations, as DurationTuples cannot express all durations

>>> a = duration.Duration(1)
>>> a.addDurationTuple(duration.DurationTuple('half', 0, 2.0))
>>> a.addDurationTuple(duration.DurationTuple('quarter', 0, 1.0))
>>> a.quarterLength
4.0
>>> len(a.components)
3
>>> a.type
'complex'

After consolidate:

>>> a.consolidate()
>>> a.quarterLength
4.0
>>> len(a.components)
1

It gains a type!

>>> a.type
'whole'

If the type cannot be expressed then the type is inexpressible

>>> a = duration.Duration(1)
>>> a.addDurationTuple(duration.DurationTuple('half', 0, 2.0))
>>> a.addDurationTuple(duration.DurationTuple('half', 0, 2.0))
>>> a.quarterLength
5.0
>>> len(a.components)
3
>>> a.type
'complex'

After consolidate:

>>> a.consolidate()
>>> a.quarterLength
5.0
>>> len(a.components)
1
>>> a.components
(DurationTuple(type='inexpressible', dots=0, quarterLength=5.0),)

It gains a type!

>>> a.type
'inexpressible'

For an 'inexpressible' duration, the opposite of consolidate is
to set the duration's quarterLength to itself.  It won't necessarily
return to the original components, but it will usually
create something that can be notated.

>>> a.quarterLength = a.quarterLength
>>> a.type
'complex'
>>> a.components
(DurationTuple(type='whole', dots=0, quarterLength=4.0),
 DurationTuple(type='quarter', dots=0, quarterLength=1.0))
r   N)r   r{   r   quarterLengthNoTuplets)r   r  s     r*   rJ  Duration.consolidate  s4    L t1$01L1LMC  #eDOr)   c                   U R                   (       a  U R                  5         USL a  [        5       nO
[        5       n/ nU R                  nUS:X  a  SnU R
                   HG  nUR                  nUS:X  a  SnUR                  [        UR                  UR                  S5      5        MI     [        U5      Ul        SUl
        XBl        SUl        U$ )a\  
Return a deepcopy of this Duration as a GraceDuration instance with the same types.

>>> d = duration.Duration(1.25)
>>> d
<music21.duration.Duration 1.25>
>>> d.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),
 DurationTuple(type='16th', dots=0, quarterLength=0.25))

>>> gd = d.getGraceDuration()
>>> gd
<music21.duration.GraceDuration unlinked type:complex quarterLength:0.0>
>>> gd.quarterLength
0.0
>>> gd.components
(DurationTuple(type='quarter', dots=0, quarterLength=0.0),
 DurationTuple(type='16th', dots=0, quarterLength=0.0))

`d` is unchanged.

>>> d.quarterLength
1.25
TrB   r7   rC   F)rz  r  AppoggiaturaDurationGraceDurationr   r{   r   r   r   r   r  r   )r   appoggiaturagdr  new_typer  c_types          r*   getGraceDurationDuration.getGraceDuration  s    : ''""$ 4%'BB99vHAVVF!  qvvqvvs!CD	 !
 m,		r)   c                    U R                   SL a-  U R                  nU R                  5         U R                  U:X  a  gU R                  nUc  gUR	                  SU R                  S.5        g)aj  
A method that tells the client that something has changed.

Call `informSites({'changedAttribute': 'duration', 'quarterLength': quarterLength})`
on any call that changes the quarterLength, so that the client can make a change.

Returns False if there was no need to inform the client (like nothing has changed)
or if `.client` is None.  Otherwise returns True.
TFr   )changedAttributer   )r{  rx  r  r  informSites)r   old_qtrLengthcls      r*   r  Duration.informClient	  sd     ++t3 OOM%%'-/[[:
J)-: 	;r)   c                   U R                  U5      n[        R                  " U5      (       a  U R                  U   nOUnU R	                  U5      nX-
  nUR
                  U-
  nUS:X  d  US:X  a  [        S5      e[        U5      n[        U5      nU R                  SU Xx4-   U R                  US-   S -   n	Xl        U R                  5         g)a%  
Given a quarter position within a component, divide that
component into two components.

>>> d = duration.Duration()
>>> d.clear()  # need to remove default
>>> components = []

>>> d.addDurationTuple(duration.Duration('quarter'))
>>> d.addDurationTuple(duration.Duration('quarter'))
>>> d.addDurationTuple(duration.Duration('quarter'))
>>> d.quarterLength
3.0
>>> d.sliceComponentAtPosition(0.5)
>>> d.quarterLength
3.0
>>> len(d.components)
4
>>> d.components[0].type
'eighth'
>>> d.components[1].type
'eighth'
>>> d.components[2].type
'quarter'
r   z-no slice is possible at this quarter positionNr   )
r  r   r4  r{   r  r   r    r   rw  r  )
r   r  
sliceIndexdurObjSlicedurationStartTime
slicePoint	remainderd1d2r{   s
             r*   sliceComponentAtPosition!Duration.sliceComponentAtPosition"	  s    8 55oF
 <<
##//*5K$K !33J? %8
--
:	>Z1_#?A A ,J7+I6__[j1RH<t?O?OPZ]^P^P_?``
%!!#r)   c                    U R                   $ )a  
Advanced Method:

returns the current components WITHOUT running the component updater.

Needed by some internal methods.  Components are made on the fly.

>>> d = duration.Duration(1.25)
>>> d.currentComponents()
()

Like in quantum physics, an observation affects the state:

>>> d.type
'complex'
>>> d.currentComponents()
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),
 DurationTuple(type='16th', dots=0, quarterLength=0.25))


Generally, just look at `.components`

>>> d = duration.Duration(1.25)
>>> d.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),
 DurationTuple(type='16th', dots=0, quarterLength=0.25))
)rw  r  s    r*   currentComponentsDuration.currentComponents\	  s    8 r)   inPlacec          	        U R                   nU R                  nU(       d  [        R                  " U 5      nOU nUR	                  5         UR                  [        X#S   5      5        [        S[        U5      5       HW  n[        UR                  5       H;  nUR                  [        [        UR                   5      UR                  5      5        M=     MY     U(       d  U$ g)a}  
splits a dotGroup-duration (of 1 component) into a new duration of two
components.  Returns a new duration

Probably does not handle properly tuplets of dot-groups.
Never seen one, so probably okay.

>>> d1 = duration.Duration(type='half')
>>> d1.dotGroups = (1, 1)
>>> d1.quarterLength
4.5
>>> d2 = d1.splitDotGroups()
>>> d2.components
(DurationTuple(type='half', dots=1, quarterLength=3.0),
 DurationTuple(type='quarter', dots=1, quarterLength=1.5))
>>> d2.quarterLength
4.5

Here's how a system that does not support dotGroups can still display
the notes accurately.  N.B. MusicXML does this automatically, so
no need.

>>> n1 = note.Note()
>>> n1.duration = d1
>>> n1.duration = n1.duration.splitDotGroups()
>>> n1.duration.components
(DurationTuple(type='half', dots=1, quarterLength=3.0),
 DurationTuple(type='quarter', dots=1, quarterLength=1.5))

>>> s1 = stream.Stream()
>>> s1.append(meter.TimeSignature('9/8'))
>>> s1.append(n1)
>>> #_DOCS_SHOW s1.show('lily.png')
.. image:: images/duration_splitDotGroups.*

>>> n2 = note.Note()
>>> n2.duration.type = 'quarter'
>>> n2.duration.dotGroups = (1, 1)
>>> n2.quarterLength
2.25
>>> #_DOCS_SHOW n2.show()  # generates a dotted-quarter tied to dotted-eighth
>>> n2.duration.splitDotGroups(inPlace=True)
>>> n2.duration.dotGroups
(1,)
>>> n2.duration.components
(DurationTuple(type='quarter', dots=1, quarterLength=1.5),
 DurationTuple(type='eighth', dots=1, quarterLength=0.75))

>>> n2 = note.Note()
>>> n2.duration.type = 'quarter'
>>> n2.duration.dotGroups = (1, 1, 1)
>>> n2.quarterLength
3.375
>>> dSplit = n2.duration.splitDotGroups()
>>> dSplit.quarterLength
3.375
>>> dSplit.components
(DurationTuple(type='quarter', dots=1, quarterLength=1.5),
 DurationTuple(type='eighth', dots=1, quarterLength=0.75),
 DurationTuple(type='eighth', dots=1, quarterLength=0.75),
 DurationTuple(type='16th', dots=1, quarterLength=0.375))

Does NOT handle tuplets etc.
r   r   N)r   r   r0  r1  r  r  r   r   r   r   r{   r   r   )r   r  	tupleTypedgr  r   existingComponents          r*   splitDotGroupsDuration.splitDotGroupsz	  s    B II	^^d#AA			4Y1FGq#b'"A%)!,,%7!""-o>O>T>T.U.?.D.DF &8 # H r)   c                   U R                   SL a  gU R                  S:X  aI  U R                  (       d8  [        U R                  5      S:X  a  U R                  S   R
                  U l        Ow[        U R                  U R                  5       -  5      U l        U R                   H<  nUS:w  d  M  [        U R                  [        R                  " U5      -  5      U l        M>     SU l        g)z^
Look to components and determine quarter length.

* Changed in v7: made private.  And faster
FNrn  r   r   )r  r~  r   r   r{   r   rx  r
   r  aggregateTupletMultiplierr   r   r{  )r   r   s     r*   r  Duration._updateQuarterLength	  s     ;;%??d"4<<C<PTU<U"ooa0>>DO$T%@%@4CaCaCc%cdDO19&,T__v?S?STX?Y-Y&ZDO ( ,1(r)   c                \    U R                   (       a  U R                  5         U R                  $ )a  
Returns or sets a tuple of the component DurationTuples of this
Duration object

>>> d = duration.Duration(1.0)
>>> d.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),)

Tuplets do not have the tuplet in their components.

>>> d = duration.Duration(1/3)
>>> d.components
(DurationTuple(type='eighth', dots=0, quarterLength=0.5),)


With a complex duration it becomes clearer why multiple components are needed.
Here is a duration that cannot be expressed as a single note.

>>> d = duration.Duration(1.25)
>>> d.type
'complex'
>>> d.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),
 DurationTuple(type='16th', dots=0, quarterLength=0.25))

But it can be expressed another way and will output in that way in MusicXML
and other readers:

>>> component0 = duration.DurationTuple(type='eighth', dots=0, quarterLength=0.5)
>>> component1 = duration.DurationTuple(type='eighth', dots=1, quarterLength=0.75)
>>> d.components = [component0, component1]

It is allowed but not advised to set components that do not add up
to the current (pre-tuplet) quarterLength.  In which case the quarterLength
will be adjusted:

>>> d.components = [component0]
>>> d
<music21.duration.Duration 0.5>
>>> d.type
'eighth'
)rz  r  rw  r  s    r*   r{   Duration.components	  s&    X ''""$r)   c                    U R                   ULa9  SU l        U R                  5         U H  nU R                  U5        M     SU l        g g NFT)rw  rz  r  r  r{  )r   r   vs      r*   r{   r  
  sJ    
 5(+0D(JJL%%a(  04D, )r)   c                    U R                   S:X  a  U R                  $ U R                   S:w  a  U R                  S:X  a  U R                   4$ U R                  $ )a  
Dot groups are a convenience for transcribing medieval music.
They represent dotted-dotted notes (written one above another).
For instance a half note with dotGroups = (1, 1) represents a dotted half note that
is itself dotted.  Worth 9 eighth notes (dotted-half tied to dotted-quarter).  It
is not the same as a double-dotted half note, which is only worth 7 eighth notes.

>>> a = duration.Duration()
>>> a.type = 'half'
>>> a.dotGroups
(0,)
>>> a.dots = 1

>>> a.dotGroups = (1, 1)
>>> a.quarterLength
4.5
r   rn  )r   r~  r  s    r*   r   Duration.dotGroups"
  sE    & 99>??"YY!^4 7II<??"r)   c                    [        U[        5      (       d  [        S5      eS U R                   5       n[        U5      U l        Xl        SU l        g )Nz9only tuple dotGroups values can be used with this method.c              3  N   #    U  H  n[        UR                  S 5      v   M     g7f)r   N)r   r   ).0r   s     r*   	<genexpr>%Duration.dotGroups.<locals>.<genexpr>A
  s#      
JZY%inna88JZs   #%T)r   r   r  rw  r~  r{  )r   r   componentsGenerators      r*   r   r  <
  sN    %''WXX
JNJZJZ
 !!45+/(r)   c                   U R                   (       a  U R                  5         [        U R                  5      S:X  a  U R                  S   R                  $ [        U R                  5      S:  a  U R                  S   R                  $ g)a  
Returns or sets the number of dots in the Duration
if it is a simple Duration.

For returning only the number of dots on the first component is returned for
complex durations. (Previously it could return None
if it was not a simple duration which led to some
terribly difficult to find errors.)

>>> a = duration.Duration()
>>> a.type = 'quarter'
>>> a.dots = 1
>>> a.quarterLength
1.5
>>> a.dots = 2
>>> a.quarterLength
1.75

If a duration is complex then setting dots has the effect of
setting the number of dots to `value` on every component.

>>> DT = duration.durationTupleFromTypeDots
>>> complexDuration = duration.Duration()
>>> complexDuration.addDurationTuple(DT('half', 0))
>>> complexDuration.addDurationTuple(DT('eighth', 2))
>>> complexDuration.type
'complex'
>>> complexDuration.quarterLength
2.875

In a complex duration, the number of dots comes from the first component:

>>> complexDuration.dots
0

But if set, applies to all components:

>>> complexDuration.dots = 1
>>> complexDuration.components
(DurationTuple(type='half', dots=1, quarterLength=3.0),
 DurationTuple(type='eighth', dots=1, quarterLength=0.75))
>>> complexDuration.quarterLength
3.75

Dots can go pretty high.

>>> d = duration.Duration('half')
>>> d.quarterLength
2.0
>>> d.dots = 5
>>> d.quarterLength
3.9375
>>> d.dots = 10
>>> d.quarterLength
3.998046875

Infinite dots gives an Easter egg:

>>> from math import inf
>>> d.type = 'half'
>>> d.dots = inf
>>> d.quarterLength
4.0
>>> d.dots
0
>>> d.type
'whole'
r   r   )rz  r  r   r{   r   r  s    r*   r   Duration.dotsI
  si    L ''""$t1$??1%***!A%??1%***r)   c                   U R                   (       a  U R                  5         [        R                  " U5      (       d  [	        S5      eU[
        :X  a"  [        U R                  5      U l        SU l        g [        U R                  5      n[        U R                  5       H  u  p4[        UR                  U5      X#'   M     [        U5      U l
        SU l        U R                  SL a  SU l        U R#                  5         g )Nz5only numeric dot values can be used with this method.r   TF)rz  r  r   r4  r  r   r   r   r   r   rw  r  r   r   r{  r  r  r  )r   r   r{   r   r   s        r*   r   r  
  s    ''""$||E""STT C<&tyy1DIDI$**+
t//0EA5bgguEJM 1 ,+/(;;$(-D%r)   c                   / nU R                   (       aB  / nU R                    H  nUR                  UR                  5        M      SR                  U5      nOSnU R                   GH  nUR
                  nUS:X  a  SnO)US:X  a  SnO US:X  a  SnOUS	:X  a  S
nOUS	:  a  U S3nOSn/ nUR                  n	US:  d  U	S;  a  Ub  UR                  U S35        O/US:X  a  UR                  S5        OUS:X  a  UR                  S5        U	S   S;   a  OU	R                  5       n	U	R                  5       S:X  a  OUR                  U	 S35        US:w  a  UR                  U S35        US:w  d  US:  d  U	R                  5       S:X  a5  [        R                  " U R                  5      n
UR                  SU
 S35        UR                  SR                  U5      R                  5       5        GM     U R                  (       d  UR                  S5        Sn[        U5      S:  a  SR                  U5      nOUS   n[        U R                  5      S:w  a)  [        R                  " U R                  5      n
USU
 S3-  nU$ )a  
Return the most complete representation of this Duration, providing
dots, type, tuplet, and quarter length representation.

>>> d = duration.Duration(quarterLength=1.5)
>>> d.fullName
'Dotted Quarter'

>>> d = duration.Duration(type='half')
>>> d.fullName
'Half'

>>> d = duration.Duration(quarterLength=1.25)
>>> d.fullName
'Quarter tied to 16th (1 1/4 total QL)'

>>> d = duration.Duration(quarterLength=0.333333)
>>> d.fullName
'Eighth Triplet (1/3 QL)'

>>> d = duration.Duration(quarterLength=0.666666)
>>> d.fullName
'Quarter Triplet (2/3 QL)'

>>> d = duration.Duration(quarterLength=0.571428)
>>> d.fullName
'Quarter Septuplet (4/7 QL)'

>>> d = duration.Duration(quarterLength=0)
>>> d.fullName
'Zero Duration (0 total QL)'
r   r   Dottedr   zDouble DottedrH   zTriple Dottedr   zQuadruple Dottedz-Times Dotted)r1   r0   r   z
Imperfect zPerfect )12356complex(z QL)zZero Duration z	 tied to z (z
 total QL))r   r   r[  joinr{   r   r   titlelowerr   mixedNumeralr   stripr   )r   totalMsgtupletStrListr   	tupletStrr  r   dotStrmsgtypeStrqlStroutMsgs               r*   r[  Duration.fullName
  s=   D <<M||$$S\\2 $/IIA66Dqy!((+ 6/CffGqyW,??%JJ&|,19JJ|,QYJJz*qz66!--/}})+

gYa=)B

i[?+B$!)w}})/K++D,>,>?

QugT?+OOBGGCL..01O !R OO,-x=1 %%h/Fa[Ft1$''(:(:;E5',,Fr)   c                8    [        U R                  5      S:  a  gg)a)  
Returns True if this Duration has more than one DurationTuple object on
the `component` list.  That is to say if it's a single Duration that
need multiple tied noteheads to represent.

>>> aDur = duration.Duration()
>>> aDur.quarterLength = 1.375
>>> aDur.isComplex
True

>>> len(aDur.components)
2

>>> aDur.components
(DurationTuple(type='quarter', dots=0, quarterLength=1.0),
 DurationTuple(type='16th', dots=1, quarterLength=0.375))

>>> cDur = duration.Duration()
>>> cDur.quarterLength = 0.25
>>> cDur.isComplex
False

>>> len(cDur.components)
1
r   TF)r   r{   r  s    r*   r  Duration.isComplex  s    6 t!#r)   c                    U R                   (       a  U R                  5         [        U R                  5      S:  a  g[        U R                  5      S:X  a  U R                  S   R                  $ g)a  
Get the ordinal value of the Duration, where whole is 4,
half is 5, etc.

>>> d = duration.Duration()
>>> d.quarterLength = 2.0
>>> d.ordinal
5
>>> d.type = '16th'
>>> d.ordinal
8

Complex values have an ordinal of the string 'complex'.  This might
change to NaN in a later version.

>>> d.quarterLength = 2.5
>>> d.ordinal
'complex'

Zero durations have an ordinal of None

>>> d2 = duration.Duration(0.0)
>>> print(d2.ordinal)
None
r   r  r   N)rz  r  r   r{   r  r  s    r*   r  Duration.ordinal1  sV    6 ''""$t!#!Q&??1%---r)   c                    U R                   (       a  U R                  5         SnU R                   H  nXR                  -  nM     U$ )z
Returns the quarter length of the duration without taking into account triplets.

Does not cache.

>>> d = duration.Duration(1/3)
>>> d.quarterLengthNoTuplets
0.5
rC   )rz  r  rw  r   )r   totr  s      r*   r  Duration.quarterLengthNoTupletsV  sA     ''""$ !!A??"C "
r)   c                \    U R                   (       a  U R                  5         U R                  $ r   )r{  r  rx  r  s    r*   _getQuarterLengthDuration._getQuarterLengthj  s!    ++%%'r)   c                J   U R                   SL a  Xl        g U R                  U:w  d!  U R                  (       d  U R                  S:X  a\  [	        U5      nUS:X  a  U R                   SL a  U R                  5         Xl        SU l        SU l        SU l        U R                  5         g g )NFr   rC   T)	r  rx  rz  r   r
   r  r  r{  r  r  s     r*   _setQuarterLengthDuration._setQuarterLengtho  s    ;;%#Ooo&//99/5ME|t 3

#O(,D%+/D(/4D, 0r)   a  
        Returns the quarter note length or Sets the quarter note length to
        the specified value. May be expressed as a float or Fraction.

        Currently (if the value is different from what is already stored)
        this wipes out any existing components, not preserving their type.
        So if you've set up Duration(1.5) as 3-eighth notes, setting
        Duration to 1.75 will NOT dot the last eighth note, but instead
        give you a single double-dotted half note.

        >>> a = duration.Duration()
        >>> a.quarterLength = 3.5
        >>> a.quarterLength
        3.5

        >>> for thisUnit in a.components:
        ...    print(duration.unitSpec(thisUnit))
        (3.5, 'half', 2, None, None, None)

        >>> a.quarterLength = 2.5
        >>> a.quarterLength
        2.5

        >>> for thisUnit in a.components:
        ...    print(duration.unitSpec(thisUnit))
        (2.0, 'half', 0, None, None, None)
        (0.5, 'eighth', 0, None, None, None)

        Note that integer values of quarter lengths get
        silently converted to floats (internally opFracs):

        >>> b = duration.Duration()
        >>> b.quarterLength = 5
        >>> b.quarterLength
        5.0
        >>> b.type  # complex because 5qL cannot be expressed as a single note.
        'complex'

        Float values will be converted to fractions if they are inexpressible exactly
        as floats:

        >>> b = duration.Duration()
        >>> b.quarterLength = 1/3
        >>> b.quarterLength
        Fraction(1, 3)
        )docc                \    U R                   (       a  U R                  5         U R                  $ )zp
Return a tuple of Tuplet objects.
Setting tuplets will inform the client (Note) that the duration has changed.
)rz  r  ry  r  s    r*   r   Duration.tuplets  s#     ''""$}}r)   c                R    [        U5      U l        SU l        U R                  5         g )NT)r   ry  r{  r  )r   tupletTuples     r*   r   r$    s$     k*+/(r)   c                    U R                   (       d  gSnU R                    H  nXR                  5       -  nM     [        R                  " U5      $ )a"  
Returns the multiple of all the tuplet multipliers as an opFrac.

This method is needed for MusicXML time-modification among other
places.

No tuplets:

>>> complexDur = duration.Duration('eighth')
>>> complexDur.aggregateTupletMultiplier()
1.0

With tuplets:

>>> complexDur.appendTuplet(duration.Tuplet())
>>> complexDur.aggregateTupletMultiplier()
Fraction(2, 3)

Nested tuplets are possible...

>>> tup2 = duration.Tuplet()
>>> tup2.setRatio(5, 4)
>>> complexDur.appendTuplet(tup2)
>>> complexDur.aggregateTupletMultiplier()
Fraction(8, 15)
r6   )r   r   r   r
   )r   currentMultiplier
thisTuplets      r*   r  "Duration.aggregateTupletMultiplier  sD    6 ||,,J!<!<!>> '}}.//r)   c                   U R                   SL a$  U R                  c  [        S5      eU R                  $ [        U R                  5      S:X  a  U R                  S   R
                  $ [        U R                  5      S:  a  gg)z
Get or set the type of the Duration.

>>> a = duration.Duration()
>>> a.type = 'half'
>>> a.quarterLength
2.0

>>> a.type= '16th'
>>> a.quarterLength
0.25
FzLlinked property setter failed to set _unlinkedType, please open a bug reportr   r   r  rB   )r  r}  r    r   r{   r   r  s    r*   r   Duration.type  sw     ;;%!!)'b  %%%!Q&??1%***!A%r)   c                    U[         ;  a  US;  a  [        SU 35      eU R                  SL a<  [        XR                  5      nU4U l        SU l        SU l        U R                  5         g Xl	        g )N)r   r  zno such type exists: TF)
rG   r  r  r   r   r{   r{  r  r  r}  )r   r   r
  s      r*   r   r,    so     **u<X/X4UG<==;;$*5))<B!eDO/3D,(-D% "'r)   )rw  rz  r~  rv  rx  r{  ry  r|  r}  r  r{   r   r  r   r   r   r   )r  'str | OffsetQLIn | DurationTuple | Noner   z
str | Noner   z
int | Noner   zOffsetQLIn | Noner  rq  r{   zIterable[DurationTuple] | Noner  zbase.Music21Object | Nonerl  )r   rk  )r  z+DurationTuple | Duration | str | OffsetQLIn)r   r   rm  ro  F)rm  ro  )r  r   rm  r   )rm  z$GraceDuration | AppoggiaturaDuration)rm  ztuple[DurationTuple, ...])r   zIterable[DurationTuple])rm  rM   )r   rM   )rm  r   )r   r   )rm  r   )rm  zint | str | None)rm  r   rp  )r   r   )rm  ztuple[Tuplet, ...])r&  zIterable[Tuplet])r   r   )-r$   r%   r&   r'   rs  isGrace	__slots__	_DOC_ATTRr  r$  r)  r  r  r  r  r  r  r  r  r   r  r  r  rJ  r  r  r  r  r  r  r{   rt  r   r   r[  r  r  r  r  r   r   r   r  r   r(   r"   r)   r*   r   r     s   ;~ GI!"%I@ FJA #'"#2659<@37A!BA  	A
  A !0A !3A :A 1AJ=~SS0-0 j*-F
 &+$ C$ L4(jX:A>FADL$` 5 
,5n,8$t < ). Sj1* -  - ^ 
4 
4 # #2 
0 
0 L L\ 
[[ * ` `D  > " "H  &
   .0A -H -M^   ^^ "0J  4 
[[' 'r)   r   c                  :   ^  \ rS rSrSrSrU 4S jrSS jrSrU =r	$ )FrozenDurationi  a  
A FrozenDuration is one that must have all of its arguments specified
at the time of construction.  After that, it is immutable, like a Tuple
and thus can be shared across different objects (like in MeterTerminals)
or used as a hash.

>>> fd = duration.FrozenDuration(type='half', dots=2)
>>> fd.quarterLength
3.5
>>> fd.dots = 1
Traceback (most recent call last):
TypeError: This FrozenDuration instance is immutable.

FrozenDurations can be used as set/dict keys with stability.

>>> {fd}
{<music21.duration.FrozenDuration 3.5>}

Copying a FrozenDuration returns the original, so it is super fast.

>>> import copy
>>> copy.deepcopy(fd) is fd
True
r"   c                f   > [         TU ]  " U0 UD6  U R                  5         U R                  5         g r   )superr  r  r  )r   	argumentsr  r  s      r*   r  FrozenDuration.__init__+  s-    )0x0 !!#r)   c                    U $ )z%
Immutable objects return themselves
r"   r  s     r*   r  FrozenDuration.__deepcopy__0  s	     r)   r   )
r$   r%   r&   r'   rs  r1  r  r  r(   __classcell__r  s   @r*   r4  r4    s    0 I$
 r)   r4  c                     ^  \ rS rSr% SrSSS.rS\S'   SrS	r S SU 4S
 jjjr	\
S 5       r\R                  SS j5       r\
S 5       r\R                  S 5       rSrU =r$ )r  i6  as  
A Duration that, no matter how it is created, always has a quarter length
of zero.

GraceDuration can be created with an implied quarter length and type; these
values are used to configure the duration, but then may not be relevant
after instantiation.

>>> gd = duration.GraceDuration(type='half')
>>> gd.quarterLength
0.0

>>> gd.type
'half'

>>> gd = duration.GraceDuration(0.25)
>>> gd.type
'16th'

>>> gd.quarterLength
0.0

>>> gd.linked
False

>>> gd = duration.GraceDuration(1.25)
>>> gd.type
'complex'

>>> gd.quarterLength
0.0

>>> [(x.quarterLength, x.type) for x in gd.components]
[(0.0, 'quarter'), (0.0, '16th')]
z
                Float number from 0.0 to 1.0, or None (default) for the proportion
                of the previous duration to steal from the previous note.z
                Float number from 0.0 to 1.0 or None (default) for the proportion
                of the following duration to steal from the following note.)stealTimePreviousstealTimeFollowingzdict[str, str]r2  T)_slashr>  r?  	_makeTimec                v  > [         TU ]  " U40 UD6  U R                  (       a  U R                  5         SU l        SU l        / nU R                   H3  nUR                  [        UR                  UR                  S5      5        M5     [        U5      U l        SU l        S U l        SU l        S U l        S U l        g )NFrC   T)r6  r  rz  r  r  r   r{   r   r   r   r   r   rA  r@  slashr>  r?  )r   r  r  r  r  r  s        r*   r  GraceDuration.__init__t  s     	484 ''""$ A  qvvqvvs!CD !. 
-1.2r)   c                    U R                   $ )z
True, False, or None (=unknown) whether the grace note should occupy time
in performance. Default False. Currently not used in generated playback.

TODO: allow a duration object or number for duration.
)rA  r  s    r*   makeTimeGraceDuration.makeTime  s     ~~r)   c                F    US;  a  [        S5      e[        U5      U l        g N)TFNz!expr must be True, False, or None)r  rk  rA  r   exprs     r*   rF  rG    s"    **@AAdr)   c                    U R                   $ )zf
True, False, or None (=unknown) whether the grace note should have a slash
through it. Default True.
)r@  r  s    r*   rC  GraceDuration.slash  s     {{r)   c                F    US;  a  [        S5      e[        U5      U l        g rI  )r  rk  r@  rJ  s     r*   rC  rM    s"    **@AA4jr)   )rA  r@  r{   r  r   rC  r?  r>  r   r  r.  )rK  zt.Literal[True, False, None])r$   r%   r&   r'   rs  r2  r}   r0  r1  r  r  rF  rt  rC  r(   r;  r<  s   @r*   r  r  6  s    "VMO	!I~  GI FJ3!B3 34   __$ $
   \\! !r)   r  c                  <   ^  \ rS rSrSrSr S SU 4S jjjrSrU =r$ )r  i  z$
Renamed in v6 to correct spelling.
r"   c                D   > [         TU ]  " U40 UD6  SU l        SU l        g r  )r6  r  rC  rF  )r   r  r  r  s      r*   r  AppoggiaturaDuration.__init__  s%     	484
r)   )rF  rC  r   rO  )	r$   r%   r&   r'   rs  r1  r  r(   r;  r<  s   @r*   r  r    s(    
 I
 FJ!B r)   r  c                  H    \ rS rSrSrS	S
S jjrSS jrSSS jjrSS jrSr	g)TupletFixeri  ag  
The TupletFixer object takes in a flat stream and tries to fix the
brackets and time modification values of the tuplet so that they
reflect proper beaming, etc.  It does not alter the quarterLength
of any notes.

See :meth:`~music21.duration.TupletFixer.findTupletGroups` and
:meth:`~music21.duration.TupletFixer.fixBrokenTupletDuration` for
demonstrations.
Nc                    Xl         / U l        g r   streamInallTupletGroupsr   rW  s     r*   r  TupletFixer.__init__  s    ,4=?r)   c                    Xl         / U l        g)z?
Define a stream to work on and reset all temporary variables.
NrV  rY  s     r*   	setStreamTupletFixer.setStream  s     !!r)   c                2   U R                   c  [        S5      e/ U l        / nSnU R                   R                   H  nUR                  R
                  (       d&  USL a  U R                  R                  U5        / nSnMD  USL a  SnUR                  U5        U(       d  Me  UR                  R
                  S   R                  S:X  d  M  U R                  R                  U5        / nSnM     U(       a  U R                  R                  U5        U R                  $ )aM  
Finds all tuplets in the stream and puts them into groups.

If incorporateGroupings is True, then a tuplet.type="stop"
ends a tuplet group even if the next note is a tuplet.

This demonstration has three groups of tuplets, two sets of 8th note
tuplets and one of 16ths:

>>> c = converter.parse(
...    'tinynotation: 4/4 trip{c8 d e} f4 trip{c#8 d# e#} g8 trip{c-16 d- e-}',
...    makeNotation=False)
>>> tf = duration.TupletFixer(c)  # no need to flatten this stream
>>> tupletGroups = tf.findTupletGroups()
>>> tupletGroups
[[<music21.note.Note C>, <music21.note.Note D>, <music21.note.Note E>],
 [<music21.note.Note C#>, <music21.note.Note D#>, <music21.note.Note E#>],
 [<music21.note.Note C->, <music21.note.Note D->, <music21.note.Note E->]]

These groups are stored in TupletFixer.allTupletGroups:

>>> tupletGroups is tf.allTupletGroups
True

Demonstration with incorporateGroupings:

>>> s = stream.Stream()
>>> for i in range(9):
...    n = note.Note()
...    n.pitch.ps = 60 + i
...    n.duration.quarterLength = 1/3
...    if i % 3 == 2:
...        n.duration.tuplets[0].type = 'stop'
...    s.append(n)
>>> tf = duration.TupletFixer(s)
>>> tupletGroups = tf.findTupletGroups(incorporateGroupings=True)
>>> tupletGroups
[[<music21.note.Note C>, <music21.note.Note C#>, <music21.note.Note D>],
 [<music21.note.Note E->, <music21.note.Note E>, <music21.note.Note F>],
 [<music21.note.Note F#>, <music21.note.Note G>, <music21.note.Note G#>]]

Without incorporateGroupings we just get one big set of tuplets

>>> tupletGroups = tf.findTupletGroups()
>>> len(tupletGroups)
1
>>> len(tupletGroups[0])
9
z&Call setStream(Stream) before running.FTr   r   )rW  r  rX  notesAndRestsr   r   r   r   )r   incorporateGroupingscurrentTupletGrouptupletActiver=  s        r*   findTupletGroupsTupletFixer.findTupletGroups  s    f == EFF!57,,A::%%4'((//0BC)+&#(Lu$#%%a(##

(:(:1(=(B(Bf(L$$++,>?%'"$ -   ''(:;###r)   c                   SnSnU(       d  gUS   R                   R                  S   n[        UR                  5       5      nSnUnUnU H  n	[        XiR                   R                  -   5      nU	R                   R                  S   n
U
R
                  n[        R                  (       a  Uc   eUR                  n[        R                  U5      nXr:X  a  UnOX:  a  UnX:X  a  UnM  X:  d  M  UnM     Xe:X  a  g[        Xe-  5      n[        SU-  5      nU[        U5      :X  Gaa  [        U   nU GHP  n	SnSU	R                   R                  S   l        U	R                   R                  S   R                  b-  U	R                   R                  S   R                  R                  n[        UU5      U	R                   R                  S   l        SnU	R                   R                  S   R
                  b-  U	R                   R                  S   R
                  R                  n[        UU5      U	R                   R                  S   l        SU	R                   R                  S   l        U	R                   R!                  5         GMS     gU[        U5      :X  Gae  [        U   nU GHT  n	SnSU	R                   R                  S   l        U	R                   R                  S   R                  b-  U	R                   R                  S   R                  R                  n[        UU5      nUU	R                   R                  S   l        SnU	R                   R                  S   R
                  b-  U	R                   R                  S   R
                  R                  n[        UU5      nUU	R                   R                  S   l        SU	R                   R                  S   l        U	R                   R!                  5         GMW     gg)	a  
Tries to fix cases like triplet quarter followed by triplet
eighth to be a coherent tuplet.

Requires a tuplet group from `findTupletGroups()` or TupletFixer.allTupletGroups.
Note: this works on a single tupletGroup while `findTupletGroups()`
returns a list of groups.

>>> s = stream.Stream()

>>> n1 = note.Note('C')
>>> n1.duration.quarterLength = 2/3
>>> n1.duration.quarterLength
Fraction(2, 3)
>>> s.append(n1)
>>> n2 = note.Note('D')
>>> n2.duration.quarterLength = 1/3
>>> n2.duration.quarterLength
Fraction(1, 3)
>>> s.append(n2)

Here are the current tuplets for the two notes:

>>> n1.duration.tuplets[0]
<music21.duration.Tuplet 3/2/quarter>
>>> n2.duration.tuplets[0]
<music21.duration.Tuplet 3/2/eighth>

Notice how the first note is waiting for 3 triplet quarters to
complete itself.  But it could be 2/3 of a quarter note divided into
eighth note triplets.  TupletFixer will work on this.

It takes in a flattened stream, like this one:

>>> tf = duration.TupletFixer(s)

Find the tuplet groups.  Returning a list of one group, which has
two notes in it:

>>> tupletGroups = tf.findTupletGroups()
>>> tupletGroups
[[<music21.note.Note C>, <music21.note.Note D>]]

Now fix that single group:

>>> tg0 = tupletGroups[0]
>>> [n.duration.tuplets[0].type for n in tg0]
[None, None]

>>> tf.fixBrokenTupletDuration(tg0)

Now the first quarter-note triplet knows that its group
will be complete after the next note:

>>> n1.duration.tuplets[0]
<music21.duration.Tuplet 3/2/eighth>
>>> n1.duration.quarterLength
Fraction(2, 3)
>>> n2.duration.tuplets[0]
<music21.duration.Tuplet 3/2/eighth>

Note that the tuplet type is not affected by this call:

>>> [n.duration.tuplets[0].type for n in tg0]
[None, None]

To do that, call :func:`~music21.stream.makeNotation.makeTupletBrackets`
on the flattened stream:

>>> stream.makeNotation.makeTupletBrackets(s, inPlace=True)
>>> [n.duration.tuplets[0].type for n in tg0]
['start', 'stop']


More complex example, from a piece by Josquin:

>>> humdrumExcerpt = '**kern *M3/1 3.c 6d 3e 3f 3d 3%2g 3e 3f#'
>>> humdrumLines = '\n'.join(humdrumExcerpt.split())

There is a side format of humdrum that the Josquin Research Project uses
for long notes like the 3%2.

>>> humdrum.spineParser.flavors['JRP'] = True

Since Humdrum parsing is going to apply TupletFixer, we will temporarily
disable it:

>>> saved_fixed_broken = duration.TupletFixer.fixBrokenTupletDuration
>>> duration.TupletFixer.fixBrokenTupletDuration = lambda x,y: None

>>> s = converter.parse(humdrumLines, format='humdrum')

>>> m1 = s.parts.first().measure(1)
>>> m1.show('text', addEndTimes=True)
{0.0 - 0.0} <music21.meter.TimeSignature 3/1>
{0.0 - 2.0} <music21.note.Note C>
{2.0 - 2.6667} <music21.note.Note D>
{2.6667 - 4.0} <music21.note.Note E>
{4.0 - 5.3333} <music21.note.Note F>
{5.3333 - 6.6667} <music21.note.Note D>
{6.6667 - 9.3333} <music21.note.Note G>
{9.3333 - 10.6667} <music21.note.Note E>
{10.6667 - 12.0} <music21.note.Note F#>

>>> duration.TupletFixer.fixBrokenTupletDuration = saved_fixed_broken
>>> tf = duration.TupletFixer(m1)
>>> tupletGroups = tf.findTupletGroups(incorporateGroupings=True)
>>> tupletGroups
[[<music21.note.Note C>, <music21.note.Note D>, <music21.note.Note E>],
 [<music21.note.Note F>, <music21.note.Note D>, <music21.note.Note G>,
  <music21.note.Note E>, <music21.note.Note F#>]]

There's a problem with the last group: it contains 5 notes and the
third note is twice as long as the others, so none of them form a coherent
triplet.

>>> [n.duration.tuplets[0] for n in tupletGroups[1]]
[<music21.duration.Tuplet 3/2/half>, <music21.duration.Tuplet 3/2/half>,
 <music21.duration.Tuplet 3/2/whole>,
 <music21.duration.Tuplet 3/2/half>, <music21.duration.Tuplet 3/2/half>]
>>> [n.duration.tuplets[0].type for n in tupletGroups[1]]
['start', None, None, None, 'stop']


Fix the last broken tuplet group.

>>> tf.fixBrokenTupletDuration(tupletGroups[1])
>>> [n.duration.tuplets[0] for n in tupletGroups[1]]
[<music21.duration.Tuplet 3/2/whole>, <music21.duration.Tuplet 3/2/whole>,
 <music21.duration.Tuplet 3/2/whole>,
 <music21.duration.Tuplet 3/2/whole>, <music21.duration.Tuplet 3/2/whole>]

Note that the changes appear in the notes in the Stream as well.

>>> m1.last().duration.tuplets[0]
<music21.duration.Tuplet 3/2/whole>

Again, TupletFixer is automatically called when parsing from Humdrum.
(MusicXML specifies its tuplet groups explicitly.) But you may need it
when building up a stream from scratch in your own projects.
i  r  Nr   rC   r   FT)r   r   r
   r?  r   r   r  TYPE_CHECKINGr   rG   r   r   r   r   r   r   r  )r   tupletGroupSMALL_SENTINELLARGE_SENTINELfirstTuptotalTupletDurationcurrentTupletDurationsmallestTupletTypeOrdinallargestTupletTypeOrdinalr=  thisTuptupDurationActualthisTupTypethisTupTypeOrdinalexcessRatioinverseExcessRatiolargestTupletType
normalDots
actualDotssmallestTupletTypedurTuples                        r*   fixBrokenTupletDuration#TupletFixer.fixBrokenTupletDuration'  sw   ^ q>**2215$X%?%?%AB #)7!(6 A$*+@::C[C[+[$\!jj((+G ' 6 6(444+00K!3!9!9+!F(:,>)#?,>)'9+=(#>+=(% ( !72HI#AO4#k** 23K L 
/4

""1%,::%%a(77C!"!3!3A!6!E!E!J!JJ7P%z83

""1%4
::%%a(77C!"!3!3A!6!E!E!J!JJ7P%z83

""1%4/3

""1%,

'') !  3'9#::!34M!N 
/4

""1%,::%%a(77C!"!3!3A!6!E!E!J!JJ45GT7?

""1%4
::%%a(77C!"!3!3A!6!E!E!J!JJ45G5?A7?

""1%4/3

""1%,

'')! ! ;r)   )rX  rW  r   )rW  zstream.Stream | None)rW  zstream.Streamrm  ro  r/  )r`  rk  rm  zlist[list[note.GeneralNote]])rg  zlist[note.GeneralNote]rm  ro  )
r$   r%   r&   r'   rs  r  r\  rc  rz  r(   r"   r)   r*   rT  rT    s    	@"J$XX*r)   rT  c                  $    \ rS rSrSrS rS rSrg)TestExternali  Tc                    SSK Jn  [        5       nSUl        UR                  " 5       nX#l        U R                  (       a  UR                  5         g g )Nr   r   g/iQU@)music21r   r   r   Noter   show)r   r   ar=  s       r*   
testSingleTestExternal.testSingle  s8     J!IIK
99FFH r)   c                l   SS K nSSKJn  SSKJn  UR                  " 5       n[        S5       Hb  nUR                  / SQ5      UR                  / SQ5      -   nUR                  " 5       n[        5       nXhl	        Xl
        UR                  U5        Md     U R                  (       a  UR                  5         g g )Nr   r   r      )r   r   rH   r   rI   )r   r:   r8         ?)randomr  r   r   Streamr   choicer  r   r   r   r   r  )	r   r  r   r   r  r   r	  r=  bs	            r*   	testBasicTestExternal.testBasic  s    " MMOrA/&--@T2UUB		A
A OJHHQK  99FFH r)   r"   N)r$   r%   r&   r'   r  r  r  r(   r"   r)   r*   r}  r}    s    Dr)   r}  c                  n    \ rS rSrS rS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rSrg)Testi%  c                2    SSK Jn  U" U [        5       5        g )Nr   )testCopyAll)music21.test.commonTestr  globals)r   r  s     r*   testCopyAndDeepcopyTest.testCopyAndDeepcopy'  s    7D')$r)   c                   [        5       nSUl        SUl        [        5       nSUl        SUl        [        5       nSU/Ul        SU/Ul        U R                  UR                  5       S5        [        5       nSUl        SUl        U4Ul        U R                  UR                  [        R                  " SS	5      5        [        5       n[        5       nS
Ul        SU/Ul        SU/Ul        U R                  UR                  5       S5        U R                  UR                  5       [        R                  " SS5      5        X54Ul        U R                  UR                  [        S5      5        [        5       nU R                  UR                  5       [        S5      5        S[        SS5      /Ul        U R                  UR                  5       [        S5      5        g )Nr7   r   r   rI   rH   g      @r5         r9   r8   gffffff?UUUUUU?r   皙?)r   r   r   r   r^  re  assertEqualr?  r   r   r   r   r   r
   r   )r   dur1dur2tup1dur3tup2dur4myTuplets           r*   	testTupleTest.testTuple+  s    z		z		xII//159 z		w++Y-?-?B-GH xz	II//137..0)2D2DQ2JK|++VF^<8224fUmD!"$=h$J K224fUmDr)   c                   SSK Jn  SSK Jn  S/S-  S/S-  -   / SQpC/ nU H$  n[        5       nXgl        UR                  U5        M&     UR                  " 5       nU H$  n	UR                  " U	S	9n
UR                  U
5        M&     UR                  R                  US
S9  / nU H+  nUR                  UR                  S   R                  5        M-     U R                  X5        g)zG
Test setting of tuplet type when durations sum to expected completion
r   r   r   F]kSU?rH   *TU?rS  )	r   Nr   r   Nr   r   Nr   r   Tr  Nr  r   r   r   r   r   r  r  makeNotationmakeTupletBracketsr   r   r  )r   r   r   testr   inputTupletsr   r  inputTupletStreamr  m21Objoutputs               r*   testTupletTypeCompleteTest.testTupletTypeCompleteU  s    
 	!" zA~a7\ D
A"O" 
 #MMOCYY,F$$V,   	../@$.OAMM!))A,++, 'r)   c                   SSK Jn  SSK Jn  [        5       nSUl        SUR
                  S   l        SUR
                  S   l        [        5       nSUl        [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      /nUR                  " 5       nU H$  nUR                  " US9nUR                  U5        M&     / S	Qn	UR                  R                  US
S9  / n
U H+  nU
R                  UR
                  S   R                  5        M-     U R!                  X5        g )Nr   r   r   giKGUU?rS  r   皙?r  )r   NNNNr   r   NNNr   Tr  )r  r   r   r   r   r   r   r   r0  r1  r  r  r   r  r  r   r  )r   r   r   tup6tup5r  r  r  r  r   r  r  s               r*   testTupletTypeComplete2Test.testTupletTypeComplete2o  sZ    "z',-Q),-Q)z  MM$t!4dmmD6IMM$t!4dmmD6IMM$t!4dmmD6IMM$t!4	
 #MMOCYY,F$$V,  4 	../@$.OAMM!))A,++, 'r)   c                   SSK Jn  SSK Jn  S/S-  S/S-  -   / SQpC/ nU H$  n[        5       nXgl        UR                  U5        M&     UR                  " 5       nU H$  n	UR                  " U	S	9n
UR                  U
5        M&     UR                  R                  US
S9  / nU H+  nUR                  UR                  S   R                  5        M-     U R                  X5        g)zO
Test setting of tuplet type when durations do not sum to expected
completion.
r   r   r   r  r   r  rI   )r   NNr   r   Nr   r  Tr  Nr  )r   r   r   r  r   inputDurationsr   r  r  r  r  r  s               r*   testTupletTypeIncompleteTest.testTupletTypeIncomplete  s    
 	!"
 !zA~a7K  D
A"O!!!$ 
 #MMO!CYY,F$$V, " 	../@$.OAMM!))A,++,   	'r)   c                   SSK Jn  SSK Jn  UR                  " 5       nUR                  " SS9nUR                  US5        U H(  nUR                  R                  [        SS5      5        M*     UR                  S   R                  R                  [        SS5      5        UR                  " 5       nU H  nUR                  U5        M     [        R                  " 5       n[        R                  " U5         UR                  R!                  U5      nS	S	S	5        U R#                  W V	s/ s H%  oR                  R$                  S   R&                  PM'     sn	/ S
Q5        g	! , (       d  f       NT= fs  sn	f )z0
Nested tuplets are not fully supported (TODO).
r   r   r   r4   r   rH   r   r   N)r   Nr   )r  r   r   Measurer  repeatAppendr   r  r   notesr   ioStringIO
contextlibredirect_stderrr  r  r  r   r   )
r   r   r   gapfulr4   r=  gapless	file_likemadeels
             r*   testTupletTypeNestedTest.testTupletTypeNested  s    	!"!yyf%D!$AJJ##F1aL1  	Q  --fQl;.."ANN1 
 KKM	''	2&&99'BD 3 	3784R[[  #((48,	
 32 9s   6E ),E1 
E.c                   S H  u  pn[        5       nXl        UR                  S5      nU R                  UR                  [	        U5      S5        UR                  S5      nU R                  UR                  [	        U5      S5        M     [        5       nSUl        [        SSS5      nUR                  U5        U R                  UR                  [	        S5      5        U R                  UR                  5       [	        S5      5        U R                  [        UR                  S	   R                  5      S
5        UR                  S5      nU R                  UR                  [	        S5      5        U R                  UR                  5       [	        S5      S5        U R                  [        UR                  S	   R                  5      S5        UR                  S5      nU R                  UR                  5       [	        S5      S5        U R                  [        UR                  S	   R                  5      S5        [        5       nSUl        U R                  UR                  5       [	        S5      S5        U R                  [        UR                  S	   R                  5      S
5        UR                  S5      nU R                  UR                  5       [	        S5      S5        U R                  [        UR                  S	   R                  5      S5        UR                  S5      nU R                  UR                  5       [	        S5      S5        U R                  [        UR                  S	   R                  5      S5        g )N))r   r   r   )r8   r:   r   )g      ?r  rH   )r  UUUUUU?gUUUUUU?r8   rI   r   r7   rH   r  r  r   z7DurationTuple(type='eighth', dots=0, quarterLength=0.5)z8DurationTuple(type='quarter', dots=0, quarterLength=1.0)r:   z6DurationTuple(type='16th', dots=0, quarterLength=0.25))r   r   r   r  r
   r   r   r  r  reprr   r   )	r   r	  r4   doubler  r  r  r  r  s	            r*   testAugmentOrDiminishTest.testAugmentOrDiminish  s   !8Bf 
A O##C(AQ__fTlA>##A&AQ__fVna@!8 JaH%	t&-8446uFaiil99:R	T "&-8446uqIaiil99:S	U %446uqIaiil99:Q	S J446uqIaiil99:R	T "446uqIaiil99:S	U %446uqIaiil99:Q	Sr)   c                   SSK Jn  UR                  5       nSUl        SUl        SUl        U R                  UR                  S5        U R                  UR
                  S5        UR                  5       nU R                  UR                  5        SUl        SUl        U R                  UR
                  S5        U R                  UR                  S5        U R                  UR                  5        SUl        U R                  UR                  S5        U R                  UR                  5        U R                  UR
                  S5        S	Ul        U R                  UR
                  S	5        U R                  UR                  S5        U R                  UR                  5        SUl        U R                  UR
                  S	5        U R                  UR                  5        g )
Nr   r  Fg      @r5   rC   r  g      4@r9   )	r  r   r   r  r   r   r  
assertTrueassertFalse)r   r   dur  s       r*   testUnlinkedTypeATest.testUnlinkedTypeA  sl   $ 	))3/),!+#."$/"+ ($/" ("r)   c                
   SSK Jn  SSK Jn  UR                  S5      nUR                  S   R                  UR                  5      S   n0 Ul        [        UR                  5        [        UR                  R                  5        g )Nr   )corpusr   ztrecento/PMFC_06-Jacopo-03a*   )r  r  r   parsepartsgetElementsByClassr  _cacheprintr   r{   )r   r  r   j1xs        r*   x_testStrangeMeasureTest.x_testStrangeMeasure3  s]    ""\\78HHQK**6>>:2>ajjajj##$r)   c                &   [        5       nSUl        U R                  [        UR                  5      S5        U R                  UR                  S5        U R                  UR                  5        U R                  [        UR                  5      S5        U R                  UR                  5        U R                  UR                  5        U R                  [        UR                  5      S5        U R                  [        [        U5      5      S5        g )Nr  zFraction(1, 3)r"   z:(DurationTuple(type='eighth', dots=0, quarterLength=0.5),)z-(Fraction(1, 3), 'eighth', 0, 3, 2, 'eighth'))r   r   r  r  rw  r  rz  r   r{   r  r{  r   r   r  s     r*   testSimpleSetQuarterLengthTest.testSimpleSetQuarterLength<  s    Jaoo.0@A+112Q\\*U	W223667aoo.0@AXa[)+Z[r)   c                   U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S	[        [        R                  " S
5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        U R                  S[        [        R                  " S5      5      R                  5        g)z}
Test tuplet durations are assigned with proper duration

This test was written while adding support for dotted tuplet notes
zEighth Triplet (1/3 QL)r  zQuarter Triplet (2/3 QL)r  z16th Quintuplet (1/5 QL)r  zEighth Quintuplet (2/5 QL)r  z!Dotted Eighth Quintuplet (3/5 QL)g333333?zQuarter Quintuplet (4/5 QL)g?z16th Septuplet (1/7 QL)g$I$I?zEighth Septuplet (2/7 QL)g$I$I?z Dotted Eighth Septuplet (3/7 QL)g۶m۶m?zQuarter Septuplet (4/7 QL)g$I$I?z!Dotted Quarter Septuplet (6/7 QL)g۶m۶m?N)r  r   r   r   r[  r  s    r*   testTupletDurationsTest.testTupletDurationsI  s    	%Y''./88	
 	&Y''./88	

 	&Y''./88	
 	(Y''./88	
 	/Y''./88	
 	)Y''./88	

 	%Y''./88	
 	'Y''./88	
 	.Y''./88	
 	(Y''./88	
 	/Y''./88	
r)   c                    [        S5      nU R                  UR                  S5        [        S5      nU R                  UR                  S5        g )Ngqq?r   g  ??)r   r  r   r  s     r*   testTinyDurationTest.testTinyDuration  sB     V1 X1r)   c                   [        S5      nU R                  UR                  S5        SUl        U R                  UR                  S5        SUl        U R                  UR                  S5        SUl        U R                  UR                  S5        UR                  [        SS5      5        U R                  UR                  S5        SUl        S	Ul        SUl        U R                  UR                  S5        g )
Nr8   Tr3   Fr:   r   rH   r   r   )	r   r  r  r   r   r   r  r   r  r  s     r*   testExpressionIsInferredTest.testExpressionIsInferred  s    SM//6//7//6//7	va|$//7 	//7r)   c                d   U R                  [        5         [        SSS9  SSS5        [        SS[	        S5      5      nSnU R                  [        U5         [        U5        SSS5        U R                  [        5         [        [	        S5      5        SSS5        [        S	5      nU R                  [        5         S
Ul        SSS5        U R                  [        5         UR                  S5        SSS5        U R                  [        5         UR                  S5        SSS5        U R                  [        5         SUl	        SSS5        U R                  [        5         SUl
        SSS5        U R                  [        5         SUl        SSS5        [        5       nU R                  [        5         SUl        SSS5        U R                  [        5         SUl        SSS5        g! , (       d  f       GN= f! , (       d  f       GN= f! , (       d  f       GN= f! , (       d  f       GNg= f! , (       d  f       GNJ= f! , (       d  f       GN-= f! , (       d  f       GN= f! , (       d  f       GN= f! , (       d  f       N= f! , (       d  f       N= f! , (       d  f       g= f)z
These errors are user errors, so they raise generic exceptions
so that catches for DurationException only get library calculation
failures (e.g. bound checking).
zredundant typer7   r   Nr5   r   nanr  r  zdo not linki  gMbPcustomTruenone)assertRaisesr  r   r   r   assertRaisesRegexr  r  r  r   r   r   r  rF  rC  )r   r   r  r  r  s        r*   testExceptionsTest.testExceptions  s    y)%H5 *9au6<##J4RL 5
 z*U5\" + UOy)$AH *z*))#. +z*))&1 +y)AK *y)AF *z*AF + _z* BK +z*BH +*; *) 54
 +* *)****))))** +***s   G/H H=H%"H7I	 I%I-
I?9JJ!/
G>
H
H"%
H47
I	
I
I*-
I<?
J
J!
J/c                   [        S5      nU R                  UR                  [        R                  " SS5      5        U R                  UR
                  S5        U R                  [        5         [        S5        SSS5        U R                  [        S5      S5        U R                  [        S5      S5        U R                  [        S5      S	5        [        S
5      nU R                  U[        5        UR                  nU R                  [        U5      S5        US   nU R                  U[         5        U R                  UR                  S5        U R                  UR
                  S5        U R                  UR"                  S5        U R%                  UR&                  5        U R                  UR&                  R)                  5       [        R                  " SS5      5        g! , (       d  f       GNr= f)zS
Test that some small rounding errors do not
give division by zero errors anymore.
g   ?i @  i  r   r   NrB   )r9   Fr   g   ?r   r  r7   r   rH   )r   r  r   r   r   r   r  r    r   r   r   r   assertIsInstancery   r{   r   r   r   r  r|   r   )r   r  or  c0s        r*   testSmallRoundTest.testSmallRound  s{    ]#)*<*<UE*JK101&q) 2 	3A6?3MB(	*Q8 56a!89LLQ#qTb-0))40
 	(+!$!224i6H6HA6NO1 21s   .G%%
G4r"   N)r$   r%   r&   r'   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r(   r"   r)   r*   r  r  %  sX    %(ET(4(B(@
>4Sl!#\%\4
l282$L$Pr)   r  r   
_DOC_ORDER__main__)r   r   rm  r   )r   r   rm  ztuple[str, bool])r   r   rm  r   )r   )r   r   rm  z;tuple[int, str] | tuple[t.Literal[False], t.Literal[False]])r   r   rm  ztuple[Tuplet, DurationTuple])r   r   r   r   rm  zlist[Tuplet])r   r   rm  ry   )r   NN)r   r   r   r   r   zlist[Tuplet] | Nonerm  r   )r   r   rm  r   )r6   )rm  r   )r5   r   )Yrs  
__future__r   collections.abcr   r  r0  r   	functoolsr   r  mathr   r   typingr  unittestr  r   music21.common.objectsr	   music21.common.numberToolsr
   music21.common.typesr   r   r   r   r   r   r   rf  r   r   r   EnvironmentenvironLocallimitOffsetDenominatorr   r   Literalri  rj  Music21Exceptionr    r-   rD   r}   rE   sortedr   keysrF   rG   rN   rw   
NamedTuplery   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r   ProtoM21Objectr   r   objectsFrozenObjectr4  r  r  rT  TestCaser}  r  r   r$   mainTestr"   r)   r*   <module>r     s  #H # $     	     5 - ? ?      ??&&z2--! YY@A
II<= 	55 		l33 	$T$d$ T$ S	$
 S$ C$ s$ c$ D$ E$ F$ W$ X$ ^$ n$  n!$" C#$  (%%% % 	%
 	&% 	&% 	&% 
7% 
7% 
7% H% H% % % 	'%  
8!%" O#%! & $*$/C/C/E*F#G [ G! I ( ,=  <- / all 
07f/,/,BJ0 (N(V..
..!..f ,G
GG 	GT 4[9 [9@ !%	??
? ?
 ?DDHALL HB EG A FBD  "? D9<)ZU	>W## U	>ru'w%%'9 u'p/$V^^00( $Lt!H t!n= 0z* z*@
8$$ @GP8 GPZ fm%?
H 
 zT r)   