U
    nufE                     @   s  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mZ d dl mZm	Z	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 d dlmZ erddlmZ G dd	 d	e
Zeeef Zejd  d
kreeeeeef eeef ef Z nej Z dd Z!G dd de"ddZ#ejdkr(e j$Z%nG dd dZ%dSddZ&dTddZ'ejdkr`dd Z(ndd Z(dd Z)dd Z*dUd d!Z+d"d# ee j,D Z-dVd$d%Z.d&d# ee j,D Z/d'd# ee j,D d(d)d*d+d,hB Z0d-d. Z1d/d0 Z2d1d2 Z3d3d4 Z4d5d6 Z5d7d8 Z6d9d: Z7e8 Z9d;d< Z:dWd=d>Z;d?d@ Z<G dAdB dBe8Z=ejd  d
krXdCdD Z>ndEdD Z>dFdG Z?dHdI Z@ejdd
 dJkrd dKlAmBZB eBddLdMdN ZCdOdP ZDndQdN ZCdRdP ZDdS )X    N)ABCMeta)ModuleexprAST)CallableDictIterableIteratorListOptionalTupleUnioncastAnyTYPE_CHECKING)	iteritems   )NodeNGc                   @   s   e Zd ZdZdZdZdS )EnhancedASTNr   )__name__
__module____qualname__Zfirst_tokenZ
last_tokenlineno r   r   2/tmp/pip-unpacked-wheel-0ukdbujv/asttokens/util.pyr   !   s   r      c                 C   s   dt j|  t|df S )zRReturns a human-friendly representation of a token with the given type and string.z%s:%su)tokentok_namereprlstrip)tok_typestringr   r   r   
token_repr/   s    r#   c                   @   s   e Zd ZdZdd ZdS )Tokena  
  TokenInfo is an 8-tuple containing the same 5 fields as the tokens produced by the tokenize
  module, and 3 additional ones useful for this module:

  - [0] .type     Token type (see token.py)
  - [1] .string   Token (a string)
  - [2] .start    Starting (row, column) indices of the token (a 2-tuple of ints)
  - [3] .end      Ending (row, column) indices of the token (a 2-tuple of ints)
  - [4] .line     Original line (string)
  - [5] .index    Index of the token in the list of tokens that it belongs to.
  - [6] .startpos Starting character offset into the input text.
  - [7] .endpos   Ending character offset into the input text.
  c                 C   s   t | j| jS N)r#   typer"   selfr   r   r   __str__D   s    zToken.__str__N)r   r   r   __doc__r)   r   r   r   r   r$   6   s   r$   z0type string start end line index startpos endpos)      c                   @   s   e Zd Ze ZdS )AstConstantN)r   r   r   objectvaluer   r   r   r   r-   L   s   r-   c                 C   s   | j |ko|dkp| j|kS )zVReturns true if token is of the given type and, if a string is given, has that string.N)r&   r"   r   r!   Ztok_strr   r   r   match_tokenP   s    r1   c                 C   s>   t | ||s:tdt||t| | jd | jd d f dS )z
  Verifies that the given token is of the expected type. If tok_str is given, the token string
  is verified too. If the token doesn't match, raises an informative ValueError.
  z+Expected token %s, got %s on line %s col %sr   r   N)r1   
ValueErrorr#   strstartr0   r   r   r   expect_tokenV   s      r5   )r+      c                 C   s   | t jt jt jfkS zW
    These are considered non-coding tokens, as they don't affect the syntax tree.
    )r   NLCOMMENTENCODING
token_typer   r   r   is_non_coding_tokend   s    r=   c                 C   s
   | t jkS r7   )r   N_TOKENSr;   r   r   r   r=   k   s    c                 C   s    t ttg tf t| jS )z;
  Generates standard library tokens for the given code.
  )tokenizegenerate_tokensr   r   r3   ioStringIOreadline)textr   r   r   r@   s   s    r@   c                 C   s   t | drtS tS )z
  Returns a function which yields all direct children of a AST node,
  skipping children that are singleton nodes.
  The function depends on whether ``node`` is from ``ast`` or from the ``astroid`` module.
  get_children)hasattriter_children_astroiditer_children_astnoder   r   r   iter_children_func~   s    rK   Fc                 C   s   |st | rg S |  S r%   )is_joined_strrE   )rJ   include_joined_strr   r   r   rG      s    rG   c              	   C   s<   h | ]4\}}t |trt|tjtjtjtjtjfr|qS r   )	
isinstancer&   
issubclassastZexpr_contextZboolopoperatorZunaryopZcmpop.0ncr   r   r   	<setcomp>   s     
rV   c                 c   sp   |st | rd S t| tjrLt| j| jD ]\}}|d k	r@|V  |V  q*d S t| D ]}|jt	krV|V  qVd S r%   )
rL   rN   rP   r   zipkeysvaluesZiter_child_nodes	__class__
SINGLETONS)rJ   rM   keyr/   childr   r   r   rH      s    
rH   c                 C   s*   h | ]"\}}t |trt|tjr|qS r   )rN   r&   rO   rP   ZstmtrR   r   r   r   rV      s    
 c                 C   s*   h | ]"\}}t |trt|tjr|qS r   )rN   r&   rO   rP   r   rR   r   r   r   rV      s    
 Z
AssignNameZDelNameZConstZ
AssignAttrZDelAttrc                 C   s   | j jtkS )z+Returns whether node is an expression node.)rZ   r   expr_class_namesrI   r   r   r   is_expr   s    r_   c                 C   s   | j jtkS )z)Returns whether node is a statement node.)rZ   r   stmt_class_namesrI   r   r   r   is_stmt   s    ra   c                 C   s   | j jdkS )z&Returns whether node is a module node.r   rZ   r   rI   r   r   r   	is_module   s    rc   c                 C   s   | j jdkS )zFReturns whether node is a JoinedStr node, used to represent f-strings.	JoinedStrrb   rI   r   r   r   rL      s    rL   c                 C   s   | j jdkS )z2Returns whether node is a starred expression node.ZStarredrb   rI   r   r   r   
is_starred   s    re   c                 C   s0   | j jdkp.| j jdko.tttttj| jS )z?Returns whether node represents a slice, e.g. `1:2` in `x[1:2]`)SliceZExtSlicer   )	rZ   r   anymapis_slicer   rP   r   ZeltsrI   r   r   r   ri      s    ri   c                 C   sB   | j jdko@t| tj o@| j| j  ko<| j  ko<d kS   S )Nrf   )rZ   r   rN   rP   r   loweruppersteprI   r   r   r   is_empty_astroid_slice   s
    &rm   c                 C   s   |sdd }t | }t }d}| dtfg}|r| \}}}	|	tkr||ksPt|| |||\}
}||||f t|}||D ]}||||
tf qq*|||t	t
t |	}q*|S )a5  
  Scans the tree under the node depth-first using an explicit stack. It avoids implicit recursion
  via the function call stack to avoid hitting 'maximum recursion depth exceeded' error.

  It calls ``previsit()`` and ``postvisit()`` as follows:

  * ``previsit(node, par_value)`` - should return ``(par_value, value)``
        ``par_value`` is as returned from ``previsit()`` of the parent.

  * ``postvisit(node, par_value, value)`` - should return ``value``
        ``par_value`` is as returned from ``previsit()`` of the parent, and ``value`` is as
        returned from ``previsit()`` of this node itself. The return ``value`` is ignored except
        the one for the root node, which is returned from the overall ``visit_tree()`` call.

  For the initial node, ``par_value`` is None. ``postvisit`` may be None.
  c                 S   s   d S r%   r   )rJ   pvaluer/   r   r   r   <lambda>       zvisit_tree.<locals>.<lambda>N)rK   set	_PREVISITpopAssertionErroraddappendleninsertr   r   r$   )rJ   ZprevisitZ	postvisititer_childrendoneretstackcurrentZ	par_valuer/   rn   Z
post_valueinsrT   r   r   r   
visit_tree   s$    
r   c                 c   sf   t | }t }| g}|rb| }||ks,t|| |V  t|}|||D ]}||| qNqdS )a1  
  Recursively yield all descendant nodes in the tree starting at ``node`` (including ``node``
  itself), using depth-first pre-order traversal (yieling parents before their children).

  This is similar to ``ast.walk()``, but with a different order, and it works for both ``ast`` and
  ``astroid`` trees. Also, as ``iter_children()``, it skips singleton nodes generated by ``ast``.

  By default, ``JoinedStr`` (f-string) nodes and their contents are skipped
  because they previously couldn't be handled. Set ``include_joined_str`` to True to include them.
  N)rK   rq   rs   rt   ru   rw   rx   )rJ   rM   ry   rz   r|   r}   r~   rU   r   r   r   walk  s    
r   c                 C   sX   d}g }t |D ]*\}}}|| ||  || |}q|| |d  d|S )ah  
  Replaces multiple slices of text with new values. This is a convenience method for making code
  modifications of ranges e.g. as identified by ``ASTTokens.get_text_range(node)``. Replacements is
  an iterable of ``(start, end, new_text)`` tuples.

  For example, ``replace("this is a test", [(0, 4, "X"), (8, 9, "THE")])`` produces
  ``"X is THE test"``.
  r   N )sortedrv   join)rD   replacementsppartsr4   endZnew_textr   r   r   replace1  s    

r   c                   @   s    e Zd ZdZdd Zdd ZdS )NodeMethodsz[
  Helper to get `visit_{node_type}` methods given a node's class and cache the results.
  c                 C   s
   i | _ d S r%   )_cacher'   r   r   r   __init__I  s    zNodeMethods.__init__c                 C   s:   | j |}|s6d|j  }t|||j}|| j |< |S )z
    Using the lowercase name of the class as node_type, returns `obj.visit_{node_type}`,
    or `obj.visit_default` if the type-specific method is not found.
    Zvisit_)r   getr   rj   getattrZvisit_default)r(   objclsmethodnamer   r   r   r   M  s    
zNodeMethods.getN)r   r   r   r*   r   r   r   r   r   r   r   E  s   r   c                 C   s   t | S r%   )iter)original_tokensr   r   r   patched_generate_tokens^  s    r   c                 c   sz   g }| D ]X}|j tjtjtjfkrB|r6|d j|jkrB|| qt|D ]
}|V  qJg }|V  qt|D ]
}|V  qjdS )a  
    Fixes tokens yielded by `tokenize.generate_tokens` to handle more non-ASCII characters in identifiers.
    Workaround for https://github.com/python/cpython/issues/68382.
    Should only be used when tokenizing a string that is known to be valid syntax,
    because it assumes that error tokens are not actually errors.
    Combines groups of consecutive NAME, NUMBER, and/or ERRORTOKEN tokens into a single NAME token.
    N)	r&   r?   NAME
ERRORTOKENNUMBERr   r4   rv   combine_tokens)r   grouptokZcombined_tokenr   r   r   r   b  s    	c                 C   sf   t dd | D r(tdd | D dkr,| S tjtjddd | D | d j| d	 j| d jd
gS )Nc                 s   s   | ]}|j tjkV  qd S r%   )r&   r?   r   rS   r   r   r   r   	<genexpr>}  s     z!combine_tokens.<locals>.<genexpr>c                 S   s   h | ]
}|j qS r   )liner   r   r   r   rV   }  s     z!combine_tokens.<locals>.<setcomp>r   r   c                 s   s   | ]}|j V  qd S r%   )r"   )rS   tr   r   r   r     s     r   r   )r&   r"   r4   r   r   )	rg   rw   r?   	TokenInfor   r   r4   r   r   )r   r   r   r   r   {  s    (r   c                 C   s*   dd t | | D }|r&t|d S | S )zq
  If the given AST node contains multiple statements, return the last one.
  Otherwise, just return the node.
  c                 S   s&   g | ]}t |st|jd kr|qS ))ZexcepthandlerZExceptHandlerZ
match_caseZ	MatchCaseZ	TryExceptZ
TryFinally)ra   r&   r   )rS   r]   r   r   r   
<listcomp>  s    zlast_stmt.<locals>.<listcomp>r   )rK   	last_stmt)rJ   Zchild_stmtsr   r   r   r     s    
r   )r+      )	lru_cache)maxsizec                     sb   d t  } dd t | D }dd |D }tt|t|k}t fdd|D }|o`|S )a  
    The positions attached to nodes inside f-string FormattedValues have some bugs
    that were fixed in Python 3.9.7 in https://github.com/python/cpython/pull/27729.
    This checks for those bugs more concretely without relying on the Python version.
    Specifically this checks:
     - Values with a format spec or conversion
     - Repeated (i.e. identical-looking) expressions
     - f-strings implicitly concatenated over multiple lines.
     - Multiline, triple-quoted f-strings.
    z(
      f"a {b}{b} c {d!r} e {f:g} h {i:{j}} k {l:{m:n}}"
      f"a {b}{b} c {d!r} e {f:g} h {i:{j}} k {l:{m:n}}"
      f"{x + y + z} {x} {y} {z} {z} {z!a} {z:z}"
      f'''
      {s} {t}
      {u} {v}
      '''
    )c                 S   s   g | ]}t |tjr|qS r   )rN   rP   NamerS   rJ   r   r   r   r     s      z*fstring_positions_work.<locals>.<listcomp>c                 S   s   g | ]}|j |jfqS r   )r   
col_offsetr   r   r   r   r     s     c                 3   s    | ]}t  ||jkV  qd S r%   )rP   Zget_source_segmentidr   sourcer   r   r     s   z)fstring_positions_work.<locals>.<genexpr>)rP   parser   rw   rq   all)treeZ
name_nodesZname_positionsZpositions_are_uniqueZcorrect_source_segmentsr   r   r   fstring_positions_work  s    	
r   c                 C   s   t jdkrdS t| ddD ]l}t|tjs,q|jD ]R}t|dd t|tjr2t	 spt|j
D ]}t|dd q^|jr2t|jdd q2qdS )z
    Add a special attribute `_broken_positions` to nodes inside f-strings
    if the lineno/col_offset cannot be trusted.
    )r+      NT)rM   Z_broken_positions)sysversion_infor   rN   rP   rd   rY   setattrZFormattedValuer   r/   format_spec)r   Z	joinedstrpartr]   r   r   r   annotate_fstring_nodes  s    

r   c                   C   s   dS )NFr   r   r   r   r   r     s    c                 C   s   d S r%   r   )Z_treer   r   r   r     s    )N)N)F)F)F)ErP   collectionsrA   r   r   r?   abcr   r   r   r   typingr   r   r   r	   r
   r   r   r   r   r   r   sixr   Zastroid_compatr   r   ZAstNoder   intr3   r   r#   
namedtupler$   Constantr-   r1   r5   r=   r@   rK   rG   __dict__r[   rH   r`   r^   r_   ra   rc   rL   re   ri   rm   r.   rr   r   r   r   r   r   r   r   	functoolsr   r   r   r   r   r   r   <module>   sv   4$






+



