§
    ƒØjÚ&  ã                  óê  — d Z ddlmZ ddlmZmZ ddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZg d¢ZddlmZ ej        r ej        d¦  «        Zd+d„Zddœd,d„Zd„ Zd-d„Zd.d„Zd/d„Zd„ Zed0d„¦   «         Zd0d„Zd0d „Z  e!d¦  «         e!e"¦  «         e!e#¦  «        e$e%e&e'e(e)ej*        e!e+ej,        ej-        ej.        e/hZ0d1d!d"œd2d'„Z1d3d)„Z2e3d*k    rddl4Z4 e4j5        ¦   «          dS dS )4zO
If it doesn't fit anywhere else in the common directory, you'll find it here!
é    )Úannotations)ÚCallableÚIterableN)
ÚcleanedFlatNotationÚdefaultDeepcopyÚflattenListÚgetMissingImportStrÚgetPlatformÚmacOSVersionÚ	pitchListÚrunningInNotebookÚsortModulesÚunique)ÚcacheÚ_TÚoriginalListúIterable[Iterable[_T]]Úreturnúlist[_T]c                ó   — d„ | D ¦   «         S )a"  
    Flatten a list of lists into a flat list:

    >>> l = [[1, 2, 3], [4, 5], [6]]
    >>> common.flattenList(l)
    [1, 2, 3, 4, 5, 6]

    But not a list of lists-of-lists!

    >>> l2 = [[1, 2, 3], [4, 5], [6, [7, 8]]]
    >>> common.flattenList(l2)
    [1, 2, 3, 4, 5, 6, [7, 8]]
    c                ó   — g | ]	}|D ]}|‘ŒŒ
S © r   )Ú.0ÚsublistÚitems      úˆ/Users/tedpeters/Documents/Projects/Claude Projects/Misc Tools/notename-sheets/.venv/lib/python3.11/site-packages/music21/common/misc.pyú
<listcomp>zflattenList.<locals>.<listcomp>?   s%   € ÐAÐAÐA�W¸ÐAÐA°ˆDÐAÐAÐAÐAó    r   )r   s    r   r   r   1   s   € ð BÐA ÐAÑAÔAÐAr   )Úkeyr   r   úCallable | NoneÚlistc               ó®   — t          ¦   «         }g }| D ]A}|r ||¦  «        }n|}||v rŒ|                     |¦  «         |                     |¦  «         ŒB|S )aµ  
    Return a List of unique items from an iterable, preserving order.
    (unlike casting to a set and back)

    (And why is this not already in Python?)

    >>> common.misc.unique([3, 2, 4, 3, 2, 5])
    [3, 2, 4, 5]

    Works on any iterable, but order might not be preserved for sets, etc.

    >>> common.misc.unique(range(5))
    [0, 1, 2, 3, 4]

    If key is a function then use that to get the value:

    >>> s = converter.parse('tinyNotation: c4 E d C f# e a')
    >>> common.misc.unique(s.recurse().notes, key=lambda n: n.name)
     [<music21.note.Note C>,
      <music21.note.Note E>,
      <music21.note.Note D>,
      <music21.note.Note F#>,
      <music21.note.Note A>]
    )ÚsetÚaddÚappend)r   r   ÚseenÚoutÚelÚelKeys         r   r   r   B   sn   € õ2 ‰5Œ5€DØ
€CØð ð ˆØð 	Ø�C˜‘G”GˆEˆEàˆEØ�Dˆ=ˆ=ØØ�Š�‰ŒˆØ�
Š
�2‰ŒˆˆØ€Jr   c                óÊ   — | sdS t          | ¦  «        dk    r | d         }t          j        d|› d�¦  «        S d                     | ¦  «        }t          j        d|› d�¦  «        S )	aï  
    Given a list of missing module names, returns a nicely-formatted message to the user
    that gives instructions on how to expand music21 with optional packages.

    >>> print(common.getMissingImportStr(['matplotlib']))
    Certain music21 functions might need the optional package matplotlib;
    if you run into errors, install it by following the instructions at
    https://www.music21.org/music21docs/installing/installAdditional.html

    >>> print(common.getMissingImportStr(['matplotlib', 'numpy']))
    Certain music21 functions might need these optional packages: matplotlib, numpy;
    if you run into errors, install them by following the instructions at
    https://www.music21.org/music21docs/installing/installAdditional.html
    Né   r   z:Certain music21 functions might need the optional package z¯;
                  if you run into errors, install it by following the instructions at
                  https://www.music21.org/music21docs/installing/installAdditional.htmlú, z>Certain music21 functions might need these optional packages: z³;
                   if you run into errors, install them by following the instructions at
                   https://www.music21.org/music21docs/installing/installAdditional.html)ÚlenÚtextwrapÚdedentÚjoin)ÚmodNameListÚms     r   r	   r	   l   s¤   € ð ð ]ØˆtÝ	ˆ[Ñ	Ô	˜QÒ	Ð	Ø˜ŒNˆÝŒð  [Ð^_ð  [ð  [ð  [ñ \ô \ð 	\ð �IŠI�kÑ"Ô"ˆÝŒð\Èqð \ð \ð \ñ]ô ]ð 	]r   Ústrc                 ó¢   — t          j        ¦   «         dk    rdS t          j        ¦   «         dk    rdS t          j        dk    rdS t          j        S )aH  
    Return the name of the platform, where platforms are divided
    between 'win' (for Windows), 'darwin' (for MacOS X), and 'nix' for
    (GNU/Linux and other variants).

    Does not discern between Linux/FreeBSD, etc.

    Lowercase names are for backwards compatibility -- this existed before
    the platform module.
    ÚWindowsÚwinÚDarwinÚdarwinÚposixÚnix)ÚplatformÚsystemÚosÚnamer   r   r   r
   r
   Š   sM   € õ „ÑÔ˜IÒ%Ð%ØˆuÝ	ŒÑ	Ô	˜hÒ	&Ð	&ØˆxÝ	Œ�GÒ	Ð	ØˆuåŒwˆr   útuple[int, int, int]c                 ó  — t          ¦   «         dk    rdS t          d„ t          j        ¦   «         d                              d¦  «        D ¦   «         ¦  «        ^} }|r|d         nd}t          |¦  «        dk    r|d         nd}| ||fS )z�
    On a Mac returns the current version as a tuple of (currently 3) ints,
    such as: (10, 5, 6) for 10.5.6.

    On other systems, returns (0, 0, 0)
    r8   )r   r   r   c              3  ó4   K  — | ]}t          |¦  «        V — Œd S ©N)Úint)r   Úvs     r   ú	<genexpr>zmacOSVersion.<locals>.<genexpr>«   s(   è è € Ð)[Ð)[°Q­#¨a©&¬&Ð)[Ð)[Ð)[Ð)[Ð)[Ð)[r   r   ú.r+   )r
   Útupler;   Úmac_verÚsplitr-   )ÚmajorÚminor_and_maintenanceÚminorÚmaintenances       r   r   r   Ÿ   sŸ   € õ �}„}˜Ò Ð Øˆyõ %*Ð)[Ð)[½(Ô:JÑ:LÔ:LÈQÔ:O×:UÒ:UÐVYÑ:ZÔ:ZÐ)[Ñ)[Ô)[Ñ$[Ô$[Ð!€EÐ!à(=ÐDÐ! !Ô$Ð$À1€EÝ.1Ð2GÑ.HÔ.HÈ1Ò.LÐ.LÐ'¨Ô*Ð*ÐRS€Kà�5˜+Ð&Ð&r   Ú
moduleListúIterable[t.Any]úlist[object]c                óf  ‡— g }i Š| D ]r}|‰|j         <   |j        }t          j        |¦  «        }t	          j        |d         ¦  «        }t	          j        |¦  «        }|                     |||j         f¦  «         Œs|                     ¦   «          | 	                    ¦   «          ˆfd„|D ¦   «         }|S )zÝ
    Sort a list of imported module names such that most recently modified is
    first.  In ties, last access time is used then module name

    Will return a different order each time depending on the last mod time
    é   c                ó(   •— g | ]\  }}}‰|         ‘ŒS r   r   )r   ÚlastmodÚasctimeÚmodNameÚmodNameToMods       €r   r   zsortModules.<locals>.<listcomp>Æ   s%   ø€ ÐKÐKÐKÑ)B¨°'¸7ˆ|˜GÔ$ÐKÐKÐKr   )
Ú__name__Ú__file__r=   ÚstatÚtimeÚ	localtimerU   r%   ÚsortÚreverse)	rN   r]   ÚmodÚfprZ   rT   rU   ÚoutModsrW   s	           @r   r   r   ³   s¶   ø€ ð €DØ€LØð 6ð 6ˆØ%(ˆ�S”\Ñ"ØŒ\ˆÝŒw�r‰{Œ{ˆÝ”.  a¤Ñ)Ô)ˆÝ”,˜wÑ'Ô'ˆØ�Š�W˜g s¤|Ð4Ñ5Ô5Ð5Ð5Ø‡I‚I�K„K€KØ‡L‚L�N„N€NàKÐKÐKÐKÀdÐKÑKÔK€GØ€Nr   c                óL   — dd                      d„ | D ¦   «         ¦  «        z   dz   S )zž
    utility method that replicates the previous behavior of
    lists of pitches.

    May be moved in v8 or later to a common.testing or test.X module.
    ú[r,   c                ó   — g | ]	}|j         ‘Œ
S r   )ÚnameWithOctave)r   Úxs     r   r   zpitchList.<locals>.<listcomp>Ò   s   € Ð=Ð=Ð=°˜AÔ,Ð=Ð=Ð=r   ú])r0   )ÚpitchLs    r   r   r   Ë   s/   € ð �—’Ð=Ð=°fÐ=Ñ=Ô=Ñ>Ô>Ñ>ÀÑDÐDr   Úboolc                 óF   — t          ¦   «         rdS t          ¦   «         rdS dS )aW  
    return bool if we are running under Jupyter Notebook (not IPython terminal)
    or Google Colabatory (colab) or Marimo.

    Methods based on:

    https://stackoverflow.com/questions/15411967/how-can-i-check-if-code-is-executed-in-the-ipython-notebook
    (No tests provided here, since results will differ depending on environment)
    TF)ÚrunningInJupyterOrColabÚrunningInMarimor   r   r   r   r   Õ   s/   € õ Ñ Ô ð ØˆtÝ	Ñ	Ô	ð Øˆtàˆur   c                 ó6   — t           j        j        j        dk    S )NÚ	OutStream)ÚsysÚstderrÚ	__class__rX   r   r   r   rk   rk   ç   s   € ÝŒ:ÔÔ(¨KÒ7Ð7r   c                 ód   — dt           j        vrdS t          d¦  «                             ¦   «         S )NÚmarimoF)ro   ÚmodulesÚ
__import__Úrunning_in_notebookr   r   r   rl   rl   ê   s.   € Ø•s”{Ð"Ð"Øˆuå�hÑÔ×3Ò3Ñ5Ô5Ð5r   r   )ÚignoreAttributesÚobjút.Anyrw   úIterable[str]c          	     óz  — |€i }|                       d¦  «        }|dd…         \  }}} ||Ž }||t          | ¦  «        <   |                     ¦   «         D ]g\  }}	||v rt          ||d¦  «         Œt	          |	¦  «        t
          v rt          |||	¦  «         ŒCt          ||t          j        |	|¦  «        ¦  «         Œh|S )aÊ  
    Unfortunately, it is not possible to do something like::

        def __deepcopy__(self, memo):
            if self._noDeepcopy:
                return self.__class__()
            else:
                copy.deepcopy(self, memo, ignore__deepcopy__=True)

    Or, else: return NotImplemented

    so that's what this is for::

        def __deepcopy__(self, memo):
            if self._noDeepcopy:
                return self.__class__()
            else:
                return common.defaultDeepcopy(self, memo)

    Does a deepcopy of the state returned by `__reduce_ex__` for protocol 4.

    * Changed in v9: callInit is removed, replaced with ignoreAttributes.
      uses `__reduce_ex__` internally.
    Né   é   )Ú__reduce_ex__ÚidÚitemsÚsetattrÚtypeÚ_IMMUTABLE_DEEPCOPY_TYPESÚcopyÚdeepcopy)
rx   Úmemorw   ÚrvÚfuncÚargsÚstateÚnewÚattrÚvalues
             r   r   r     sÚ   € ð2 €|Øˆà	×	Ò	˜1Ñ	Ô	€BØ˜2˜A˜2œÑ€Dˆ$�Ø
ˆ$�ˆ+€CØ€D�ˆC‰Œ�Mð —{’{‘}”}ð ;ð ;‰ˆˆeØÐ#Ð#Ð#Ý�C˜˜tÑ$Ô$Ð$Ð$Ý�%‰[Œ[Õ5Ð5Ð5Ý�C˜˜uÑ%Ô%Ð%Ð%å�C˜�tœ}¨U°DÑ9Ô9Ñ:Ô:Ð:Ð:Ø€Jr   Ú	music_strc                ó.   — t          j        dd| ¦  «        S )aA  
    Returns a copy of the given string where each occurrence of a flat note
    specified with a 'b' is replaced by a '-'.

    music_str is a string containing a note specified (for example in a chord)

    Returns a new string with flats only specified with '-'.

    >>> common.cleanedFlatNotation('Cb')
    'C-'
    z([A-Ga-g])bz\1-)ÚreÚsub)rŽ   s    r   r   r   -  s   € õ Œ6�- ¨Ñ3Ô3Ð3r   Ú__main__)r   r   r   r   )r   r   r   r    r   r!   )r   r3   )r   r?   )rN   rO   r   rP   )r   ri   rB   )rx   ry   rw   rz   )rŽ   r3   r   r3   )6Ú__doc__Ú
__future__r   Úcollections.abcr   r   r„   r=   r;   r�   ro   r.   r[   ÚtypesÚtypingÚtÚweakrefÚ__all__Ú	functoolsr   ÚTYPE_CHECKINGÚTypeVarr   r   r   r	   r
   r   r   r   r   rk   rl   r‚   ÚEllipsisÚNotImplementedrC   Úfloatri   ÚcomplexÚbytesr3   ÚCodeTypeÚrangeÚBuiltinFunctionTypeÚFunctionTypeÚrefÚpropertyrƒ   r   r   rX   Úmusic21ÚmainTestr   r   r   ú<module>r«      s~  ððð ð #Ð "Ð "Ð "Ð "Ð "à .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ø €€€Ø 	€	€	€	Ø €€€Ø 	€	€	€	Ø 
€
€
€
Ø €€€Ø €€€Ø €€€Ø Ð Ð Ð Ø €€€ðð ð €ð Ð Ð Ð Ð Ð à„?ð Ø	ˆŒ�4‰Œ€Bð
Bð Bð Bð Bð" <@ð $ð $ð $ð $ð $ð $ðT]ð ]ð ]ð<ð ð ð ð*'ð 'ð 'ð 'ð(ð ð ð ð0Eð Eð Eð ðð ð ñ „ðð"8ð 8ð 8ð 8ð6ð 6ð 6ð 6ð  	€Dˆ�J„J���X‘”   ^Ñ 4Ô 4Øˆ��g˜u cØ	„N�D˜%Ø	Ô˜uÔ1Ø„K�ðÐ ð)ÐPRð )ð )ð )ð )ð )ð )ðX4ð 4ð 4ð 4ð ˆzÒÐØ€N€N€NØ€GÔÑÔÐÐÐð Ðr   