ó
    Ù“,j�a  ã                   óP  • S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKrSSKJr  SSKJr  SS\R                  R(                  4S jr " S S5      r " S	 S
5      rS rSS jrS rS rS rS rS rS rS r S r!S r"SS jr#SS jr$S r%S r&SS jr'g)z~This library gathers utilities for hyperpyyaml loading

Authors
 * Peter Plantinga 2020
 * Aku Rouhe 2020
 * Jianchen Li 2022
é    N)ÚStringIO)ÚRepresenterErrorTc                 ój  • [        XU5      n UR                  S[        S9  [        R                  " S5      nUR                  SUSS9  UR                  S[        5        UR                  S[        5        UR                  S[        5        UR                  S	[        5        S
[        R                  R                  R                  l        S
[         R                  R                  R                  R                  l        [        R"                  " XS9nS[        R                  R                  R                  l        S[         R                  R                  R                  R                  l        UR%                  5        Vs/ s H  ofR'                  S5      (       d  M  UPM     nnU H  nXX	 M     U$ s  snf )a‘  This function implements the HyperPyYAML syntax

The purpose for this syntax is a compact, structured hyperparameter and
function definition. This function implements a few extensions to the yaml
syntax, listed below.

**PyYAML complex tag shortcuts**

Part of our clean structured hyperparameter interface is being able to
specify python objects easily and cleanly. This is possible with
native YAML using the following syntax:

.. code-block:: yaml

    alignment_saver: !!python/object/new:speechbrain.data_io.TensorSaver
        kwargs: {save_dir: results/asr/ali}

However, due to the extensive use within speechbrain yaml files, we have
added a shortcut for this that has the following syntax:

.. code-block:: yaml

    alignment_saver: !new:speechbrain.data_io.TensorSaver
        save_dir: results/asr/ali

In this example, the alignment_saver will be an instance of the
``TensorSaver`` class, with ``'exp/asr/ali'`` passed to the
``__init__()`` method as a keyword argument. This is equivalent to:

.. code-block:: python

    import speechbrain.data_io.data_io
    alignment_saver = speechbrain.data_io.TensorSaver(
        save_dir='exp/asr/ali'
    )

We have also implemented a few more shortcuts:::

    !!python/name: => !name:
    !!python/module: => !module:
    !!python/object/apply: => !apply:

**References and copies**

Allows internal references to any node in the file. Any node with
tag ``!ref`` will create an object reference to the yaml object at the
``<key.subkey>`` location within the yaml itself,
following reference chains.

.. code-block:: yaml

    output_folder: results/asr
    alignment_saver: !new:speechbrain.data_io.TensorSaver
        save_dir: !ref <output_folder>

Strings values are handled specially: references are substituted but
the rest of the string is left in place, allowing filepaths to be
easily extended:

.. code-block:: yaml

    output_folder: results/asr
    alignment_saver: !new:speechbrain.data_io.TensorSaver
        save_dir: !ref <output_folder>/ali  # results/asr/ali

A more complex example for demonstration purposes:

.. code-block:: yaml

    key1: {a: !new:object {arg1: 1}}
    key2: !ref <key1[a]>

Here, ``key2`` will contain a reference to the ``a`` object, so changing
``a.arg1`` will also change ``key2.arg1``. If you need a
deep copy of the object instead of a shallow reference, you
can use a similar syntax with the tag ``!copy``. For example:

.. code-block:: yaml

    key1: {a: !new:object {arg1: 1}}
    key2: !copy <key1[a]>

These will also implement very basic arithmetic, so:

.. code-block:: yaml

    key1: 1
    key2: !ref <key1> + 3  # this is 4

**Tuples**

One last minor enhancement is an implicit tuple resolver. Passing
a string value of ``(3, 4)`` will be given a tag of ``!tuple`` which is
then interpreted as a tuple.

Arguments
---------
yaml_stream : stream
    A file-like object or string from which to read.
overrides : mapping or str
    A set of overrides for the values read from the stream.
    As yaml implements a nested structure, so can the overrides.
    See `speechbrain.utils.data_utils.recursive_update`
overrides_must_match : bool
    Whether an error will be thrown when an override does not match
    a corresponding key in the yaml_stream.
return_dict : bool
    Whether to return a dictionary rather than the default namespace.
loader : Loader
    Use to parse the yaml_stream, could be `ruamel.yaml.Loader`,
    `yaml.Loader`, etc.

Returns
-------
hparams : dict
    Reflects the structure of ``yaml_stream``.

Example
-------
>>> yaml_string = """
... a: 3
... thing: !new:collections.Counter
...     b: !ref <a>
... """
>>> params = load_hyperpyyaml(yaml_string)
>>> params["thing"]
Counter({'b': 3})
z!tuple)ÚtagÚconstructorz^\(.*\)$Ú()Úfirstú!new:ú!name:ú!module:ú!apply:)T©ÚLoader©FÚ__)Úresolve_referencesÚadd_constructorÚ_make_tupleÚreÚcompileÚadd_implicit_resolverÚadd_multi_constructorÚ_construct_objectÚ_construct_nameÚ_construct_moduleÚ_apply_functionÚyamlr   ÚBaseConstructorÚconstruct_objectÚ__defaults__ÚruamelÚloadÚkeysÚ
startswith)	Úyaml_streamÚ	overridesÚoverrides_must_matchÚloaderÚtuple_patternÚhparamsÚkÚremoval_keysÚkeys	            ÚžC:\Users\johnn\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\hyperpyyaml/core.pyÚload_hyperpyyamlr/      s[  € ôF % [Ð=QÓR€Kð ×Ñ˜x´[ÐÑAÜ—J’J˜{Ó+€MØ
× Ñ  ¨=ÀÐ ÑDð × Ñ  Ô*;Ô<Ø
× Ñ  ¬?Ô;Ø
× Ñ  Ô->Ô?Ø
× Ñ  ¬OÔ<ðF„D×Ñ×$Ñ$×5Ñ5ÔBðM„F‡K�K×Ñ×+Ñ+×<Ñ<ÔIô �iŠi˜Ñ3€GðF„D×Ñ×$Ñ$×5Ñ5ÔBðM„F‡K�K×Ñ×+Ñ+×<Ñ<ÔIð
  'Ÿ|™|œ~ÓDš~˜!·±¸d×1C—A™~€LÐDÛˆØŠLñ ð €Nùò	 Es   Å>F0ÆF0c                   ó2   • \ rS rSrSrSrS r\S 5       rSr	g)ÚRefTagéÎ   z¤Class for dumping !ref tags to yaml

Arguments
---------
ref_str : str
    String including yaml keys in `<key>` notation

Example
-------
See ``dump_hyperpyyaml``
ú!refc                 ó   • Xl         g ©N©Úref_str)Úselfr7   s     r.   Ú__init__ÚRefTag.__init__Ý   s   € Ø�ó    c                 óN   • UR                  U R                  UR                  5      $ r5   )Úrepresent_scalarÚyaml_tagr7   ©ÚclsÚrepresenterÚnodes      r.   Úto_yamlÚRefTag.to_yamlà   s   € à×+Ñ+¨C¯L©L¸$¿,¹,ÓGÐGr;   r6   N)
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r>   r9   ÚclassmethodrC   Ú__static_attributes__© r;   r.   r1   r1   Î   s)   † ñ
ð €Hòð ñHó óHr;   r1   c                   ó,   • \ rS rSrSrSr\S 5       rSrg)ÚPlaceholderéå   zVClass for dumping !PLACEHOLDER tags to yaml

Example
-------
See ``dump_hyperpyyaml``
ú!PLACEHOLDERc                 ó:   • UR                  U R                  S5      $ )NÚ )r=   r>   r?   s      r.   rC   ÚPlaceholder.to_yamlï   s   € à×+Ñ+¨C¯L©L¸"Ó=Ð=r;   rL   N)	rE   rF   rG   rH   rI   r>   rJ   rC   rK   rL   r;   r.   rN   rN   å   s    † ñð €Hàñ>ó ó>r;   rN   c                 ó$  • [         R                  R                  5       nUR                  R	                  [
        [
        R                  5        UR                  R	                  [        [        R                  5        UR                  " X/UQ70 UD6  g)a·  Dump yaml including placeholder and reference tags.

Arguments
---------
yaml_tree : dict
    An object to dump
output_stream : stream
    A file stream for putting the yaml
*args, **kwargs
    Arguments to forward to ruamel.yaml.YAML().dump()

Example
-------
>>> to_yaml = {'a': Placeholder(), 'b': RefTag('<a>')}
>>> stringio = StringIO()
>>> dump_hyperpyyaml(to_yaml, stringio)
>>> stringio.getvalue()
'a: !PLACEHOLDER\nb: !ref <a>\n'
N)	r!   r   ÚYAMLrA   Úadd_representerr1   rC   rN   Údump)Ú	yaml_treeÚoutput_streamÚargsÚkwargsÚruamel_yamls        r.   Údump_hyperpyyamlr]   ô   sd   € ô( —+‘+×"Ñ"Ó$€KØ×Ñ×+Ñ+¬F´F·N±NÔCØ×Ñ×+Ñ+¬K¼×9LÑ9LÔMØ×Ò�YÐ?°Ò?¸Ó?r;   c                 óÎ  • Sn[        U S5      (       aF  [        R                  R                  [        R                  R	                  U R
                  5      5      n[        R                  R                  5       nUR                  U 5      nUb@  [        U5      S:”  a1  [        U[        5      (       a  UR                  U5      n [        XQUS9  [!        SXUU5        [#        5       n  UR%                  XP5        U R'                  S5        U $ ! [         a    [        SU5      ef = f! [(         a8  nUR*                  S   S-   4Ul        UR-                  UR.                  5      eSnAff = f)a“  Resolves inter-document references, a component of HyperPyYAML.

Arguments
---------
yaml_stream : stream
    A file-like object or string with the contents of a yaml file
    written with the HyperPyYAML syntax.
overrides : mapping or str
    Replacement values, either in a yaml-formatted string or a dict.
overrides_must_match : bool
    Whether an error will be thrown when an override does not match
    a corresponding key in the yaml_stream. This is the opposite
    default from ``load_hyperpyyaml`` because ``resolve_references``
    doesn't need to be as strict by default.

Returns
-------
stream
    A yaml-formatted stream with all references and overrides resolved.

Example
-------
>>> yaml_string = """
... constants:
...     a: 3
...     b: !ref <constants[a]>
... """
>>> overrides = {'constants': {'a': 4}}
>>> resolve_references(yaml_string, overrides).getvalue()
'constants:\n  a: 4\n  b: 4\n'
NÚnamer   )Ú
must_matchzLThe structure of the overrides doesn't match the structure of the document: Úrootz$. Please use the !apply tag instead.)ÚhasattrÚosÚpathÚdirnameÚrealpathr_   r!   r   rU   r"   ÚlenÚ
isinstanceÚstrÚrecursive_updateÚ	TypeErrorÚ
ValueErrorÚ_walk_tree_and_resolver   rW   Úseekr   rZ   Úwith_tracebackÚ__traceback__)r%   r&   r'   Ú	file_pathr\   ÚpreviewÚes          r.   r   r     sD  € ðB €IÜˆ{˜F×#Ñ#Ü—G‘G—O‘O¤B§G¡G×$4Ñ$4°[×5EÑ5EÓ$FÓGˆ	ô —+‘+×"Ñ"Ó$€KØ×Ñ˜{Ó+€Gð Ñ¤ Y£°!Ó!3Ü�i¤×%Ñ%Ø#×(Ñ(¨Ó3ˆIð	Ü˜WÐ<PÒQô ˜6 7°YÔ?ä“*€Kð0à×Ñ˜Ô.Ø×Ñ˜Ôð
 Ðøô' ó 	Üð2àóð ð	ûô ó 0Ø—&‘&˜‘)ÐDÑDÐFˆŒØ×Ñ˜qŸ™Ó/Ð/ûð0ús$   Ã
D Ã$"D" ÄDÄ"
E$Ä,3EÅE$c                 óè  • [        U[        5      (       a3  [        U5       H#  u  pEU S:X  a  UOU  SU S3n[        XeX#5      X'   M%     OL[        U[        5      (       a7  UR                  5        H#  u  puU S:X  a  UOU  SU S3n[        XeX#5      X'   M%     [        US5      (       Ga(  UR                  R                  =(       d    SnUS:X  a  [        SU  S35      eUS	;   a  US
:H  n	[        UR                  / UU	S9nU$ UR                  S5      (       aŒ  U[        S5      S n
Ub  [        R                  R                  X:5      n
 [	        U5      n[#        U
5       n[%        XË5      nSSS5        [&        R(                  R+                  5       nUR-                  W5      nU$ UR                  S5      (       a  U[        S5      S n[/        Xñ5      nU$ ! [          a    0 n N�f = f! , (       d  f       N‚= f)a?  A recursive function for resolving ``!ref``, ``!copy`` and ``!applyref`` tags.

Loads additional yaml files if ``!include:`` tags are used.
Also throws an error if ``!PLACEHOLDER`` tags are encountered.

Arguments
---------
key : str
    The fully-qualified path to current node.
current_node : node
    A node in the yaml tree loaded with ruamel.yaml.
tree : node
    The base node in the yaml tree loaded with ruamel.yaml.
file_path : str
    The location of the directory storing the main yaml file

Returns
-------
yaml.Node
    A yaml tree with all references resolved.
ra   Ú[Ú]r   rR   rP   Ú'z)' is a !PLACEHOLDER and must be replaced.)r3   ú!copyrx   )Ú	referenceÚreference_listÚ	full_treeÚ	copy_modez	!include:Nú
!applyref:)rh   ÚlistÚ	enumeraterm   ÚdictÚitemsrb   r   Úvaluerl   Úrecursive_resolver$   rg   rc   rd   Újoinrk   Úopenr   r!   r   rU   r"   Ú_applyref_function)r-   Úcurrent_nodeÚtreerq   ÚiÚsub_nodeÚsub_keyr+   Ú	tag_valuer|   Úfilenamer&   ÚfÚincluded_yamlr\   Úfunctions                   r.   rm   rm   T  sù  € ô0 �,¤×%Ñ%Ü$ \Ö2‰KˆAØ &›=‘a°°°Q°q°c¸¨mˆGÜ4°WÈÓXˆL‹Oò 3ô
 
�L¤$×	'Ñ	'Ø'×-Ñ-Ö/‰KˆAØ &›=‘a°°°Q°q°c¸¨mˆGÜ4°WÈÓXˆL‹Oñ 0ô
 ˆ|˜U×#Ò#Ø ×$Ñ$×*Ñ*×0¨bˆ	ð ˜Ó&Ü˜q  Ð%NÐOÓPÐPð Ð+Ó+Ø! WÑ,ˆIÜ,Ø&×,Ñ,Ø!ØØ#ñ	ˆLðB Ðð3 ×!Ñ! +×.Ñ.Ø ¤ [Ó!1Ð!2Ð3ˆHàÑ$ÜŸ7™7Ÿ<™<¨	Ó<�ðÜ  Ó.�	ô �h” 1Ü 2°1Ó @�÷  ô !Ÿ+™+×*Ñ*Ó,ˆKØ&×+Ñ+¨MÓ:ˆLð Ðð ×!Ñ! ,×/Ñ/Ø ¤ \Ó!2Ð!3Ð4ˆHÜ-¨hÓEˆLð Ðøô! ó Ø’	ðú÷  •ús   ÅG ÅG#ÇG ÇG Ç#
G1c                 ó–   • U R                  U5      nSUSS -   S-   n[        R                  " U[        R                  S9n[	        U5      $ )z-Parse scalar node as a list, convert to tupleru   é   éÿÿÿÿrv   r   )Úconstruct_scalarr   r"   r   Útuple)r(   rB   Útuple_stringÚlist_stringÚparsed_lists        r.   r   r   ¦  sG   € à×*Ñ*¨4Ó0€LØ˜ Q rÐ*Ñ*¨SÑ0€KÜ—)’)˜K´·±Ñ<€KÜ�ÓÐr;   c                 óz  • [        U[        R                  5      (       d)  [        U[        R                  R                  5      (       a  U R	                  USS9n/ U4$ [        U[        R
                  5      (       d)  [        U[        R                  R
                  5      (       a  U R                  USS9nU0 4$ / 0 4$ )NT)Údeep)rh   r   ÚMappingNoder!   Úconstruct_mappingÚSequenceNodeÚconstruct_sequence)r(   rB   r[   rZ   s       r.   Ú
_load_noderŸ   ®  sœ   € ä�tœT×-Ñ-×.Ñ.Ü�tœVŸ[™[×4Ñ4×5Ñ5à×)Ñ)¨$°TÐ)Ð:ˆØ�6ˆzÐä�tœT×.Ñ.×/Ñ/Ü�tœVŸ[™[×5Ñ5×6Ñ6à×(Ñ(¨°DÐ(Ð9ˆØ�RˆxˆØˆrˆ6€Mr;   c                 óä   • [        U 5      (       d  / 0 4$ [        U [        5      (       a)  SU ;   a  SU ;   a  [        U 5      S:X  a
  U S   U S   4$ / U 4$ [        U [        5      (       a  U 0 4$ [
        e)NÚ_argsÚ_kwargsé   )ri   rh   r€   rg   r~   rl   )rB   s    r.   Ú	_get_argsr¤   ¾  ss   € äˆt�9‰9Ø�2ˆvˆä�$œ×Ñð �d‹?˜y¨DÓ0´S¸³YÀ!³^Ø˜‘= $ y¡/Ð1Ð1à�t�8ˆOä	�Dœ$×	Ñ	Ø�RˆxˆäÐr;   c                 ó.  • [         R                  " U5      nUc  [        SU-  5      e[        R                  " U5      (       d  [        SU SU 35      e [        X5      u  pEU" U0 UD6$ ! [         a   nSU-  nU/UR                  Q7Ul        e S nAff = f)NzThere is no such class as %sr
   z should be a class, but is zInvalid argument to class %s)	ÚpydocÚlocateÚImportErrorÚinspectÚisclassrl   rŸ   rk   rZ   ©r(   Úcallable_stringrB   Ú	callable_rZ   r[   rs   Úerr_msgs           r.   r   r   Ö  s¦   € Ü—’˜_Ó-€IØÑÜÐ8¸?ÑJÓKÐKä�?Š?˜9×%Ñ%ÜØ�OÐ$Ð$?À	¸{ÐKó
ð 	
ðÜ! &Ó/‰ˆÙ˜$Ð) &Ñ)Ð)øÜó Ø0°?ÑBˆØÐ#˜AŸF™FÑ#ˆŒØûðúó   ÁA* Á*
BÁ4BÂBc                 óâ  • [         R                  " U5      nUc  [        SU-  5      e[        R                  " U5      (       dI  [        R
                  " U5      (       d.  [        X5      u  pEU(       d  U(       a  [        SU SU 35      eU$  [        X5      u  pEU(       d  U(       a  [        R                  " U/UQ70 UD6$ U$ ! [         a   nSU-  nU/UR                  Q7Ul        e S nAff = f)NzThere is no such entity as %sr   zK should be class or function, if you specify args or kwargs. Instead it is úInvalid argument to callable %s)r¦   r§   r¨   r©   rª   Ú	isroutinerŸ   rl   Ú	functoolsÚpartialrk   rZ   )r(   r¬   rB   r_   rZ   r[   rs   r®   s           r.   r   r   é  sé   € Ü�<Š<˜Ó(€DØ�|ÜÐ9¸OÑKÓLÐLä�OŠO˜D×!Ñ!¤W×%6Ò%6°t×%<Ñ%<Ü! &Ó/‰ˆÞ–6ÜØ˜Ð)ð *@Ø@D¸vðGóð ð ˆðÜ! &Ó/‰ˆÞ–6Ü×$Ò$ TÐ;¨DÒ;°FÑ;Ð;ØˆøÜó Ø3°oÑEˆØÐ#˜AŸF™FÑ#ˆŒØûðús   Â4C ÃC Ã
C.ÃC)Ã)C.c                 óô   • [         R                  " U5      nUc  [        SU-  5      e[        X5      u  pEU/ :w  d  U0 :w  a  [	        S5      e[
        R                  " U5      (       d  [	        SU SU 35      eU$ )NzThere is no such module as %szCannot pass args to moduler   z should be module, but is )r¦   r§   r¨   rŸ   rl   r©   Úismodule)r(   Úmodule_namerB   ÚmodulerZ   r[   s         r.   r   r     sz   € Ü�\Š\˜+Ó&€FØ�~ÜÐ9¸KÑGÓHÐHä˜fÓ+�L€DØˆrƒz�V˜r“\ÜÐ5Ó6Ð6Ü×Ò˜F×#Ñ#Ü˜8 K =Ð0JÈ6È(ÐSÓTÐTà€Mr;   c                 ó.  • [         R                  " U5      nUc  [        SU-  5      e[        R                  " U5      (       d  [        SU SU 35      e [        X5      u  pEU" U0 UD6$ ! [         a   nSU-  nU/UR                  Q7Ul        e S nAff = f)NúThere is no such callable as %sr   ú should be a callable, but is r±   )	r¦   r§   r¨   r©   r²   rl   rŸ   rk   rZ   r«   s           r.   r   r     s¨   € Ü—’˜_Ó-€IØÑÜÐ;¸oÑMÓNÐNä×Ò˜Y×'Ñ'ÜØ�oÐ&Ð&DÀYÀKÐPó
ð 	
ðÜ! &Ó/‰ˆÙ˜$Ð) &Ñ)Ð)øÜó Ø3°oÑEˆØÐ#˜AŸF™FÑ#ˆŒØûðúr¯   c                 ó2  • [         R                  " U 5      nUc  [        SU -  5      e[        R                  " U5      (       d  [        SU  SU 35      e [        U5      u  p4U" U0 UD6nU$ ! [         a   nSU -  nU/UR                  Q7Ul        e S nAff = f)Nrº   r}   r»   r±   )	r¦   r§   r¨   r©   r²   rl   r¤   rk   rZ   )r¬   rB   r­   rZ   r[   Úoutrs   r®   s           r.   r†   r†   #  s«   € Ü—’˜_Ó-€IØÑÜÐ;¸oÑMÓNÐNä×Ò˜Y×'Ñ'ÜØ˜Ð)Ð)GÈ	À{ÐSó
ð 	
ðÜ  “‰ˆÙ˜Ð( Ñ(ˆàˆ
øÜó Ø3°oÑEˆØÐ#˜AŸF™FÑ#ˆŒØûðús   ÁA, Á,
BÁ6BÂBc                 ó¶  • SnSU ;   a  U R                  SSS9u  pUnU R                  S5       H+  nUR                  S5      nXT;  a  [        SU -  5      eXE   nM-     U(       a  [        R                  " U5      $ Ub\  [
        R                  R                  R                  5       nXdU/-  nUR                  [
        R                  R                  SS	95        U$ U$ )
aÅ  Find the value referred to by a reference in dot-notation

Arguments
---------
ref : str
    The location of the requested value, e.g. 'constants.param'
full_tree : dict
    The dictionary to use for finding values
copy_mode : bool
    Whether to copy the node before dereferencing.

Returns
-------
node
    The node in the full_tree dictionary referenced by ``ref``.

Example
-------
>>> deref('constants[a][b]', {'constants': {'a': {'b': 'c'}}})
'c'
NÚ.r’   )Úmaxsplitru   rv   zThe reference "%s" is not validz!apply:getattr)Úsuffix)ÚsplitÚstriprl   ÚcopyÚdeepcopyr!   r   ÚcommentsÚCommentedSeqÚyaml_set_ctagÚTag)Úrefr{   r|   ÚattrÚbranchÚpartrB   s          r.   ÚderefrÎ   8  sÕ   € ð0 €DØ
ˆcƒzØ—I‘I˜c¨A�IÐ.‰	ˆð €FØ—	‘	˜#–ˆØ�z‰z˜#‹ˆØÓÜÐ>ÀÑDÓEÐEØ‘Šñ	 ö Ü�}Š}˜VÓ$Ð$ð ÑÜ�{‰{×#Ñ#×0Ñ0Ó2ˆØ˜�ÑˆØ×ÑÜ�K‰K�O‰OÐ#3ˆOÐ4ô	
ð ˆà€Mr;   c                 ó  • [         R                  " S5      n[        U [        5      (       a  UR	                  U 5      (       d  U $ [        U5      S:”  a  XSS ;   a  [        SU5      eUR                  U 5      (       a,  [        U R                  S5      X#5      nX/-  n[        XQX#5      $ UR                  U 5      nX Vs/ s H  owS   PM	     sn-  nX#4S jnUR                  X€5      n	[        X‘X#5      n [        U 5      $ s  snf )a)  Resolve a reference to a value, following chained references

Arguments
---------
reference : str
    a string containing '<x[y]>' in it where x[y] refers
    to a scalar node in the file.
reference_list : list
    list of prior references in the chain, in order
    to catch circular references.
full_tree : dict
    the dictionary in which to find all references and their values.
copy_mode : bool
    Whether to perform a deep copy of the referenced node, rather than
    a shallow reference to the same object.

Returns
-------
scalar
    The dereferenced value, with possible string interpolation and
    arithmetic parsing.

Example
-------
>>> tree = {'a': 3, 'b': 'x', 'c': '<a>', 'd': '<c>/<c>', 'e': '<b>/<b>'}
>>> recursive_resolve('<d>', [], tree)
1.0
>>> recursive_resolve('<e>', [], tree)
'x/x'
z<[^>]*>r’   NzCircular reference detected: ú<>r   c                 óL   • [        [        U S   R                  S5      XS95      $ )Nr   rÐ   )r{   r|   )ri   rÎ   rÃ   )Úxrˆ   r|   s      r.   Ú
replace_fnÚ%recursive_resolve.<locals>.replace_fn¡  s!   € Ü”5˜˜1™Ÿ™ DÓ)°TÑOÓPÐPr;   )r   r   rh   ri   Úsearchrg   rl   Ú	fullmatchrÎ   rÃ   rƒ   ÚfindallÚsubÚparse_arithmetic)
ry   rz   r{   r|   Úreference_finderr‚   ÚmatchesÚmatchrÓ   rØ   s
             r.   rƒ   rƒ   l  s  € ôB —z’z *Ó-Ðô �i¤×%Ñ%Ð-=×-DÑ-DÀY×-OÑ-OØÐä
ˆ>Ó˜QÓ 9¸q¸rÐ0BÓ#BÜÐ8¸.ÓIÐIð ×!Ñ! )×,Ñ,Ü�i—o‘o dÓ+¨YÓBˆØ˜+Ñ%ˆÜ  ¸	ÓMÐMð ×&Ñ& yÓ1€GØ¨WÓ5ªW E˜Q”x©WÑ5Ñ5€Nð %ô Qð ×
Ñ
˜zÓ
5€CÜ! #°yÓL€Iô ˜IÓ&Ð&ùò 6s   Â>C?c                 óŽ   •  [        [        R                  " U SS9R                  5      $ ! [        [
        [        4 a    U s $ f = f)aS  Parses simple arithmetic operations in references

Adapted from https://stackoverflow.com/a/9558001/1761970

Arguments
---------
reference_string : str
    A string with references and possible arithmetic operations.

Returns
-------
str
    Result of parsing and applying the arithmetic.

Example
-------
>>> parse_arithmetic('2 * 6')
12
Úeval)Úmode)Ú	_ast_evalÚastÚparseÚbodyrk   ÚSyntaxErrorÚKeyError)Úreference_strings    r.   rÙ   rÙ   «  s@   € ð( ÜœŸšÐ#3¸&ÑA×FÑFÓGÐGøÜ”{¤HÐ-ó  ØÒð ús   ‚'* ªAÁAc                 óþ  • [         R                  [        R                  [         R                  [        R
                  [         R                  [        R                  [         R                  [        R                  [         R                  [        R                  [         R                  [        R                  [         R                  [        R                  0n[         R"                  S:¼  a,  [%        U [         R&                  5      (       a  U R(                  $ O+[%        U [         R*                  5      (       a  U R,                  $ [%        U [         R.                  5      (       aE  U[1        U R                  5         " [3        U R4                  5      [3        U R6                  5      5      $ [%        U [         R8                  5      (       a1  U[1        U R                  5         " [3        U R:                  5      5      $ [=        U 5      e)N)é   é   )rá   ÚAddÚopÚaddÚSubrØ   ÚMultÚmulÚDivÚtruedivÚFloorDivÚfloordivÚPowÚpowÚModÚmodÚsysÚversion_inforh   ÚConstantr‚   ÚNumÚnÚBinOpÚtyperà   ÚleftÚrightÚUnaryOpÚoperandrk   )rB   Úopss     r.   rà   rà   Å  s)  € ä�‰”—‘Ü�‰”—‘Ü�‰”"—&‘&Ü�‰”—‘Ü�‰”b—k‘kÜ�‰”—‘Ü�‰”—‘ð€Cô ×Ñ˜6Ó!Ü�dœCŸL™L×)Ñ)Ø—:‘:Ðð *ô �dœCŸG™G×$Ñ$Ø—6‘6ˆMä�$œŸ	™	×"Ñ"Ø”4˜Ÿ™“=Ò!¤)¨D¯I©IÓ"6¼	À$Ç*Á*Ó8MÓNÐNÜ	�Dœ#Ÿ+™+×	&Ñ	&Ø”4˜Ÿ™“=Ò!¤)¨D¯L©LÓ"9Ó:Ð:ä˜‹oÐr;   c           
      ó2  • [        U [        R                  R                  5      (       d  [	        SU  35      e[        U[        R                  R                  5      (       d  [	        SU 35      eUR                  5        H�  u  p4[        U[        R                  R                  5      (       a#  X0;   a  [        U R                  U0 5      U5        MQ  U(       a4  X0;  a/  [        SU SU R                  5        Vs/ s H  oUPM     sn 35      eX@U'   M’     gs  snf )a¥  Similar function to `dict.update`, but for a nested `dict`.

From: https://stackoverflow.com/a/3233356

If you have to a nested mapping structure, for example:

    {"a": 1, "b": {"c": 2}}

Say you want to update the above structure with:

    {"b": {"d": 3}}

This function will produce:

    {"a": 1, "b": {"c": 2, "d": 3}}

Instead of:

    {"a": 1, "b": {"d": 3}}

Arguments
---------
d : dict
    mapping to be updated
u : dict
    mapping to update with
must_match : bool
    Whether to throw an error if the key in `u` does not exist in `d`.

Example
-------
>>> d = {'a': 1, 'b': {'c': 2}}
>>> recursive_update(d, {'b': {'d': 3}})
>>> d
{'a': 1, 'b': {'c': 2, 'd': 3}}
z'Expected to update a mapping, but got: z.Expected a mapping to use for update, but got z
Override 'z' not found in: N)
rh   ÚcollectionsÚabcÚMappingrk   r�   rj   Úgetrå   r#   )ÚdÚur`   r+   Úvr-   s         r.   rj   rj   â  sß   € ôN �aœŸ™×0Ñ0×1Ñ1ÜÐAÀ!ÀÐEÓFÐFÜ�aœŸ™×0Ñ0×1Ñ1ÜÐHÈÈÐLÓMÐMð —‘–	‰ˆÜ�aœŸ™×0Ñ0×1Ñ1°a³fÜ˜QŸU™U 1 b›\¨1Ö-Þ˜A›JÜ˜Z¨ sÐ*:È1Ï6É6Ì8Ó;TÊ8ÀCºCÉ8Ñ;TÐ:UÐVÓWÐWàˆa‹Dò ùò <Us   Ã7D)NFr   )(rI   r   rá   rø   r   rÄ   r¦   Úos.pathrc   r©   r³   r  Úruamel.yamlr!   Úoperatorrë   Úior   Úruamel.yaml.representerr   r   r/   r1   rN   r]   r   rm   r   rŸ   r¤   r   r   r   r   r†   rÎ   rƒ   rÙ   rà   rj   rL   r;   r.   Ú<module>r     s½   ðñó 
Û 
Û 
Û Û Û Û Û Û Û Û Û Ý Ý 4ð  °dÀ6Ç;Á;×CUÑCUôp÷fHñ H÷.>ñ >ò@ô4CòLOòdòò ò0ò&ò2òò&ô*1ôh<'ò~ ò4õ:4r;   