§
    ƒØjù+  ã                  ó,  — d dl mZ d dlZd dlZd dlmZ d dlm	Z	 d dlm
Z
 d dlmZ d dlmZ ej        rd dlmZ d dlmc mZ d d	lmZ d
dœd-d„Zd„ Zd.d„Zd/d„Zd0d„Zd1d„Zd2d„Zd3d „Z	 	 d4d5d)„Z	 	 d4d6d+„Ze d,k    rd dlZ ej!        ¦   «          dS dS )7é    )ÚannotationsN)Útostring)Úcommon)Úmeter)Ú
xmlObjects)Úprebase)ÚCallable)ÚMusic21ObjectF)ÚnoCopyÚreturnÚstrc               óš  — |du rt          j        | ¦  «        }n| }t          |¦  «         |                     ¦   «         D ]f}|j        }t          |¦  «        dk    rJt          |                     ¦   «         ¦  «        }|                     ¦   «          | 	                    |¦  «         Œgt          |d¬¦  «        }|                     ¦   «         }|S )u¬  
    wrapper around xml.etree.ElementTree that returns a string
    in every case and indents tags and sorts attributes.

    >>> from music21.musicxml.m21ToXml import Element
    >>> from music21.musicxml.helpers import dumpString
    >>> e = Element('accidental')

    >>> dumpString(e)
    '<accidental />'

    >>> e.text = 'âˆ†'
    >>> e.text == 'âˆ†'
    True
    >>> dumpString(e)
    '<accidental>âˆ†</accidental>'
    Fé   Úunicode)Úencoding)ÚcopyÚdeepcopyÚindentÚiterÚattribÚlenÚsortedÚitemsÚclearÚupdateÚet_tostringÚrstrip)Úobjr   ÚxmlElÚelr   ÚattribsÚxStrs          ú�/Users/tedpeters/Documents/Projects/Claude Projects/Misc Tools/notename-sheets/.venv/lib/python3.11/site-packages/music21/musicxml/helpers.pyÚ
dumpStringr$      s´   € ð$ �€€Ý”˜cÑ"Ô"ˆˆàˆÝ
ˆ5�M„M€Mà�jŠj‰lŒlð #ð #ˆØ”ˆÝˆv‰;Œ;˜Š?ˆ?å˜VŸ\š\™^œ^Ñ,Ô,ˆGØ�LŠL‰NŒNˆNØ�MŠM˜'Ñ"Ô"Ð"øÝ�u yÐ1Ñ1Ô1€DØ�;Š;‰=Œ=€DØ€Kó    c                ó>   — t          t          | ¦  «        ¦  «         dS )u¬  
    wrapper around xml.etree.ElementTree that prints a string
    in every case and indents tags and sorts attributes.  (Prints, does not return)

    >>> from music21.musicxml.helpers import dump
    >>> from xml.etree.ElementTree import Element
    >>> e = Element('accidental')

    >>> dump(e)
    <accidental />

    >>> e.text = 'âˆ†'
    >>> e.text == 'âˆ†'
    True
    >>> dump(e)
    <accidental>âˆ†</accidental>
    N)Úprintr$   )r   s    r#   Údumpr(   A   s   € õ$ 
�*�S‰/Œ/ÑÔÐÐÐr%   c                óÜ  — d|dz  z   }t          | ¦  «        }|r¥| j        r| j                             ¦   «         s
|dz   | _        | j        r| j                             ¦   «         s|| _        d}| D ]}t	          ||dz   ¦  «         Œ|�||_        | j        r| j                             ¦   «         sd|dz  z   | _        dS dS |r)| j        r| j                             ¦   «         s|| _        dS dS dS )z4
    helper method, indent an element in place:
    ú
z  Nr   )r   ÚtextÚstripÚtailr   )ÚelemÚlevelÚiÚlenLÚsubElems        r#   r   r   V   s)  € ð 	ˆu�t‰|Ñ€AÝˆt‰9Œ9€DØð ØŒyð 	! ¤	§¢Ñ 1Ô 1ð 	!Ø˜D™ˆDŒIØŒyð 	 ¤	§¢Ñ 1Ô 1ð 	ØˆDŒIàˆØð 	'ð 	'ˆGÝ�7˜E A™IÑ&Ô&Ð&Ð&ØÐØˆGŒLàŒyð 	, ¤	§¢Ñ 1Ô 1ð 	,Ø˜u t™|Ñ+ˆDŒIˆIˆIð	,ð 	,ð ð 	˜$œ)ð 	¨4¬9¯?ª?Ñ+<Ô+<ð 	ØˆDŒIˆIˆIð	ð 	ð 	ð 	r%   c                ó*  — |s|                       |¦  «         dS t          | ¦  «        h}t          |                      d¦  «        ¦  «        D ]#\  }}|j        |v r|                     |¦  «         Œ$|                      t          |¦  «        |¦  «         dS )aH  
    Insert element `insert` into element `root` at the earliest position
    of any instance of a child tag given in `tagList`. Append the element
    if `tagList` is `None`.

    >>> from xml.etree.ElementTree import fromstring as EL
    >>> from music21.musicxml.helpers import insertBeforeElements, dump
    >>> root = EL('<clef><sign>G</sign><line>4</line></clef>')
    >>> insert = EL('<foo/>')

    >>> insertBeforeElements(root, insert, tagList=['line'])
    >>> dump(root)
    <clef>
        <sign>G</sign>
        <foo />
        <line>4</line>
    </clef>

    Now insert another element at the end by not specifying a tag list:

    >>> insert2 = EL('<bar/>')
    >>> insertBeforeElements(root, insert2)
    >>> dump(root)
    <clef>
        <sign>G</sign>
        <foo />
        <line>4</line>
        <bar />
    </clef>
    NÚ*)Úappendr   Ú	enumerateÚfindallÚtagÚaddÚinsertÚmin)Úrootr:   ÚtagListÚinsertIndicesr0   Úchilds         r#   ÚinsertBeforeElementsr@   o   sœ   € ð@ ð Ø�Š�FÑÔÐØˆÝ˜‘Y”Y�K€Må˜dŸlšl¨3Ñ/Ô/Ñ0Ô0ð !ð !‰ˆˆ5ØŒ9˜ÐÐØ×Ò˜aÑ Ô Ð øØ‡K‚K•�MÑ"Ô" FÑ+Ô+Ð+Ð+Ð+r%   ÚmNum1ÚmNum2Úboolc                ó  — d„ }| |k    rdS  || ¦  «        \  }} ||¦  «        \  }}t          |¦  «        t          |¦  «        k    r t          |¦  «        t          |¦  «        k     S t          ||g¦  «        }||d         u S )ag  
    Determine whether `measureNumber1` strictly precedes
    `measureNumber2` given that they could involve suffixes.
    Equal values return False.

    >>> from music21.musicxml.helpers import measureNumberComesBefore
    >>> measureNumberComesBefore('23', '24')
    True
    >>> measureNumberComesBefore('23', '23')
    False
    >>> measureNumberComesBefore('23', '23a')
    True
    >>> measureNumberComesBefore('23a', '23b')
    True
    >>> measureNumberComesBefore('23b', '23a')
    False
    >>> measureNumberComesBefore('23b', '24a')
    True
    >>> measureNumberComesBefore('23b', '23b')
    False
    c                óz   — d}| D ]}|                      ¦   «         r||z  }Œ | t          |¦  «        d …         }||fS )NÚ )Ú	isnumericr   )ÚmeasureNumberÚnumberÚcharÚsuffixs       r#   ÚsplitSuffixz-measureNumberComesBefore.<locals>.splitSuffix°   sT   € ØˆØ!ð 	ð 	ˆDØ�~Š~ÑÔð Ø˜$‘��àØ�s 6™{œ{˜|˜|Ô,ˆØ�vˆ~Ðr%   Fr   )Úintr   )rA   rB   rL   Ú	m1NumericÚm1SuffixÚ	m2NumericÚm2SuffixÚsortedSuffixess           r#   ÚmeasureNumberComesBeforerS   š   s™   € ð,ð ð ð �‚~€~ØˆuØ%˜+ eÑ,Ô,Ñ€IˆxØ%˜+ eÑ,Ô,Ñ€IˆxÝ
ˆ9�~„~�˜Y™œÒ'Ð'Ý�9‰~Œ~¥ I¡¤Ò.Ð.å ¨8Ð 4Ñ5Ô5ˆØ˜>¨!Ô,Ð,Ð,r%   Úrú'music21.note.Rest'c                ó²   — d}| j         dv rd}nH| j         dk    r=|                      t          j        ¦  «        }|r|j        j        | j        j        k    rd}|S )NF)TÚalwaysTÚauto)ÚfullMeasureÚgetContextByClassr   ÚTimeSignatureÚbarDurationÚquarterLengthÚduration)rT   ÚisFullMeasureÚ	tsContexts      r#   ÚisFullMeasureRestra   Å   sg   € Ø€MØ„}Ð(Ð(Ð(ØˆˆØ	
Œ˜&Ò	 Ð	 Ø×'Ò'­Ô(;Ñ<Ô<ˆ	Øð 	!˜Ô.Ô<ÀÄ
Ô@XÒXÐXØ ˆMØÐr%   Úelementú
ET.ElementÚ	m21Objectr
   c                óH   — |                       dd¦  «        }|sdS ||_        dS )a’  
    MusicXML 3.1 defines the id attribute
    (%optional-unique-id)
    on many elements which is perfect for setting as .id on
    a music21 element.

    <fermata id="hello"><id>bye</id></fermata>

    >>> from xml.etree.ElementTree import fromstring as EL
    >>> e = EL('<fermata id="fermata1"/>')
    >>> f = expressions.Fermata()
    >>> musicxml.helpers.synchronizeIdsToM21(e, f)
    >>> f.id
    'fermata1'

    Does not change the id if the id is not specified:

    >>> e = EL('<fermata />')
    >>> f = expressions.Fermata()
    >>> f.id = 'doNotOverwrite'
    >>> musicxml.helpers.synchronizeIdsToM21(e, f)
    >>> f.id
    'doNotOverwrite'
    ÚidN)Úgetrf   )rb   rd   ÚnewIds      r#   ÚsynchronizeIdsToM21ri   Ð   s/   € ð2 �KŠK˜˜dÑ#Ô#€EØð ØˆØ€I„L€L€Lr%   úprebase.ProtoM21Object | NoneÚNonec                óÐ   — t          |t          j        ¦  «        sdS t          |d¦  «        sdS |j        }|€dS t          j        |¦  «        sdS |                      d|¦  «         dS )a°  
    MusicXML 3.1 defines the id attribute (entity: %optional-unique-id)
    on many elements which is perfect for getting from .id on
    a music21 element.

    >>> from xml.etree.ElementTree import fromstring as EL
    >>> e = EL('<fermata />')
    >>> f = expressions.Fermata()
    >>> f.id = 'fermata1'
    >>> musicxml.helpers.synchronizeIdsToXML(e, f)
    >>> e.get('id')
    'fermata1'

    Does not set attr: id if el.id is not valid or default:

    >>> e = EL('<fermata />')
    >>> f = expressions.Fermata()
    >>> musicxml.helpers.synchronizeIdsToXML(e, f)
    >>> e.get('id', None) is None
    True
    >>> f.id = '123456'  # invalid for MusicXML id
    >>> musicxml.helpers.synchronizeIdsToXML(e, f)
    >>> e.get('id', None) is None
    True

    None can be passed in instead of a m21object.

    >>> e = EL('<fermata />')
    >>> musicxml.helpers.synchronizeIdsToXML(e, None)
    >>> e.get('id', 'no idea')
    'no idea'
    Nrf   )Ú
isinstancer   ÚProtoM21ObjectÚhasattrrf   r   ÚisValidXSDIDÚset)rb   rd   Úm21Ids      r#   ÚsynchronizeIdsToXMLrs   î   sy   € õN �i¥Ô!7Ñ8Ô8ð ØˆÝ�9˜dÑ#Ô#ð ØˆàŒL€Eà€}ØˆåÔ" 5Ñ)Ô)ð ØˆØ‡K‚K��eÑÔÐÐÐr%   Úm21Elút.Anyr   ÚxmlAttributeNameÚattributeNameú
str | NoneÚ	transformúCallable[[str], t.Any] | Nonec                ó    — |                      |¦  «        }|€dS |� ||¦  «        }|€t          j        |¦  «        }t          | ||¦  «         dS )a·  
    If xmlEl has at least one element of tag==tag with some text. If
    it does, set the attribute either with the same name (with "foo-bar" changed to
    "fooBar") or with attributeName to the text contents.

    Pass a function or lambda function as transform to transform the value before setting it

    >>> from xml.etree.ElementTree import fromstring as EL
    >>> e = EL('<page-layout new-page="yes" page-number="4" />')

    >>> setb = musicxml.helpers.setM21AttributeFromAttribute
    >>> pl = layout.PageLayout()
    >>> setb(pl, e, 'page-number')
    >>> pl.pageNumber
    '4'

    >>> setb(pl, e, 'new-page', 'isNew')
    >>> pl.isNew
    'yes'

    Transform the pageNumber value to an int.

    >>> setb(pl, e, 'page-number', transform=int)
    >>> pl.pageNumber
    4

    More complex:

    >>> convBool = musicxml.xmlObjects.yesNoToBoolean
    >>> setb(pl, e, 'new-page', 'isNew', transform=convBool)
    >>> pl.isNew
    True
    N)rg   r   ÚhyphenToCamelCaseÚsetattr©rt   r   rv   rw   ry   Úvalues         r#   ÚsetM21AttributeFromAttributer€   %  se   € ðP �IŠIÐ&Ñ'Ô'€EØ€}ØˆàÐØ�	˜%Ñ Ô ˆàÐÝÔ0Ð1AÑBÔBˆÝˆE�= %Ñ(Ô(Ð(Ð(Ð(r%   úCallable[[t.Any], t.Any] | Nonec                ó¼   — |€t          j        |¦  «        }t          | |d¦  «        }|€dS |� ||¦  «        }|                     |t	          |¦  «        ¦  «         dS )aæ  
    If m21El has at least one element of tag==tag with some text. If
    it does, set the attribute either with the same name (with "foo-bar" changed to
    "fooBar") or with attributeName to the text contents.

    Pass a function or lambda function as transform to transform the value before setting it

    >>> from xml.etree.ElementTree import fromstring as EL
    >>> e = EL('<page-layout/>')

    >>> setb = musicxml.helpers.setXMLAttributeFromAttribute
    >>> pl = layout.PageLayout()
    >>> pl.pageNumber = 4
    >>> pl.isNew = True

    >>> setb(pl, e, 'page-number')
    >>> e.get('page-number')
    '4'

    >>> XB = musicxml.m21ToXml.XMLExporterBase()
    >>> XB.dump(e)
    <page-layout page-number="4" />

    >>> setb(pl, e, 'new-page', 'isNew')
    >>> e.get('new-page')
    'True'

    Transform the isNew value to 'yes'.

    >>> convBool = musicxml.xmlObjects.booleanToYesNo
    >>> setb(pl, e, 'new-page', 'isNew', transform=convBool)
    >>> e.get('new-page')
    'yes'
    N)r   r|   Úgetattrrq   r   r~   s         r#   ÚsetXMLAttributeFromAttributer„   Y  sm   € ðR ÐÝÔ0Ð1AÑBÔBˆå�E˜=¨$Ñ/Ô/€EØ€}ØˆàÐØ�	˜%Ñ Ô ˆà	‡I‚IÐ¥ E¡
¤
Ñ+Ô+Ð+Ð+Ð+r%   Ú__main__)r   r   )r   )N)rA   r   rB   r   r   rC   )rT   rU   r   rC   )rb   rc   rd   r
   )rb   rc   rd   rj   r   rk   )NN)rt   ru   r   rc   rv   r   rw   rx   ry   rz   r   rk   )
rt   ru   r   rc   rv   r   rw   rx   ry   r�   )"Ú
__future__r   r   ÚtypingÚtÚxml.etree.ElementTreer   r   Úmusic21r   r   Úmusic21.musicxmlr   r   ÚTYPE_CHECKINGÚcollections.abcr	   ÚetreeÚElementTreeÚETÚmusic21.baser
   r$   r(   r   r@   rS   ra   ri   rs   r€   r„   Ú__name__ÚmainTest© r%   r#   ú<module>r•      sø  ðð #Ð "Ð "Ð "Ð "Ð "à €€€Ø Ð Ð Ð Ø 9Ð 9Ð 9Ð 9Ð 9Ð 9à Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø Ð Ð Ð Ð Ð à„?ð +Ø(Ð(Ð(Ð(Ð(Ð(Ø&Ð&Ð&Ð&Ð&Ð&Ð&Ð&Ð&à*Ð*Ð*Ð*Ð*Ð*ð $ð !ð !ð !ð !ð !ð !ðHð ð ð*ð ð ð ð2(,ð (,ð (,ð (,ðV(-ð (-ð (-ð (-ðVð ð ð ðð ð ð ð<3ð 3ð 3ð 3ðv #Ø-1ð1)ð 1)ð 1)ð 1)ð 1)ðp #Ø/3ð3,ð 3,ð 3,ð 3,ð 3,ðn ˆzÒÐØ€N€N€NØ€GÔÑÔÐÐÐð Ðr%   