B
    Mt\6                 @   s   d dl mZ d dlmZ d dlZd dlZd dlZd dlZd dlm	Z	 e
Zyd dlZd dlmZ W n ek
r|   d ZdZY nX G dd deZddejd fd	d
Zdd Zdd Zdd ZdddZdd ZdddZdddZdS )    )
generators)bisect_rightN)
ModuleType)PyCF_ONLY_ASTc               @   s   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
d%ddZd&ddZd'ddZd(ddZd)ddZd*ddZd d! Zdd"ejddfd#d$ZdS )+SourcezY a immutable object holding a source code fragment,
        possibly deindenting it.
    r   c             O   s   g  | _ }|dd}|dd}x|D ]}|s4g }t|trF|j }njt|ttfrddd |D }nLt|tjjr|	d}|rx.|r|d 
 rP |  qW nt||dj }|rt|}|| q(W d S )	NdeindentTrstripc             S   s   g | ]}| d qS )
)r   ).0x r   .lib/python3.7/site-packages/py/_code/source.py
<listcomp>!   s    z#Source.__init__.<locals>.<listcomp>r	   )r   )linesget
isinstancer   tuplelistpybuiltinZ_basestringsplitstrippop	getsourcer   extend)selfpartskwargsr   Zder   partZ	partlinesr   r   r   __init__   s*    



zSource.__init__c             C   s<   y| j |j kS  tk
r6   t|tr2t| |kS dS X d S )NF)r   AttributeErrorr   str)r   otherr   r   r   __eq__/   s    
zSource.__eq__c             C   s:   t |tr| j| S |jdkr&td| |j|jS d S )N)N   z!cannot slice a Source with a step)r   intr   step
IndexError__getslice__startstop)r   keyr   r   r   __getitem__7   s
    


zSource.__getitem__c             C   s
   t | jS )N)lenr   )r   r   r   r   __len__?   s    zSource.__len__c             C   s   t  }| j|| |_|S )N)r   r   )r   r*   end	newsourcer   r   r   r)   B   s    zSource.__getslice__c             C   s|   dt |  }}x"||k r0| j|  s0|d7 }qW x&||krX| j|d   sX|d8 }q4W t }| j|| |jdd< |S )z] return new source object with trailing
            and leading blank lines removed.
        r   r%   N)r.   r   r   r   )r   r*   r0   sourcer   r   r   r   G   s    zSource.strip     c                s@   t |}t |}t  } fdd| jD }|j| |j |_|S )ze return a copy of the source object with
            'before' and 'after' wrapped around it.
        c                s   g | ]} | qS r   r   )r
   line)indentr   r   r   [   s    z$Source.putaround.<locals>.<listcomp>)r   r   )r   ZbeforeZafterr6   r1   r   r   )r6   r   	putaroundT   s    zSource.putaroundc                s    t  } fdd| jD |_|S )zl return a copy of the source object with
            all lines indented by the given indent-string.
        c                s   g | ]} | qS r   r   )r
   r5   )r6   r   r   r   d   s    z!Source.indent.<locals>.<listcomp>)r   r   )r   r6   r1   r   )r6   r   r6   _   s    zSource.indentFc             C   s   |  ||\}}| || S )zc return Source statement which contains the
            given linenumber (counted from 0).
        )getstatementrange)r   lineno	assertionr*   r0   r   r   r   getstatementg   s    zSource.getstatementc             C   s:   d|  krt | k s"n tdt|| \}}}||fS )z{ return (start, end) tuple which spans the minimal
            statement region which containing the given lineno.
        r   zlineno out of range)r.   r(   getstatementrange_ast)r   r9   r:   astr*   r0   r   r   r   r8   n   s    zSource.getstatementrangeNc             C   s    t  }t| j||jdd< |S )a:   return a new source object deindented by offset.
            If offset is None then guess an indentation offset from
            the first non-blank line.  Subsequent lines which have a
            lower indentation offset will be copied verbatim as
            they are assumed to be part of multilines.
        N)r   r   r   )r   offsetr1   r   r   r   r   w   s    	zSource.deindentTc             C   s   yddl }W n tk
r(   dd }Y nX |j}|rBt|  }nt| }y||d  W n( tk
rp    Y n tk
r   dS X dS dS )zb return True if source is parseable, heuristically
            deindenting it by default.
        r   Nc             S   s   t | ddS )NZasdexec)compile)r   r   r   r   <lambda>   s    z$Source.isparseable.<locals>.<lambda>r	   FT)parserImportErrorZsuiter"   r   KeyboardInterrupt	Exception)r   r   rB   Zsyntax_checkerr2   r   r   r   isparseable   s    zSource.isparseablec             C   s   d | jS )Nr	   )joinr   )r   r   r   r   __str__   s    zSource.__str__r?   c             C   sd  |rt j|jddr||dkr*td}|jj|j }}d| j	 }| j
 j	d7  _	|sj|d||f  }n|d|||f  }d| jd }	yt|	|||}
W n tk
r"   t d }| jd|j }|jr|d	|j d
  |d|  td|}|j|_|j|_|j|_|Y n>X |t@ r2|
S dd | jD }ddl}dd||f|j|< |
S dS )z return compiled code object. if filename is None
            invent an artificial filename which displays
            the source/line position of the caller frame.
        r   )fileNr%   z<%d-codegen z%s:%d>z	%r %s:%d>r	    ^z*(code was compiled probably from here: %s)c             S   s   g | ]}|d  qS )r	   r   )r
   r   r   r   r   r      s    z"Source.compile.<locals>.<listcomp>)r   pathlocalZchecksys	_getframef_codeco_filenamef_lineno_compilecounter	__class__rG   r   cpy_compileSyntaxErrorexc_infor9   r>   appendtext	_AST_FLAG	linecachecache)r   filenamemodeflagdont_inherit	_genframefnr9   baser2   coexZmsglinesZnewexr   r[   r   r   r   r@      s:    



zSource.compile)r3   r3   r4   )r4   )F)F)N)T)__name__
__module____qualname____doc__rS   r    r$   r-   r/   r)   r   r7   r6   r;   r8   r   rF   rH   r   compiler_flagr@   r   r   r   r   r      s$   



	

r   r?   c             C   sL   t dk	r$t| t jr$t| ||||S td}t| }|j||||d}|S )z compile the given source to a raw code object,
        and maintain an internal cache which allows later
        retrieval of the source code for the code object
        and any recursively created code objects.
    Nr%   )ra   )_astr   ZASTrU   rN   rO   r   r@   )r2   r]   r^   flagsr`   ra   srd   r   r   r   compile_   s    
rn   c             C   s   yt j| }W n tk
r   yt| p4t| }W n tk
rL   dS X |r^t j|p`d}d}|ryt	| \}}W n t
k
r   Y nX Y nX |j}|j}t|tst||fS )zx Return source location (path, lineno) for the given object.
    If the source cannot be determined return ("", -1)
    )r3   r   Nr   )r   codeZCode	TypeErrorinspectZgetsourcefileZgetfilerL   rM   
findsourceIOErrorZfirstlinenor   r&   AssertionError)objro   rb   fspathr9   _r   r   r   getfslineno   s&    
rx   c             C   sT   yt | \}}W n" tjjk
r,    Y n
   dS t }dd |D |_||fS )N)Nr   c             S   s   g | ]}|  qS r   )r   )r
   r5   r   r   r   r     s    zfindsource.<locals>.<listcomp>)rq   rr   r   r   Z_sysexr   r   )ru   Zsourcelinesr9   r2   r   r   r   rr      s    rr   c             K   sN   t j| } yt| }W n tk
r2   d}Y nX t|tsBtt	|f|S )Nz<"Buggy python version consider upgrading, cannot get source")
r   ro   Z
getrawcoderq   r   IndentationErrorr   r"   rt   r   )ru   r   Zstrsrcr   r   r   r     s    
r   c       
   	      sH  |d kr@x6| D ]*}|  }| }|rt|t| }P qW d}|dkrPt| S g }dd }||  yxt fddD ]\}}\}}\}}}|t| krP |t|kr| |d    }| r|d |  r||d  }|| x t||D ]}	|| |	  qW qzW W n t	tj
fk
r,   Y nX || t|d   |S )Nr   c             s   s(   x| D ]}|d V  qW x
dV  qW d S )Nr	   r3   r   )r   r5   r   r   r   readline_generator  s    
z$deindent.<locals>.readline_generatorc                  s   t  S )N)nextr   )itr   r   rA   $  s    zdeindent.<locals>.<lambda>r%   )
expandtabslstripr.   r   tokenizegenerate_tokensisspacerX   rangery   
TokenErrorr   )
r   r>   r5   rm   newlinesrz   rw   ZslineZelineir   )r|   r   r     s8    
*
r   c       
      C   s   dd l }g }xp||D ]b}t|tjs4t|tjr||jd  x4dD ],}t||d }|rJ||d jd d  qJW qW |	  t
|| }||d  }|t|krd }	n|| }	||	fS )Nr   r%   )Z	finalbodyZorelse)r=   walkr   rk   ZstmtZExceptHandlerrX   r9   getattrsortr   r.   )
r9   Znoder=   lr   namevalZinsert_indexr*   r0   r   r   r   get_statement_startend28  s     
 
r   Fc       
   	      s^  |d krNt |}yt|ddd}W n* tk
rL   t| ||\}}d ||fS X t| |\}}|d krnt|j}||d krt }|j| d 	 |_
dd |j|| D  y*x$t fdd	D ]}|j|  qW W n: tjtfk
r    |j| }Y n tk
r   Y nX x<|rR|j|d   }	|	d
sB|	sL|d8 }nP qW |||fS )Nr2   r?   i   r%   r   c             s   s   | ]}|d  V  qdS )r	   Nr   )r
   r   r   r   r   	<genexpr>e  s    z(getstatementrange_ast.<locals>.<genexpr>c                  s   t  S )N)r{   r   )r|   r   r   rA   g  s    z'getstatementrange_ast.<locals>.<lambda>#)r"   r@   
ValueErrorgetstatementrange_oldr   r.   r   rq   ZBlockFinderr   Zstartedr   r   Z
tokeneaterZ
EndOfBlockry   ZlastrE   r~   
startswith)
r9   r2   r:   ZastnodeZcontentr*   r0   Zblock_findertokr5   r   )r|   r   r<   O  s6    

r<   c       	      C   s  ddl m} xt| ddD ]}|r^|j| }d|krLd|krLd|krLtdd|kr^d	|kr^q|j|| d
  }|dd d|}y|| W n ttt	fk
r   wY nX x:t| d
 t
|d
 D ] }||| }| r||fS qW qW td| f dS )z return (start, end) tuple which spans the minimal
        statement region which containing the given lineno.
        raise an IndexError if no such statementrange can be found.
    r   )compile_commandr   superr   r    zlikely a subclassassertraiser%   z
def xxx():z
 z%no valid source range around line %d N)Zcodeopr   r   r   r(   insertrG   rV   OverflowErrorr   r.   rF   )	r9   r2   r:   r   r*   r5   ZtrylinesZ	trysourcer0   r   r   r   r   x  s(    

r   )N)FN)F)Z
__future__r   Zbisectr   rN   rq   r   r   typesr   r@   rU   rk   r   rZ   rC   objectr   rj   rn   rx   rr   r   r   r   r<   r   r   r   r   r   <module>   s.   
 ;	
*
)