o
    DDi                      @   s   d dl mZmZ d dlmZmZmZ d dlmZm	Z	m
Z
 d dlmZ d dlmZ d dlmZ G dd dZeed	d
G dd deZG dd dee ZdS )    )	dataclassfield)ListOptionalSequence)BaseStatementCSTNodeModule)	add_slots)CodegenState)BaseMetadataProviderc                   @   s   e Zd ZdZg dZdddZdefd	d
ZdefddZ	defddZ
dedefddZdedefddZdedefddZdS )CodegenPartiala  
    Provided by :class:`ExperimentalReentrantCodegenProvider`.

    Stores enough information to generate either a small patch
    (:meth:`get_modified_code_range`) or a new file (:meth:`get_modified_code`) by
    replacing the old node at this position.
    )start_offset
end_offsethas_trailing_newline_indent_tokens_prev_codegen_statestate_ReentrantCodegenStatereturnNc                 C   s0   |j d | _|j| _d| _t|j| _|| _d S )NT)	start_offset_stackr   char_offsetr   r   tupleindent_tokensr   r   )selfr    r   Z/var/www/Datamplify/venv/lib/python3.10/site-packages/libcst/metadata/reentrant_codegen.py__init__!   s
   
zCodegenPartial.__init__c                 C   s
   | j  S z
        Equivalent to :meth:`libcst.Module.bytes` on the top-level module that contains
        this statement, except that it uses the cached result from our previous code
        generation pass, so it's faster.
        )r   get_coder   r   r   r   get_original_module_code*   s   
z'CodegenPartial.get_original_module_codec                 C   s   |   | jjS r   )r"   encoder   encodingr!   r   r   r   get_original_module_bytes2   s   z(CodegenPartial.get_original_module_bytesc                 C   s   | j  | j| j S )z
        Equivalent to :meth:`libcst.Module.code_for_node` on the current statement,
        except that it uses the cached result from our previous code generation pass,
        so it's faster.
        )r   r    r   r   r!   r   r   r   get_original_statement_code:   s   z*CodegenPartial.get_original_statement_codenodec                 C   s@   t | jj| jjt| jd}|| | js|  d	|j
S )z
        Gets the new code for ``node`` as if it were in same location as the old
        statement being replaced. This means that it inherits details like the old
        statement's indentation.
        )default_indentdefault_newliner    )r   r   r(   r)   listr   _codegenr   pop_trailing_newlinejointokens)r   r'   new_codegen_stater   r   r   get_modified_statement_codeB   s   
z*CodegenPartial.get_modified_statement_codec                 C   s6   |   }| |}|d| j  | || jd  S )z
        Gets the new code for the module at the root of this statement's tree, but with
        the supplied replacement ``node`` in its place.
        N)r"   r1   r   r   )r   r'   originalpatchr   r   r   get_modified_module_codeR   s   
$z'CodegenPartial.get_modified_module_codec                 C   s   |  || jjS )z
        Gets the new bytes for the module at the root of this statement's tree, but with
        the supplied replacement ``node`` in its place.
        )r4   r#   r   r$   r   r'   r   r   r   get_modified_module_bytes[   s   
z(CodegenPartial.get_modified_module_bytes)r   r   r   N)__name__
__module____qualname____doc__	__slots__r   strr"   bytesr%   r&   r   r1   r4   r6   r   r   r   r   r      s    
		r   F)frozenc                       s  e Zd ZU ee ed< dZeed< dZe	ed< dZ
e	ed< eedZee	 ed< d	Zee ed
< eedZee ed< dedd	f fddZd fddZd fddZdedd	f fddZdedd	fddZdedd	fddZd fddZdefddZ  ZS ) r   providerzutf-8r$   r   indent_sizer   )default_factoryr   Ncached_codetrailing_partialsvaluer   c                    s&   t t| | |  jt|7  _d S N)superr   increase_indentr@   lenr   rD   	__class__r   r   rG   p   s   z&_ReentrantCodegenState.increase_indentc                    s*   |  j t| jd 8  _ tt|   d S )Nr   )r@   rH   r   rF   r   decrease_indentr!   rJ   r   r   rL   t   s   z&_ReentrantCodegenState.decrease_indentc                    s"   t t|   |  j| j7  _d S rE   )rF   r   add_indent_tokensr   r@   r!   rJ   r   r   rM   x   s   z(_ReentrantCodegenState.add_indent_tokensc                    s0   t t| | |  jt|7  _| j  d S rE   )rF   r   	add_tokenr   rH   rC   clearrI   rJ   r   r   rN   |   s   z _ReentrantCodegenState.add_tokenr'   c                 C   s    t |tsd S | j| j d S rE   )
isinstancer   r   appendr   r5   r   r   r   before_codegen   s   
z%_ReentrantCodegenState.before_codegenc                 C   s>   t |tsd S t| }| j|| | j  | j| d S rE   )	rP   r   r   r?   set_metadatar   poprC   rQ   )r   r'   partialr   r   r   after_codegen   s   

z$_ReentrantCodegenState.after_codegenc                    s<   | j D ]}| jt| jd 8  _d|_qtt|   dS )a  
        :class:`libcst.Module` contains a hack where it removes the last token (a
        newline) if the original file didn't have a newline.

        If this happens, we need to go back through every node at the end of the file,
        and fix their `end_offset`.
        r   FN)rC   r   rH   r/   r   rF   r   r-   )r   tprJ   r   r   r-      s   
z+_ReentrantCodegenState.pop_trailing_newlinec                 C   s(   | j }|d ur	|S d| j}|| _ |S )Nr*   )rB   r.   r/   )r   rB   r   r   r   r       s   z_ReentrantCodegenState.get_code)r   N)r7   r8   r9   r   r   __annotations__r$   r<   r@   intr   r   r+   r   r   rB   r   rC   rG   rL   rM   rN   r   rR   rV   r-   r    __classcell__r   r   rJ   r   r   e   s    
 	r   c                   @   s"   e Zd ZdZdeddfddZdS )$ExperimentalReentrantCodegenProvidera  
    An experimental API that allows fast generation of modified code by recording an
    initial code-generation pass, and incrementally applying updates. It is a
    performance optimization for a few niche use-cases and is not user-friendly.

    **This API may change at any time without warning (including in minor releases).**

    This is rarely useful. Instead you should make multiple modifications to a single
    syntax tree, and generate the code once. However, we can think of a few use-cases
    for this API (hence, why it exists):

    - When linting a file, you might generate multiple independent patches that a user
      can accept or reject. Depending on your architecture, it may be advantageous to
      avoid regenerating the file when computing each patch.

    - You might want to call out to an external utility (e.g. a typechecker, such as
      pyre or mypy) to validate a small change. You may need to generate and test lots
      of these patches.

    Restrictions:

    - For safety and sanity reasons, the smallest/only level of granularity is a
      statement. If you need to patch part of a statement, you regenerate the entire
      statement. If you need to regenerate an entire module, just call
      :meth:`libcst.Module.code`.

    - This does not (currently) operate recursively. You can patch an unpatched piece
      of code multiple times, but you can't layer additional patches on an already
      patched piece of code.
    moduler   Nc                 C   s$   t |j|j| |jd}|| d S )N)r(   r)   r?   r$   )r   r(   r)   r$   r,   )r   r\   r   r   r   r   	_gen_impl   s   z.ExperimentalReentrantCodegenProvider._gen_impl)r7   r8   r9   r:   r	   r]   r   r   r   r   r[      s    r[   N)dataclassesr   r   typingr   r   r   libcstr   r   r	   libcst._add_slotsr
   libcst._nodes.internalr   libcst.metadatar   r   r   r[   r   r   r   r   <module>   s   UC