U
    c                     @  s   d Z ddlmZ ddlmZ ddlmZ ddlZddlZddl	m
Z
mZ dZddd	d
dZdddddZddd	ddZdddddddZdddddZdS )z6
:func:`~pandas.eval` source string parsing functions
    )annotations)StringIO)	iskeywordN)HashableIteratord   str)namereturnc                   s   |   rt| s| S dd tj D   ddddddd	d
d d fdd| D } d|  } |   s|td|  d| S )a=  
    Create valid Python identifiers from any string.

    Check if name contains any special characters. If it contains any
    special characters, the special characters will be replaced by
    a special string and a prefix is added.

    Raises
    ------
    SyntaxError
        If the returned name is not a Python valid identifier, raise an exception.
        This can happen if there is a hashtag in the name, as the tokenizer will
        than terminate and not find the backtick.
        But also for characters that fall out of the range of (U+0001..U+007F).
    c                 S  s$   i | ]\}}|d t j|  d qS )_)tokentok_name).0chartokval r   C/tmp/pip-unpacked-wheel-g7fro6k3/pandas/core/computation/parsing.py
<dictcomp>)   s    z2create_valid_python_identifier.<locals>.<dictcomp>r   Z_QUESTIONMARK_Z_EXCLAMATIONMARK_Z_DOLLARSIGN_Z
_EUROSIGN_Z_DEGREESIGN_Z_SINGLEQUOTE_Z_DOUBLEQUOTE_) ?!$u   €   °'" c                   s   g | ]}  ||qS r   )get)r   r   Zspecial_characters_replacementsr   r   
<listcomp>=   s     z2create_valid_python_identifier.<locals>.<listcomp>ZBACKTICK_QUOTED_STRING_zCould not convert 'z' to a valid Python identifier.)isidentifierr   tokenizeEXACT_TOKEN_TYPESitemsupdatejoinSyntaxError)r	   r   r   r   create_valid_python_identifier   s*    r&   ztuple[int, str])tokr
   c                 C  s&   | \}}|t krtjt|fS ||fS )a[  
    Clean up a column name if surrounded by backticks.

    Backtick quoted string are indicated by a certain tokval value. If a string
    is a backtick quoted token it will processed by
    :func:`_create_valid_python_identifier` so that the parser can find this
    string when the query is executed.
    In this case the tok will get the NAME tokval.

    Parameters
    ----------
    tok : tuple of int, str
        ints correspond to the all caps constants in the tokenize module

    Returns
    -------
    tok : Tuple[int, str]
        Either the input or token or the replacement values
    )BACKTICK_QUOTED_STRINGr    NAMEr&   )r'   toknumr   r   r   r   clean_backtick_quoted_toksF   s    r+   r   c                 C  sD   z&t d|  d}t|d }t|W S  tk
r>   |  Y S X dS )a  
    Function to emulate the cleaning of a backtick quoted name.

    The purpose for this function is to see what happens to the name of
    identifier if it goes to the process of being parsed a Python code
    inside a backtick quoted string and than being cleaned
    (removed of any special characters).

    Parameters
    ----------
    name : hashable
        Name to be cleaned.

    Returns
    -------
    name : hashable
        Returns the name after tokenizing and cleaning.

    Notes
    -----
        For some cases, a name cannot be converted to a valid Python identifier.
        In that case :func:`tokenize_string` raises a SyntaxError.
        In that case, we just return the name unmodified.

        If this name was used in the query string (this makes the query call impossible)
        an error will be raised by :func:`tokenize_backtick_quoted_string` instead,
        which is not caught and propagates to the user level.
    `   N)tokenize_stringnextr&   r%   )r	   Z	tokenizedr   r   r   r   clean_column_name`   s    
r0   zIterator[tokenize.TokenInfo]int)token_generatorsourcestring_startr
   c                 C  s8   | D ]"\}}}}}|dkr|d } q(qt ||| fS )a  
    Creates a token from a backtick quoted string.

    Moves the token_generator forwards till right after the next backtick.

    Parameters
    ----------
    token_generator : Iterator[tokenize.TokenInfo]
        The generator that yields the tokens of the source string (Tuple[int, str]).
        The generator is at the first token after the backtick (`)

    source : str
        The Python source code string.

    string_start : int
        This is the start of backtick quoted string inside the source string.

    Returns
    -------
    tok: Tuple[int, str]
        The token that represents the backtick quoted string.
        The integer is equal to BACKTICK_QUOTED_STRING (100).
    r,   r-   )r(   )r2   r3   r4   r   r   startZ
string_endr   r   r   tokenize_backtick_quoted_string   s
    r6   zIterator[tuple[int, str]])r3   r
   c                 c  s   t | j}t|}|D ]t\}}}}}|dkrzt|| |d d dV  W q tk
r~ } ztd|  d|W 5 d}~X Y qX q||fV  qdS )a$  
    Tokenize a Python source code string.

    Parameters
    ----------
    source : str
        The Python source code string.

    Returns
    -------
    tok_generator : Iterator[Tuple[int, str]]
        An iterator yielding all tokens with only toknum and tokval (Tuple[ing, str]).
    r,   r-   )r4   zFailed to parse backticks in 'z'.N)r   readliner    generate_tokensr6   	Exceptionr%   )r3   Zline_readerr2   r*   r   r5   r   errr   r   r   r.      s    

  
&r.   )__doc__
__future__r   ior   keywordr   r   r    typingr   r   r(   r&   r+   r0   r6   r.   r   r   r   r   <module>   s   3%"