a
    g	gb                    @   s  d Z ddlZddlZddlmZmZ ddlmZ ddlm	Z	 ddl
mZmZmZmZmZmZmZmZmZmZmZmZmZmZ ejdk rddlmZmZ ndd	l
mZmZ dd
lmZ ddlm Z  ddl!m"Z"m#Z# ddl$m%Z%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z< ddl=m>Z> ddl?m@Z@mAZA G dd deBZCedZDee@eAf ZEee"ee% e&gee" f ZFeGZHeGZIeGZJeGZKe5eDeCf ZLeLeeH  ZMeNg dZOePe3eC dddZQe"ee% e&ee" dddZRG dd deZSe	G dd  d ZTeG d!d" d"ZUG d#d$ d$eSeUZVG d%d& d&eSZWG d'd( d(eSZXePeeeGeGf  d)d*d+ZYePeZd)d,d-Z[ePePePd.d/d0Z\G d1d2 d2eXeUZ]G d3d4 d4eXeUZ^G d5d6 d6Z_e@eeEgdf d7d8d9Z`ee eeGgeZf d:d;d<ZadS )=z7
String transformers that can split and merge strings.
    N)ABCabstractmethod)defaultdict)	dataclass)AnyCallableClassVar
CollectionDictIterableIteratorListOptionalSequenceSetTupleTypeVarUnion)      )FinalLiteral)r   r   )trait)contains_pragma_comment)Lineappend_leaves)FeatureMode)
CLOSING_BRACKETSOPENING_BRACKETSSTANDALONE_COMMENTis_empty_lparis_empty_paris_empty_rparis_part_of_annotationparent_typereplace_childsyms)ErrOkResult)assert_is_leaf_stringcount_chars_in_widthget_string_prefixhas_triple_quotesnormalize_string_quotes	str_width)token)LeafNodec                   @   s   e Zd ZdZdS )CannotTransformz-Base class for errors raised by Transformers.N)__name__
__module____qualname____doc__ r9   r9   N/var/www/html/llm_bihealth/app/venv/lib/python3.9/site-packages/black/trans.pyr4   =   s   r4   T)u   、u   。u   ，)err_msgreturnc                 C   s   t | }t|S )zW(T)ransform Err

    Convenience function used when working with the TResult type.
    )r4   r(   )r<   cant_transformr9   r9   r:   TErrO   s    r?   )linefeaturesmoder=   c           
      #   s4  j D ]}|jtjkr q$qtdttd tdfdd ttd td fdd	} }d
}t	j D ]\}}| }|rd|_
d
}d|  k otj d k n  o|jtjko||d ddoj |d  jdko||d dd}|rd|_
|j|dd |D ]}	|j|	dd qqp|V  dS )z>A transformer which normalizes spacing around power operators.z*No doublestar token was found in the line.   )indexstepr=   c                    s   |dkrt jt jh}nt jt jh}d|   kr<t jk rn nB j|  }|j|v rXdS |jt jt j	hvst|j
dkrxdS | |7 } q"dS )NrE   r   FforT)r1   RPARRSQBLPARLSQBlenleavestypeNAMEDOTvalue)rF   rG   Z
disallowedcurrent)r@   r9   r:   is_simple_lookupd   s    


z&hug_power_op.<locals>.is_simple_lookup)baseexponent)rF   kindr=   c                    sz   j |  }|jtjtjhv r4 | |dkr,dnddS |jtjtjtjhv rvj | d  jtjtjhv rv | d ddS dS )NrV   rD   rE   )rG   F)rN   rO   r1   rP   NUMBERPLUSMINUSTILDE)rF   rW   startrT   r@   r9   r:   is_simple_operand|   s    
z'hug_power_op.<locals>.is_simple_operandF r   rD   rU   )rW   lambdarV   TZpreformattedN)rN   rO   r1   
DOUBLESTARr4   intr   boolclone	enumerateprefixrM   rR   appendcomments_after)
r@   rA   rB   leafr^   new_lineZ
should_hugidxZnew_leafcomment_leafr9   r]   r:   hug_power_opX   s8    
"
rn   c                   @   s   e Zd ZU dZd Z eed< eeddddZe	e
eddd	Ze	e
ee eee
  d
ddZe
ee eee
 dddZdS )StringTransformera  
    An implementation of the Transformer protocol that relies on its
    subclasses overriding the template methods `do_match(...)` and
    `do_transform(...)`.

    This Transformer works exclusively on strings (for example, by merging
    or splitting them).

    The following sections can be found among the docstrings of each concrete
    StringTransformer subclass.

    Requirements:
        Which requirements must be met of the given Line for this
        StringTransformer to be applied?

    Transformations:
        If the given Line meets all of the above requirements, which string
        transformations can you expect to be applied to it by this
        StringTransformer?

    Collaborations:
        What contractual agreements does this StringTransformer have with other
        StringTransfomers? Such collaborations should be eliminated/minimized
        as much as possible.
    r5   N)line_lengthnormalize_stringsr=   c                 C   s   || _ || _d S N)rp   rq   )selfrp   rq   r9   r9   r:   __init__   s    zStringTransformer.__init__r@   r=   c                 C   s   dS )a  
        Returns:
            * Ok(string_indices) such that for each index, `line.leaves[index]`
            is our target string if a match was able to be made. For
            transformers that don't result in more lines (e.g. StringMerger,
            StringParenStripper), multiple matches and transforms are done at
            once to reduce the complexity.
                OR
            * Err(CannotTransform), if no match could be made.
        Nr9   rs   r@   r9   r9   r:   do_match   s    zStringTransformer.do_matchr@   string_indicesr=   c                 C   s   dS )a&  
        Yields:
            * Ok(new_line) where new_line is the new transformed line.
                OR
            * Err(CannotTransform) if the transformation failed for some reason. The
            `do_match(...)` template method should usually be used to reject
            the form of the given Line, but in some cases it is difficult to
            know whether or not a Line meets the StringTransformer's
            requirements until the transformation is already midway.

        Side Effects:
            This method should NOT mutate @line directly, but it MAY mutate the
            Line's underlying Node structure. (WARNING: If the underlying Node
            structure IS altered, then this method should NOT be allowed to
            yield an CannotTransform after that point.)
        Nr9   )rs   r@   ry   r9   r9   r:   do_transform   s    zStringTransformer.do_transform)r@   	_features_moder=   c                 c   s   t dd |jD std| |}t|trN| }td| jj d||	 }| 
||D ].}t|tr| }td||	 }|V  qbdS )z
        StringTransformer instances have a call signature that mirrors that of
        the Transformer type.

        Raises:
            CannotTransform(...) if the concrete StringTransformer class is unable
            to transform @line.
        c                 s   s   | ]}|j tjkV  qd S rr   )rO   r1   STRING.0rj   r9   r9   r:   	<genexpr>       z-StringTransformer.__call__.<locals>.<genexpr>z"There are no strings in this line.zThe string transformer z; does not recognize this line as one that it can transform.z>StringTransformer failed while attempting to transform string.N)anyrN   r4   rw   
isinstancer(   err	__class__r5   okrz   )rs   r@   r{   r|   match_resultr>   ry   Zline_resultr9   r9   r:   __call__   s*    


zStringTransformer.__call__)r5   r6   r7   r8   r   __annotations__rc   rd   rt   r   r   TMatchResultrw   r   r   TResultrz   r	   r   r   r   r9   r9   r9   r:   ro      s   


ro   c                   @   s"   e Zd ZU dZeed< eed< dS )CustomSplita  A custom (i.e. manual) string split.

    A single CustomSplit instance represents a single substring.

    Examples:
        Consider the following string:
        ```
        "Hi there friend."
        " This is a custom"
        f" string {split}."
        ```

        This string will correspond to the following three CustomSplit instances:
        ```
        CustomSplit(False, 16)
        CustomSplit(False, 17)
        CustomSplit(True, 16)
        ```
    
has_prefix	break_idxN)r5   r6   r7   r8   rd   r   rc   r9   r9   r9   r:   r     s   
r   c                   @   s   e Zd ZU dZeeef Zee	d< e
eZeeeeedf f  e	d< eeddddZeee d	d
ddZeee dddZeedddZd	S )CustomSplitMapMixinz
    This mixin class is used to map merged strings to a sequence of
    CustomSplits, which will then be used to re-split the strings iff none of
    the resultant substrings go over the configured max line length.
    _Key._CUSTOM_SPLIT_MAPzCustomSplitMapMixin._Keystringr=   c                 C   s   t | | fS )z
        Returns:
            A unique identifier that is used internally to map @string to a
            group of custom splits.
        )id)r   r9   r9   r:   _get_key9  s    zCustomSplitMapMixin._get_keyN)r   custom_splitsr=   c                 C   s   |  |}t|| j|< dS )zCustom Split Map Setter Method

        Side Effects:
            Adds a mapping from @string to the custom splits @custom_splits.
        N)r   tupler   )rs   r   r   keyr9   r9   r:   add_custom_splitsB  s    
z%CustomSplitMapMixin.add_custom_splitsc                 C   s$   |  |}| j| }| j|= t|S )aa  Custom Split Map Getter Method

        Returns:
            * A list of the custom splits that are mapped to @string, if any
            exist.
                OR
            * [], otherwise.

        Side Effects:
            Deletes the mapping between @string and its associated custom
            splits (which are returned to the caller).
        )r   r   list)rs   r   r   r   r9   r9   r:   pop_custom_splitsM  s    

z%CustomSplitMapMixin.pop_custom_splitsc                 C   s   |  |}|| jv S )zb
        Returns:
            True iff @string is associated with a set of custom splits.
        )r   r   )rs   r   r   r9   r9   r:   has_custom_splitsa  s    
z%CustomSplitMapMixin.has_custom_splits)r5   r6   r7   r8   r   StringIDstrr   r   r   r   r   r   r
   r   staticmethodr   r   r   r   r   rd   r   r9   r9   r9   r:   r   ,  s   
 	r   c                   @   s   e Zd ZdZeedddZeee e	e
e  dddZeeee e
e ddd	Zeee e
e dd
dZee eeegef eeef dddZeeee
d dddZdS )StringMergera  StringTransformer that merges strings together.

    Requirements:
        (A) The line contains adjacent strings such that ALL of the validation checks
        listed in StringMerger._validate_msg(...)'s docstring pass.
            OR
        (B) The line contains a string which uses line continuation backslashes.

    Transformations:
        Depending on which of the two requirements above where met, either:

        (A) The string group associated with the target string is merged.
            OR
        (B) All line-continuation backslashes are removed from the target string.

    Collaborations:
        StringMerger provides custom split information to StringSplitter.
    ru   c                 C   s   |j }t|}g }d}||r|| }|jtjkr||d r||d  jtjkrt|sd|| |d7 }||r|| jtjkr|d7 }qlq|jtjkrd|jv r|| |d7 }||r|| jtjkr|d7 }qq|d7 }q|rt|S t	dS d S )Nr   rD      \
z+This line has no strings that need merging.)
rN   is_valid_index_factoryrO   r1   r}   r$   rh   rR   r)   r?   )rs   r@   LLis_valid_indexry   rl   rj   r9   r9   r:   rw   ~  s4    




zStringMerger.do_matchrx   c           	      c   s   |}|  ||}t|tr"| }| ||}t|tr@| }t|trt|tr| }| }td}||_||_t|V  n
t|V  d S )Nz6StringMerger failed to merge any strings in this line.)	)_remove_backslash_line_continuation_charsr   r)   r   _merge_string_groupr(   r   r4   	__cause__)	rs   r@   ry   rk   Zrblc_resultZ
msg_resultZmsg_cant_transformZrblc_cant_transformr>   r9   r9   r:   rz     s&    

zStringMerger.do_transformc                 C   s   | j }g }|D ]6}|| }|jtjkrd|jv rt|js|| q|sRtdS |  }| j	
 |_	t|| | |D ]}|j | }|jdd|_qvt|S )a$  
        Merge strings that were split across multiple lines using
        line-continuation backslashes.

        Returns:
            Ok(new_line), if @line contains backslash line-continuation
            characters.
                OR
            Err(CannotTransform), otherwise.
        r   zKFound no string leaves that contain backslash line continuation characters.r_   )rN   rO   r1   r}   rR   r.   rh   r?   re   commentscopyr   replacer)   )r@   ry   r   Zindices_to_transform
string_idxstring_leafrk   Znew_string_leafr9   r9   r:   r     s,    

z6StringMerger._remove_backslash_line_continuation_charsc                 C   s   |j }t|}i }|D ].}| ||}t|tr2q| |||||< q|sRtdS | }d}	d}
t|D ]x\}}||v r|}	|| \}
}|	| |	|  kr|	|
 k rn n$|
|| D ]}|j	|dd qqjt|||g qjt|S )am  
        Merges string groups (i.e. set of adjacent strings).

        Each index from `string_indices` designates one string group's first
        leaf in `line.leaves`.

        Returns:
            Ok(new_line), if ALL of the validation checks found in
            _validate_msg(...) pass.
                OR
            Err(CannotTransform), otherwise.
        zNo string group is mergedrE   Tra   )rN   r   _validate_msgr   r(   _merge_one_string_groupr?   re   rf   rh   ri   r   r)   )rs   r@   ry   r   r   Zmerged_string_idx_dictr   vresultrk   Zprevious_merged_string_idxZprevious_merged_num_of_stringsirj   r   rm   r9   r9   r:   r     s<    



z StringMerger._merge_string_group)r   r   r   r=   c                    sd  || j }d}|| jd  tttd fdd}g }g }|}	d}
|
sz||	rz||	 jtjkrzt||	 j }
|	d7 }	qBd}d}d}|}	||	r*||	 jtjkr*|d7 }||	 j}t| }d	|
v rd	|vrt	d
d|}|||}t
|}|| |
  | | |   }|||
}|	d7 }	q|	}ttj|}| jrNt|j|_|jt|
d d }|D ]`}||}|dksJ d||t| d }||rt|
nd d }|t|| qhttj|j|d}|durN|| t|jk rD||  }t|d |D ]}||   q|durN||| n
t|| | |j| ||fS )aA  
        Merges one string group where the first string in the group is
        `LL[string_idx]`.

        Returns:
            A tuple of `(num_of_strings, leaf)` where `num_of_strings` is the
            number of strings merged and `leaf` is the newly merged string
            to be replaced in the new line.
        z#@@@@@ BLACK BREAKPOINT MARKER @@@@@rE   )r   string_prefixr=   c                    sT   t |  d|v rt|  } d}| t|d d }td| d   d  |}|S )a  Strip @string (i.e. make it a "naked" string)

            Pre-conditions:
                * assert_is_leaf_string(@string)

            Returns:
                A string that is identical to @string except that
                @string_prefix has been stripped, the surrounding QUOTE
                characters have been removed, and any remaining QUOTE
                characters have been escaped.
            fz(?:(?<!\\)(?:\\\\)*)rD   rE   ()z\1\\)r+   _toggle_fexpr_quotesrM   resub)r   r   ZRE_EVEN_BACKSLASHESZnaked_stringQUOTEr9   r:   
make_naked:  s    
z8StringMerger._merge_one_string_group.<locals>.make_nakedr_   rD   r   r   z(\{|\})z\1\1z=Logic error while filling the custom string breakpoint cache.N)parentrR   r   rO   r1   r}   r-   lowerr   r   rd   rh   r2   rq   r/   rM   findr   r   childrenremoverangeinsert_childr&   r   )rs   r   r   r   Z	atom_nodeZ
BREAK_MARKr   r   Zprefix_trackerZnext_str_idxrg   SZNSnum_of_stringsZSSZnext_prefixZNSSr   Znon_string_idxZS_leafZtemp_stringZmark_idxZbreakpoint_idxr   Zfirst_child_idxrl   r9   r   r:   r   "  sr    










z$StringMerger._merge_one_string_groupNr@   r   r=   c                 C   s  dD ]d}|}d}t | j}||r| j| jtjtfv r| j| jtkrNd}n|r^td  S ||7 }qqd}t }d}| j|d D ]}	|	jtjkr|	jtjkrt	|	| j
v r|d7 } q>t|	jrtd  S |d7 }t|	j }
d	|
v rtd
  S ||
 t	|	| j
v r|d7 }t| j
t	|	 rtd  S q|dk rXtd| dS |dkrrtd| dS t|dkr|ddhkrtd| dS tdS )a  Validate (M)erge (S)tring (G)roup

        Transform-time string validation logic for _merge_string_group(...).

        Returns:
            * Ok(None), if ALL validation checks (listed below) pass.
                OR
            * Err(CannotTransform), if any of the following are true:
                - The target string group does not contain ANY stand-alone comments.
                - The target string is not in a string group (i.e. it has no
                  adjacent strings).
                - The string group has more than one inline comment.
                - The string group has an inline comment that appears to be a pragma.
                - The set of all string prefixes in the string group is of
                  length greater than one and is not equal to {"", "f"}.
                - The string group consists of raw strings.
                - The string group is stringified type annotations. We don't want to
                  process stringified type annotations since pyright doesn't support
                  them spanning multiple string values. (NOTE: mypy, pytype, pyre do
                  support them, so we can change if pyright also gains support in the
                  future. See https://github.com/microsoft/pyright/issues/4359.)
        rC   FTzMStringMerger does NOT merge string groups which contain stand-alone comments.r   NrD   z.StringMerger does NOT merge multiline strings.rz(StringMerger does NOT merge raw strings.z0Cannot merge strings which have pragma comments.r   z,Not enough strings to merge (num_of_strings=z).z!Too many inline string comments (r_   r   zToo many different prefixes ()r   rN   rO   r1   r}   r    r?   setCOMMAr   r   r.   rR   r-   r   addr   rM   r)   )r@   r   incr   Zfound_sa_commentr   Znum_of_inline_string_commentsZset_of_prefixesr   rj   rg   r9   r9   r:   r     sZ    






zStringMerger._validate_msg)r5   r6   r7   r8   r   r   rw   r   rc   r   r   rz   r   r   r   r2   r   rd   r   r   r   r9   r9   r9   r:   r   j  s$   &
*8
 r   c                   @   sT   e Zd ZdZeedddZeee e	e
e  dddZeee edd	d
ZdS )StringParenStrippera)  StringTransformer that strips surrounding parentheses from strings.

    Requirements:
        The line contains a string which is surrounded by parentheses and:
            - The target string is NOT the only argument to a function call.
            - The target string is NOT a "pointless" string.
            - If the target string contains a PERCENT, the brackets are not
              preceded or followed by an operator with higher precedence than
              PERCENT.

    Transformations:
        The parentheses mentioned in the 'Requirements' section are stripped.

    Collaborations:
        StringParenStripper has its own inherent usefulness, but it is also
        relied on to clean up the parentheses created by StringParenWrapper (in
        the event that they are no longer needed).
    ru   c                 C   s*  |j }t|}g }d}|d7 }|t|kr.q|| }|jtjkrDq|jrd|jjrd|jjjtjkrdq||d r||d  jtj	kst
||d  rq||d r||d  jtjks||d  jtv rq|}t }|||}	||d r|||d  }
tjdd ||d |	 D v r||
jtjtjtjtjtjtjtjtjtjtj	h
v s|
jr||
jjtjkr||
jtjtjhv r|q||	r||	 jtjkrt||	 s||	d r||	d  jtjtjtj	tjhv rq|| |}|t|d k r||d  jtjkr|d7 }qq|r"t|S t dS )NrE   rD   r   c                 S   s   h | ]
}|j qS r9   rO   r~   r9   r9   r:   	<setcomp>R  r   z/StringParenStripper.do_match.<locals>.<setcomp>z+This line has no strings wrapped in parens.)!rN   r   rM   rO   r1   r}   r   r'   Zsimple_stmtrK   r!   rP   r   StringParserparsePERCENTSTARATSLASHDOUBLESLASHr[   rb   AWAITrL   ZfactorrY   rZ   rI   r#   rQ   rh   r)   r?   )rs   r@   r   r   ry   rl   rj   r   string_parserZnext_idxZbefore_lparr9   r9   r:   rw     s    
"

$zStringParenStripper.do_matchrx   c           
      c   s   |j }g }|D ]X}t }|||}d}||d  || fD ]}	||	r<d} qTq<|r|||f q|rt| ||V  nttdV  d S )NTrD   Fz1All string groups have comments attached to them.)	rN   r   r   ri   extendr)   _transform_to_new_liner(   r4   )
rs   r@   ry   r   string_and_rpar_indicesr   r   Zrpar_idxZshould_transformrj   r9   r9   r:   rz     s"    
z StringParenStripper.do_transform)r@   r   r=   c           
      C   s   |j }| }|j |_d}t|D ]}|| }|jtjkrF|d n|}t||||d |  |jtjkrt	tj|| j
}	||   t|| |	 ||	 n||   |}q&t||||d d   |S )NrE   rD   )rN   re   r   r   sortedrO   r1   r}   r   r2   rR   r   r&   rh   )
rs   r@   r   r   rk   Zprevious_idxrl   rj   Zlpar_or_rpar_idxr   r9   r9   r:   r     s"    z*StringParenStripper._transform_to_new_lineN)r5   r6   r7   r8   r   r   rw   r   rc   r   r   rz   r   r9   r9   r9   r:   r     s   i
r   c                	   @   s   e Zd ZU dZejejejejej	ej
ejejejg	Zeed< eeedddZeedddZeeed d	d
dZeeed	ddZeee ee dddZdS )BaseStringSplittera  
    Abstract class for StringTransformers which transform a Line's strings by splitting
    them or placing them on their own lines where necessary to avoid going over
    the configured line length.

    Requirements:
        * The target string value is responsible for the line going over the
        line length limit. It follows that after all of black's other line
        split methods have been exhausted, this line (or one of the resulting
        lines after all line splits are performed) would still be over the
        line_length limit unless we split this string.
            AND
        * The target string is NOT a "pointless" string (i.e. a string that has
        no parent or siblings).
            AND
        * The target string is not followed by an inline comment that appears
        to be a pragma.
            AND
        * The target string is not a multiline (i.e. triple-quote) string.
    STRING_OPERATORSru   c                 C   s   dS )a  
        BaseStringSplitter asks its clients to override this method instead of
        `StringTransformer.do_match(...)`.

        Follows the same protocol as `StringTransformer.do_match(...)`.

        Refer to `help(StringTransformer.do_match)` for more information.
        Nr9   rv   r9   r9   r:   do_splitter_match  s    z$BaseStringSplitter.do_splitter_matchc                 C   sl   |  |}t|tr|S | }t|dksFJ | jj dt| |d }| ||}t|trh|S |S )NrD   - should only find one match at a time, found r   )r   r   r(   r   rM   r   r5   	_validate)rs   r@   r   ry   r   r   r9   r9   r:   rw     s    



zBaseStringSplitter.do_matchNr   c                 C   s   |j }|| }| ||}t|j|kr0tdS |jrTdd |jjD tjtj	gkrftd|j dS t
|j | |jv rt|jt
|j |  rtdS t|jrtdS tdS )	aw  
        Checks that @line meets all of the requirements listed in this classes'
        docstring. Refer to `help(BaseStringSplitter)` for a detailed
        description of those requirements.

        Returns:
            * Ok(None), if ALL of the requirements are met.
                OR
            * Err(CannotTransform), if ANY of the requirements are NOT met.
        zBThe string itself is not what is causing this line to be too long.c                 S   s   g | ]
}|j qS r9   r   )r   Lr9   r9   r:   
<listcomp>  r   z0BaseStringSplitter._validate.<locals>.<listcomp>zThis string (z/) appears to be pointless (i.e. has no parent).ziLine appears to end with an inline pragma comment. Splitting the line could modify the pragma's behavior.z"We cannot split multiline strings.N)rN   _get_max_string_lengthrM   rR   r?   r   r   r1   r}   NEWLINEr   r   r   r.   r)   )rs   r@   r   r   r   max_string_lengthr9   r9   r:   r     s.    
zBaseStringSplitter._validatec                 C   s*  |j }t|}|jd }||d r|d }||d  jtjkrb||d  jdkrb|dkrb|d8 }|| }|j| jv r|tt	|d 7 }|jtj
kr|d7 }|jtjtjtjtjfv r|d7 }t|d|d  D ]"}|tt	|7 }|jtv r qq||d r||d  }	|	jtjkrJ|	jdkrJt||d krJ||d  }	|	jtj
kr`|d7 }||d r||d  }
|	jtjkr|
jtjkr|d7 }||d r||d  jtjkr|d7 }|t|
j7 }d}||| D ]&}|s d}|d7 }|t|j7 }qtt	|| j| }|S )	az  
        Calculates the max string length used when attempting to determine
        whether or not the target string is responsible for causing the line to
        go over the line length limit.

        WARNING: This method is tightly coupled to both StringSplitter and
        (especially) StringParenWrapper. There is probably a better way to
        accomplish what is being done here.

        Returns:
            max_string_length: such that `line.leaves[string_idx].value >
            max_string_length` implies that the target string IS responsible
            for causing this line to exceed the line length limit.
           rD   r_   r   r   NFT)rN   r   depthrO   r1   rK   rR   r   rM   r   r   COLONEQUAL	PLUSEQUALrP   reversedr   rI   rQ   ri   r,   rp   )rs   r@   r   r   r   offsetZp_idxPrj   NZNNZhas_commentsrm   r   r9   r9   r:   r   )  s^    

,
z)BaseStringSplitter._get_max_string_lengthr   r=   c                 C   s   | d j tjkrdS | d j}| d j}|sd|sdt| d tjkrd| d j}|dusXJ |j}|j}|rt|j tj	kr|r|j tj	krdS dS )ac  
        Returns:
            string_idx such that @LL[string_idx] is equal to our target (i.e.
            matched) string, if this line matches the "prefer paren wrap" statement
            requirements listed in the 'Requirements' section of the StringParenWrapper
            class's docstring.
                OR
            None, otherwise.
        r   N)
rO   r1   r}   prev_siblingnext_siblingr%   r'   Zatomr   r   )r   r   r   r   r9   r9   r:   _prefer_paren_wrap_match  s     



z+BaseStringSplitter._prefer_paren_wrap_match)r5   r6   r7   r8   r1   EQEQUALGREATERGREATEREQUALLESS	LESSEQUALNOTEQUALr   rY   r   r   r   r   r   r   r   r   rw   rc   r   r   r   r   r   r2   r   r   r9   r9   r9   r:   r     s$   

+mr   )sr=   c                 c   sF  g }d}|t | k rB| | dkrd|sP|d t | k rP| |d  dkrP|d7 }q|| |d7 }q| | dkr|s~|d7 }q| }|s||d fV  |d7 }q|r8d}| ||d  dv r| ||d  }n| | d	v r| | }|r8|t |7 }|t | k r*| ||t |  |kr*|d7 }q|t |7 }q|d7 }qdS )
z
    Yields spans corresponding to expressions in a given f-string.
    Spans are half-open ranges (left inclusive, right exclusive).
    Assumes the input string is a valid f-string, but will not crash if the input
    string is invalid.
    r   {rD   r   }Nr   )z'''z""")'")rM   rh   pop)r   stackr   jdelimr9   r9   r:   iter_fexpr_spans  s@    $
(
r  c                 C   s   t t| S rr   )r   r  )r   r9   r9   r:   fstring_contains_expr  s    r  )fstring	old_quoter=   c                 C   sv   |dkrdnd}g }d}t | D ]8\}}|| ||  || || || |}q || |d  d|S )a;  
    Toggles quotes used in f-string expressions that are `old_quote`.

    f-string expressions can't contain backslashes, so we need to toggle the
    quotes if the f-string itself will end up using the same quote. We can
    simply toggle without escaping because, quotes can't be reused in f-string
    expressions. They will fail to parse.

    NOTE: If PEP 701 is accepted, above statement will no longer be true.
    Though if quotes can be reused, we can simply reuse them without updates or
    escaping, once Black figures out how to parse the new grammar.
    r   r   r   Nr_   )r  rh   r   join)r  r  Z	new_quotepartsZprevious_indexr\   endr9   r9   r:   r     s    r   c                   @   s   e Zd ZU dZdZeed< eedddZ	ee
e eee  ddd	Zeeeeef  d
ddZeeeeef  d
ddZeee d
ddZeeee dddZeddddZeeedddZee e
e dddZdS )StringSplittera^  
    StringTransformer that splits "atom" strings (i.e. strings which exist on
    lines by themselves).

    Requirements:
        * The line consists ONLY of a single string (possibly prefixed by a
        string operator [e.g. '+' or '==']), MAYBE a string trailer, and MAYBE
        a trailing comma.
            AND
        * All of the requirements listed in BaseStringSplitter's docstring.

    Transformations:
        The string mentioned in the 'Requirements' section is split into as
        many substrings as necessary to adhere to the configured line length.

        In the final set of substrings, no substring should be smaller than
        MIN_SUBSTR_SIZE characters.

        The string will ONLY be split on spaces (i.e. each new substring should
        start with a space). Note that the string will NOT be split on a space
        which is escaped with a backslash.

        If the string is an f-string, it will NOT be split in the middle of an
        f-expression (e.g. in f"FooBar: {foo() if x else bar()}", {foo() if x
        else bar()} is an f-expression).

        If the string that is being split has an associated set of custom split
        records and those custom splits will NOT result in any line going over
        the configured line length, those custom splits are used. Otherwise the
        string is split as late as possible (from left-to-right) while still
        adhering to the transformation rules listed above.

    Collaborations:
        StringSplitter relies on StringMerger to construct the appropriate
        CustomSplit objects and add them to the custom split map.
       MIN_SUBSTR_SIZEru   c                 C   s  |j }| |d urtdS t|}d}||r||d r|| j||d  jgtjtjgkrt|| t||d   dkr|d7 }n@||r|| j| jv s|| jtjkrt|| dkr|d7 }||rt	|| r|d7 }||r|| jtj
kr
tdS |}t }|||}||r@t|| r@|d7 }||rd|| jtjkrd|d7 }||rvtdS t|gS )	Nz)Line needs to be wrapped in parens first.r   rD   znot inr   inz"Line does not start with a string.z%This line does not end with a string.)rN   r   r?   r   rO   r1   rP   r   r   r!   r}   r   r   r#   r   r)   )rs   r@   r   r   rl   r   r   r9   r9   r:   r   )  sH    
"

z StringSplitter.do_splitter_matchrx   c                 #   s  j  t|dks,J jj dt| |d } | jd }t }t | }t | j }d|v o|t	 | j}d
 		rtdd 	D d nd
td d	 	fd
d}	||d o |d  jtjktd
fddjd8 jd 8 dk rBtd | j dj V  d S  | jtontfddD  | jtdfdd}
g }|
 rΈrd}|j}nLt
 }|}|d u r rΈ | jg }ddqq|}d | | }rZ|jsZ||| ksB|||krZ|d7 }d | | }|rl||}ttj|}|| |   }|	| |!| |!t"| || |d   dq|E d H  |r|ttj}|| |   }|	| ||d r} |d d  D ]&}|t#|7 }|jtj$kr: qbq:t%| ks |d  jtjkr|!| t&| |d d   t"|V  n>|!| t"|V    }t&| |d d   t"|V  n |!| j'( |_'t"|V  d S )NrD   r   r   rE   r   Tc                 s   s   | ]}t t|V  qd S rr   )rM   r   )r   prefix_leafr9   r9   r:   r   |  r   z.StringSplitter.do_transform.<locals>.<genexpr>)rk   r=   c                    s:   rng }t |D ] \}}t | | | | qdS )a\  
            Side Effects:
                If @line starts with a string operator and this is the first
                line we are constructing, this function appends the string
                operator to @new_line and replaces the old string operator leaf
                in the node structure. Otherwise this function does nothing.
            N)rf   r&   rh   )rk   Zmaybe_prefix_leavesr   r  )r   first_string_linestring_op_leavesr9   r:   maybe_append_string_operators  s    zBStringSplitter.do_transform.<locals>.maybe_append_string_operatorsr=   c                     s0   j } | jd 8 } |  rdnd8 } | 8 } | S )a;  
            Returns:
                The max allowed width of the string value used for the last
                line we will construct.  Note that this value means the width
                rather than the number of characters (e.g., many East Asian
                characters expand to two columns).
            r   rD   r   )rp   r   )result)ends_with_commar@   rs   string_op_leaves_lengthr9   r:   max_last_string_column  s
    z;StringSplitter.do_transform.<locals>.max_last_string_columnr   zUnable to split z at such high of a line depth: c                 3   s   | ]}|j  kV  qd S rr   )r   )r   csplit)max_break_widthr9   r:   r     r   c                      s"   rt  dkS t kS dS )z
            Returns:
                True iff `rest_value` (the remaining string value from the last
                split), should be split again.
            rD   N)rM   r0   r9   )r   r  
rest_valueuse_custom_breakpointsr9   r:   more_splits_should_be_made  s    z?StringSplitter.do_transform.<locals>.more_splits_should_be_madeF))rN   rM   r   r5   rR   r   insert_str_child_factoryr-   r   r  _get_string_operator_leavessumr   rO   r1   r   rc   rp   r   r?   r   rd   allr   r   r,   _get_break_idxr   _normalize_f_stringr2   r}   _maybe_normalize_string_quotesre   rh   r)   r   rK   r0   r   r   r   )rs   r@   ry   r   r   r   insert_str_childrg   Zdrop_pointless_f_prefixr  r  Zstring_line_resultsr  r   Zmax_bidxZmaybe_break_idxZ
next_valueZ	next_leaf	next_lineZ	rest_leaf	last_lineZ
temp_valuerj   Znon_string_liner9   )r   r   r  r  r@   r  r  r  rs   r  r  r  r:   rz   _  s    

















zStringSplitter.do_transformr   c                 c   s   d}t t|}|D ]p\}}|dkr,| }q|r8|dkr>d}qd}|d }|D ]\}}|dkrN|} qzqNt| jj d||fV  qdS )z
        Yields:
            All ranges of @string which, if @string were to be split there,
            would result in the splitting of an \N{...} expression (which is NOT
            allowed).
        F\r   rD   r    LOGIC ERROR!N)iterrf   RuntimeErrorr   r5   )rs   r   Z previous_was_unescaped_backslashitrl   cbeginr  r9   r9   r:   _iter_nameescape_slicesG  s"    	z&StringSplitter._iter_nameescape_slicesc                 c   s&   dt | vrdS t|E dH  dS )z
        Yields:
            All ranges of @string which, if @string were to be split there,
            would result in the splitting of an f-expression (which is NOT
            allowed).
        r   N)r-   r   r  )rs   r   r9   r9   r:   _iter_fexpr_slicesf  s    z!StringSplitter._iter_fexpr_slicesc                 C   sJ   t  }| || |g}|D ]&}|D ]\}}|t||d  q&q|S NrD   )r   r,  r+  updater   )rs   r   Zillegal_indices	iteratorsr(  r*  r  r9   r9   r:   _get_illegal_split_indicesq  s    z)StringSplitter._get_illegal_split_indices)r   max_break_idxr=   c                    s   t |sJ t  ttd fddttdfdd}|}|d rv||sv|d8 }qX||s|d }|d r||s|d7 }q|r||sdS |S )a  
        This method contains the algorithm that StringSplitter uses to
        determine which character to split each string at.

        Args:
            @string: The substring that we are attempting to split.
            @max_break_idx: The ideal break index. We will return this value if it
            meets all the necessary conditions. In the likely event that it
            doesn't we will try to find the closest index BELOW @max_break_idx
            that does. If that fails, we will expand our search by also
            considering all valid indices ABOVE @max_break_idx.

        Pre-Conditions:
            * assert_is_leaf_string(@string)
            * 0 <= @max_break_idx < len(@string)

        Returns:
            break_idx, if an index is able to be found that meets all of the
            conditions listed in the 'Transformations' section of this classes'
            docstring.
                OR
            None, otherwise.
        )r   r=   c                    s   |  v S )z
            Returns:
                True iff returning @i would result in the splitting of an
                unsplittable expression (which is NOT allowed).
            r9   )r   )_illegal_split_indicesr9   r:   breaks_unsplittable_expression  s    zEStringSplitter._get_break_idx.<locals>.breaks_unsplittable_expressionc                    s   |  dk}| d o&| d  t v }d}| d }|rX| dkrX| }|d8 }q4t| d jkotd|  jk}|s|o|o|o |  S )z
            Returns:
                True iff ALL of the conditions listed in the 'Transformations'
                section of this classes' docstring would be be met by returning @i.
             rD   Tr$  N)SPLIT_SAFE_CHARSrM   r
  )r   Zis_spaceZis_split_safeZis_not_escapedr   Zis_big_enough)r3  r   rs   r   r9   r:   passes_all_checks  s"    
z8StringSplitter._get_break_idx.<locals>.passes_all_checksrD   N)r   r+   r0  Indexrd   )rs   r   r1  r6  r   r9   )r2  r3  r   rs   r   r:   r  |  s     


zStringSplitter._get_break_idxNrj   r=   c                 C   s   | j rt|j|_d S rr   )rq   r/   rR   )rs   rj   r9   r9   r:   r     s    z-StringSplitter._maybe_normalize_string_quotes)r   rg   r=   c                 C   sh   t | d|v r`t|s`|dd}|t|d }tdd|}tdd|}|}| | S |S dS )a  
        Pre-Conditions:
            * assert_is_leaf_string(@string)

        Returns:
            * If @string is an f-string that contains no f-expressions, we
            return a string identical to @string except that the 'f' prefix
            has been stripped and all double braces (i.e. '{{' or '}}') have
            been normalized (i.e. turned into '{' or '}').
                OR
            * Otherwise, we return @string.
        r   r_   Nz\{\{r   z\}\}r   )r+   r  r   rM   r   r   )rs   r   rg   
new_prefixtempZ
new_stringr9   r9   r:   r    s    z"StringSplitter._normalize_f_string)rN   r=   c                 C   s\   t |}g }d}|| j| jtjg v rXt|| jt||  }|| |d7 }q|S )Nr   rD   )	r   rO   r   r1   rP   r2   r   striprh   )rs   rN   r   r  r   r  r9   r9   r:   r    s    

z*StringSplitter._get_string_operator_leaves)r5   r6   r7   r8   r
  r   r   r   r   r   r   rc   r   r   rz   r   r   r7  r+  r,  r   r0  r   r  r2   r   r  r   r  r9   r9   r9   r:   r    s   
%7
 iUr  c                   @   s   e Zd ZdZeedddZeee	 e
e dddZeee	 e
e ddd	Zeee	 e
e dd
dZeee	 e
e dddZeee	 e
e dddZeee eee  dddZdS )StringParenWrappera	  
    StringTransformer that wraps strings in parens and then splits at the LPAR.

    Requirements:
        All of the requirements listed in BaseStringSplitter's docstring in
        addition to the requirements listed below:

        * The line is a return/yield statement, which returns/yields a string.
            OR
        * The line is part of a ternary expression (e.g. `x = y if cond else
        z`) such that the line starts with `else <string>`, where <string> is
        some string.
            OR
        * The line is an assert statement, which ends with a string.
            OR
        * The line is an assignment statement (e.g. `x = <string>` or `x +=
        <string>`) such that the variable is being assigned the value of some
        string.
            OR
        * The line is a dictionary key assignment where some valid key is being
        assigned the value of some string.
            OR
        * The line is an lambda expression and the value is a string.
            OR
        * The line starts with an "atom" string that prefers to be wrapped in
        parens. It's preferred to be wrapped when the string is surrounded by
        commas (or is the first/last child).

    Transformations:
        The chosen string is wrapped in parentheses and then split at the LPAR.

        We then have one line which ends with an LPAR and another line that
        starts with the chosen string. The latter line is then split again at
        the RPAR. This results in the RPAR (and possibly a trailing comma)
        being placed on its own line.

        NOTE: If any leaves exist to the right of the chosen string (except
        for a trailing comma, which would be placed after the RPAR), those
        leaves are placed inside the parentheses.  In effect, the chosen
        string is not necessarily being "wrapped" by parentheses. We can,
        however, count on the LPAR being placed directly before the chosen
        string.

        In other words, StringParenWrapper creates "atom" strings. These
        can then be split again by StringSplitter, if necessary.

    Collaborations:
        In the event that a string line split by StringParenWrapper is
        changed such that it no longer needs to be given its own line,
        StringParenWrapper relies on StringParenStripper to clean up the
        parentheses it created.

        For "atom" strings that prefers to be wrapped in parens, it requires
        StringSplitter to hold the split until the string is wrapped in parens.
    ru   c                 C   s   |j }|j d jtv rtdS | |pX| |pX| |pX| |pX| |pX| 	|}|d ur|j | j
}tdd |D s| j|jd d  }t||kr| |stdS t|gS tdS )	NrE   zACannot wrap parens around a line that ends in an opening bracket.c                 s   s   | ]}|d kp|t v V  qdS )r4  N)r5  )r   charr9   r9   r:   r   I  s   z7StringParenWrapper.do_splitter_match.<locals>.<genexpr>rD   r   zWe do not wrap long strings in parentheses when the resultant line would still be over the specified line length and can't be split further by StringSplitter.z2This line does not contain any non-atomic strings.)rN   rO   r   r?   _return_match_else_match_assert_match_assign_match_dict_or_lambda_matchr   rR   r   rp   r   r0   r   r)   )rs   r@   r   r   string_valueZmax_string_widthr9   r9   r:   r   5  s:    
	

z$StringParenWrapper.do_splitter_matchr   c                 C   sj   t | d tjtjfv rf| d jdv rft| }|drFt| d rFdnd}||rf| | jtj	krf|S dS )aK  
        Returns:
            string_idx such that @LL[string_idx] is equal to our target (i.e.
            matched) string, if this line matches the return/yield statement
            requirements listed in the 'Requirements' section of this classes'
            docstring.
                OR
            None, otherwise.
        r   )r=   yieldrD   r   N)
r%   r'   Zreturn_stmtZ
yield_exprrR   r   r"   rO   r1   r}   r   r   rl   r9   r9   r:   r>  [  s    z StringParenWrapper._return_matchc                 C   st   t | d tjkrp| d jtjkrp| d jdkrpt| }|drPt| d rPdnd}||rp| | jtj	krp|S dS )aG  
        Returns:
            string_idx such that @LL[string_idx] is equal to our target (i.e.
            matched) string, if this line matches the ternary expression
            requirements listed in the 'Requirements' section of this classes'
            docstring.
                OR
            None, otherwise.
        r   elserD   r   N)
r%   r'   testrO   r1   rP   rR   r   r"   r}   rE  r9   r9   r:   r?  t  s    zStringParenWrapper._else_matchc                 C   s   t | d tjkr| d jdkrt| }t| D ]r\}}|jtjkr0t	| |d  r\|d n|d }||r0| | jtj
kr0|}t }|| |}||s0|  S q0dS )aE  
        Returns:
            string_idx such that @LL[string_idx] is equal to our target (i.e.
            matched) string, if this line matches the assert statement
            requirements listed in the 'Requirements' section of this classes'
            docstring.
                OR
            None, otherwise.
        r   assertrD   r   N)r%   r'   Zassert_stmtrR   r   rf   rO   r1   r   r"   r}   r   r   r   r   r   rj   rl   r   r   r9   r9   r:   r@    s      
z StringParenWrapper._assert_matchc                 C   s   t | d tjtjtjfv r| d jtjkrt| }t	| D ]\}}|jtj
tjfv r<t| |d  rn|d n|d }||r<| | jtjkr<|}t }|| |}t | d tjkr||r| | jtjkr|d7 }||s<|  S q<dS )aI  
        Returns:
            string_idx such that @LL[string_idx] is equal to our target (i.e.
            matched) string, if this line matches the assignment statement
            requirements listed in the 'Requirements' section of this classes'
            docstring.
                OR
            None, otherwise.
        r   rD   r   N)r%   r'   Z	expr_stmtargumentpowerrO   r1   rP   r   rf   r   r   r"   r}   r   r   r   rI  r9   r9   r:   rA    s,     
z StringParenWrapper._assign_matchc                 C   s   t | d t | d jg}tj|v s.tj|v rt| }t| D ]\}}|jtj	kr>|t
| d k r>t| |d  rz|d n|d }||r>| | jtjkr>|}t }|| |}||r| | jtjkr|d7 }||s>|  S q>dS )am  
        Returns:
            string_idx such that @LL[string_idx] is equal to our target (i.e.
            matched) string, if this line matches the dictionary key assignment
            statement or lambda expression requirements listed in the
            'Requirements' section of this classes' docstring.
                OR
            None, otherwise.
        r   rD   r   N)r%   r   r'   ZdictsetmakerZlambdefr   rf   rO   r1   r   rM   r"   r}   r   r   r   )r   Zparent_typesr   r   rj   rl   r   r   r9   r9   r:   rB    s     
z(StringParenWrapper._dict_or_lambda_matchrx   c                 c   s  |j }t|dks,J | jj dt| |d }t|}t|| }d}d}|| jtjkrdd}|| g}	|r|		||  |
 }
|d | }d}|r|d jtjkrd}|		|d  |  t|
|| ttjd}|rt||d  | n|| |
	| |	D ]&}||D ]}|
j	|dd qqt|
V  || j}t|j|jd d|j|jd	}ttj|}|| |	| d }||d r||d d  }|r|  |r|r|d jtjksJ d
| d| d| }n|r|d jtjkr|d j}|d ur||v r||}|dkr|t|d k r||d  jtjkr||d  jdkr|  t||| t|V  |
 }|
j|_ttjd}|d urt|| n|| |	| |rttjd}t|| | |	| t|V  d S )NrD   r   r   rE   FTr   ra   )rB   r   Zinside_bracketsshould_split_rhsmagic_trailing_commaz8Apparently, old parentheses do NOT exist?! (left_leaves=z, right_leaves=r   r`   ,)rN   rM   r   r5   r   r  rO   r1   r   rh   re   rK   r   r   r2   r&   ri   r)   rR   r   rB   r   rL  rM  r}   rI   opening_bracketrF   r   Zbracket_tracker)rs   r@   ry   r   r   r   r!  Z	comma_idxr  Zleaves_to_steal_comments_from
first_lineZleft_leavesZold_parens_existZ	lpar_leafrj   rm   rC  Zstring_liner   Zold_rpar_leafZright_leavesrO  rF   r#  Znew_rpar_leafZ
comma_leafr9   r9   r:   rz     s    






	





zStringParenWrapper.do_transformN)r5   r6   r7   r8   r   r   r   r   r   r2   r   rc   r>  r?  r@  rA  rB  r   r   rz   r9   r9   r9   r:   r<    s   8&".'
r<  c                   @   s,  e Zd ZU dZdZeed< dZeed< dZeed< dZ	eed	< d
Z
eed< dZeed< dZeed< dZeed< dZeed< eejfeeej
fe
eefeeej	fe	e	ejfee	efee
ejfee
efeeefeeefei
Zeeeeef ef  ed< ddddZee eedddZeedddZdS )r   a  
    A state machine that aids in parsing a string's "trailer", which can be
    either non-existent, an old-style formatting sequence (e.g. `% varX` or `%
    (varX, varY)`), or a method-call / attribute access (e.g. `.format(varX,
    varY)`).

    NOTE: A new StringParser object MUST be instantiated for each string
    trailer we need to parse.

    Examples:
        We shall assume that `line` equals the `Line` object that corresponds
        to the following line of python code:
        ```
        x = "Some {}.".format("String") + some_other_string
        ```

        Furthermore, we will assume that `string_idx` is some index such that:
        ```
        assert line.leaves[string_idx].value == "Some {}."
        ```

        The following code snippet then holds:
        ```
        string_parser = StringParser()
        idx = string_parser.parse(line.leaves, string_idx)
        assert line.leaves[idx].type == token.PLUS
        ```
    ic4DEFAULT_TOKENrD   STARTr   rQ   r   rP   r   r      SINGLE_FMT_ARGr	  rK      rI   r   DONE_gotoNr  c                 C   s   | j | _d| _d S )Nr   )rR  _state_unmatched_lpars)rs   r9   r9   r:   rt     s    zStringParser.__init__)rN   r   r=   c                 C   sD   || j tjksJ |d }|t|k r@| || r@|d7 }q|S )a6  
        Pre-conditions:
            * @leaves[@string_idx].type == token.STRING

        Returns:
            The index directly after the last leaf which is apart of the string
            trailer, if a "trailer" exists.
                OR
            @string_idx + 1, if no string "trailer" exists.
        rD   )rO   r1   r}   rM   _next_state)rs   rN   r   rl   r9   r9   r:   r     s
    
zStringParser.parser8  c                 C   s   t |rdS |j}|tjkr*|  jd7  _| j}|| jkrf|tjkr|  jd8  _| jdkr| j| _nf||f| jv r| j||f | _n6|| jf| jv r| j|| jf | _nt	| j
j d| j| jkrdS dS )a  
        Pre-conditions:
            * On the first call to this function, @leaf MUST be the leaf that
            was directly after the string leaf in question (e.g. if our target
            string is `line.leaves[i]` then the first call to this method must
            be `line.leaves[i + 1]`).
            * On the next call to this function, the leaf parameter passed in
            MUST be the leaf directly following @leaf.

        Returns:
            True iff @leaf is apart of the string's trailer.
        TrD   r   r%  F)r"   rO   r1   rK   rY  rX  rI   rW  rQ  r'  r   r5   rV  )rs   rj   Z
next_tokenZcurrent_stater9   r9   r:   rZ    s&    




zStringParser._next_state)r5   r6   r7   r8   rQ  r   r   rR  rQ   rP   r   rT  rK   rI   rV  r1   rW  r
   r   ParserStateNodeTypert   r   r2   rc   r   rd   rZ  r9   r9   r9   r:   r     s0   





 r   )r   r=   c                    s(   | j |   tdd fdd}|S )a  
    Factory for a convenience function that is used to orphan @string_leaf
    and then insert multiple new leaves into the same part of the node
    structure that @string_leaf had originally occupied.

    Examples:
        Let `string_leaf = Leaf(token.STRING, '"foo"')` and `N =
        string_leaf.parent`. Assume the node `N` has the following
        original structure:

        Node(
            expr_stmt, [
                Leaf(NAME, 'x'),
                Leaf(EQUAL, '='),
                Leaf(STRING, '"foo"'),
            ]
        )

        We then run the code snippet shown below.
        ```
        insert_str_child = insert_str_child_factory(string_leaf)

        lpar = Leaf(token.LPAR, '(')
        insert_str_child(lpar)

        bar = Leaf(token.STRING, '"bar"')
        insert_str_child(bar)

        rpar = Leaf(token.RPAR, ')')
        insert_str_child(rpar)
        ```

        After which point, it follows that `string_leaf.parent is None` and
        the node `N` now has the following structure:

        Node(
            expr_stmt, [
                Leaf(NAME, 'x'),
                Leaf(EQUAL, '='),
                Leaf(LPAR, '('),
                Leaf(STRING, '"bar"'),
                Leaf(RPAR, ')'),
            ]
        )
    N)childr=   c                    s0   d usJ  d usJ   |   d7  d S r-  )r   )r]  Zstring_child_idxZstring_parentr9   r:   r!  D	  s    z2insert_str_child_factory.<locals>.insert_str_child)r   r   LN)r   r!  r9   r^  r:   r  	  s    .	r  )seqr=   c                    s   t td fdd}|S )a  
    Examples:
        ```
        my_list = [1, 2, 3]

        is_valid_index = is_valid_index_factory(my_list)

        assert is_valid_index(0)
        assert is_valid_index(2)

        assert not is_valid_index(3)
        assert not is_valid_index(-1)
        ```
    )rl   r=   c                    s   d|   kot  k S   S )zx
        Returns:
            True iff @idx is positive AND seq[@idx] does NOT raise an
            IndexError.
        r   )rM   )rl   r`  r9   r:   r   `	  s    z.is_valid_index_factory.<locals>.is_valid_index)rc   rd   )r`  r   r9   ra  r:   r   P	  s    r   )br8   r   sysabcr   r   collectionsr   Zdataclassesr   typingr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   version_infoZtyping_extensionsr   r   Zmypy_extensionsr   Zblack.commentsr   Zblack.linesr   r   Z
black.moder   r   Zblack.nodesr   r   r    r!   r"   r#   r$   r%   r&   r'   Zblack.rustyr(   r)   r*   Zblack.stringsr+   r,   r-   r.   r/   r0   Zblib2to3.pgen2r1   Zblib2to3.pytreer2   r3   	Exceptionr4   r;   r_  ZTransformerrc   r7  r\  r[  r   r   r   	frozensetr5  r   r?   rn   ro   r   r   r   r   r   r  rd   r  r   r  r<  r   r  r   r9   r9   r9   r:   <module>   sz   @
0 

Pj=   ! 9 w/   ~    =