
MV]c           @   sp  d  Z  d d l Z d d l Z d d l m Z d d l Z d d l m Z d d l m	 Z	 d d l
 m Z d d l m Z d d l m Z e j e  Z e Z d! Z d   Z d   Z d   Z d   Z d   Z d   Z d d  Z d   Z d   Z d   Z d   Z  d e! f d     YZ" d   Z# d e$ f d     YZ% d e$ f d     YZ& d e$ f d      YZ' d S("   s   
Basically a contains parser that is faster, because it tries to parse only
parts and if anything changes, it only reparses the changed parts.

It works with a simple diff in the beginning and will try to reuse old parser
fragments.
iN(   t
   namedtuple(   t   split_lines(   t   Parser(   t	   EndMarker(   t   PythonToken(   t   PythonTokenTypest   INDENTt   ERROR_DEDENTt   DEDENTc         C   s;   x4 |  r6 |  j  d k r6 |  j t k r6 |  j   }  q W|  S(   Nt
   error_leaf(   t   typet
   token_typet   _INDENTATION_TOKENSt   get_previous_leaf(   t   leaf(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt!   _get_previous_leaf_if_indentation   s    c         C   s;   x4 |  r6 |  j  d k r6 |  j t k r6 |  j   }  q W|  S(   NR	   (   R
   R   R   R   (   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _get_next_leaf_if_indentation    s    c   	      C   s  y |  j  } WnWt k
 rf|  j d k r_ |  j t k r_ |  j sK t  |  j s[ t  d St |  j	    } | d k r |  j } d } n= | j |  j k s t | |  f   | j |  j } | j } d | k s d | k r!t |  } | d t |  d } | t | d  f } n | d | d t |  f } |  j | k st |  j | f   n= Xx9 | D]1 } | j |  k st |  | f   t |  qnWd S(	   s~   
    Checks if the parent/children relationship is correct.

    This is a check that only runs during debugging/testing.
    R	   Ni   i    s   
s   i(   i   i    (   t   childrent   AttributeErrorR
   R   R   t   valuet   AssertionErrort   prefixR   R   t   Nonet   end_post	   start_posR   t   lent   parentt   _assert_valid_graph(	   t   nodeR   t   previous_leaft   contentt   previous_start_post   splittedt   linet   actualt   child(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   '   s0    			(!c         C   sn   t  |  j   d t } t j | |  } t j | |  } d d  l } d | j d j |  d j |  f S(   Nt   keependsism   There's an issue with the diff parser. Please report (parso v%s) - Old/New:
%s
Actual Diff (May be empty):
%st    (   R   t   get_codet   Truet   difflibt   unified_difft   parsot   __version__t   join(   t   modulet	   old_linest	   new_linest   current_linest   current_difft   old_new_diffR*   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _get_debug_error_messageQ   s    c         C   s2   |  j    } t |  r# | j d S| j d Sd  S(   Ni    (   t   get_last_leaft   _ends_with_newlineR   R   (   t   node_or_leaft	   last_leaf(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _get_last_line]   s    c         C   sA   x: |  d  k	 r< |  j d k r< |  j d k r< |  j   }  q W|  S(   NR	   R   (   R   R
   R   R   (   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _skip_dedent_error_leavese   s    -R%   c         C   s^   t  |   }  |  j d k r- |  j j   } n	 |  j } | d k p] | j d  p] | j d  S(   NR	   t   newlines   
s   (   R9   R
   R   t   lowert   endswith(   R   t   suffixt   typ(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR5   k   s
    	c         C   s(   x! | D] } | j  d k r t Sq Wt S(   sg   
    if, while, for and try might not be finished, because another part might
    still be parsed.
    t   if_stmtt
   while_stmtt   for_stmtt   try_stmt(   R?   R@   RA   RB   (   t   nonterminalt   FalseR'   (   t   pgen_grammart   stackt
   stack_node(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _flows_finishedv   s    c         C   sa   |  j  d k r |  j d }  n  |  j  d k r> |  j d }  n  |  j  d	 k o` |  j d j  d k S(
   Nt	   decoratedit   async_funcdeft
   async_stmtt   classdeft   funcdeft   suite(   RJ   RK   (   RL   RM   (   R
   R   (   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _func_or_class_has_suite   s
    c         C   sc   t  |  |  s t SxI t |  D]; } | j d k r9 t S| j d k r  t | j  d k Sq  Wt S(   Nt	   decoratorRN   i   (   RH   RD   t   reversedRC   R   t   nodesR'   (   RE   RF   RG   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _suite_or_file_input_is_valid   s    c         C   sR   |  j  d k r |  j d }  n  y |  j d j } Wn t k
 rG t SX| d	 k S(
   NRK   i   i    t   ift   fort   whilet   tryt   with(   RT   RU   RV   RW   RX   (   R
   R   R   R   RD   (   R   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _is_flow_node   s    t   _PositionUpdatingFinishedc           B   s   e  Z RS(    (   t   __name__t
   __module__(    (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRZ      s   c         C   sj   xc |  D][ } y | j  } Wn5 t k
 rQ | j | 7_ | | k rb t  qb q Xt | | |  q Wd  S(   N(   R   R   R!   RZ   t   _update_positions(   RR   t   line_offsetR7   R   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR]      s    t
   DiffParserc           B   sb   e  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z	 d   Z
 d	 d
  Z RS(   s   
    An advanced form of parsing a file faster. Unfortunately comes with huge
    side effects. It changes the given module.
    c         C   s   | |  _  | |  _ | |  _ d  S(   N(   t   _pgen_grammart
   _tokenizert   _module(   t   selfRE   t	   tokenizerR-   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   __init__   s    		c         C   s(   d |  _  d |  _ t |  j  |  _ d  S(   Ni    (   t   _copy_countt   _parser_countt
   _NodesTreeRb   t   _nodes_tree(   Rc   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _reset   s    		c         C   s4  t  j d  d |  j _ | |  _ |  j   t |  } t j	 d | |  j  } | j
   } t  j d t |  | f  x | D] \ } } } }	 }
 t  j d | | d | |	 d |
  |
 | k r | d d k r |
 d 8}
 n  | d k r|	 | } |  j | | |
  q | d k r-|  j d	 |
  q | d
 k rL|  j d	 |
  q | d k s t  q W|  j j   t ry5 |  j j   d j |  k st  t |  j  Wqt k
 rt |  j | |  GH  qXn  |  j j d } | | k r t d | | f t |  j | |    n  t  j d  |  j S(   s  
        The algorithm works as follows:

        Equal:
            - Assure that the start is a newline, otherwise parse until we get
              one.
            - Copy from parsed_until_line + 1 to max(i2 + 1)
            - Make sure that the indentation is correct (e.g. add DEDENT)
            - Add old and change positions
        Insert:
            - Parse from parsed_until_line + 1 to min(j2 + 1), hopefully not
              much more.

        Returns the new module node.
        s   diff parser starts   line_lengths old: %s; new: %ss!   -> code[%s] old[%s:%s] new[%s:%s]i   iR%   t   equalt   replacet
   until_linet   insertt   deletei    s   (%s != %s) s   diff parser endN(   t   LOGt   debugR   Rb   t   _used_namest   _parser_lines_newRj   R   R(   t   SequenceMatchert   get_opcodest   _copy_from_old_parsert   _parseR   Ri   t   closet   DEBUG_DIFF_PARSERR&   R,   R   R3   R   t	   Exception(   Rc   R.   R/   t   line_lengtht   smt   opcodest	   operationt   i1t   i2t   j1t   j2R^   t   last_pos(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   update   sH    	
	
$
c         C   sJ   |  j  j   d j |  k rF t j d d j |  d j |   n  d  S(   NR%   s   parser issue:
%s
%s(   Rb   R&   R,   Rp   t   warning(   Rc   R.   t	   lines_new(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _enabled_debugging  s    c         C   sK  d } x>| |  j  j k rF|  j  j | } |  j | d  } | d  k rd |  j |  j  j d  n | j j } | j |  } |  j  j d }	 |  j  j | | | |  }
 |
 r|  j	 d 7_	 |  j  j } t
 j d |
 d j d |
 d j d d |	 |  n |  j |  j  j d  | |  j  j k s7t |   |  j  j } q	 Wd  S(   Nii   s   copy old[%s:%s] new[%s:%s]i    (   Ri   t   parsed_until_linet   _get_old_line_stmtR   Rw   R   R   t   indext
   copy_nodesRf   Rp   Rq   R   R   R   (   Rc   R^   t   until_line_oldt   until_line_newt   last_until_linet   parsed_until_line_oldt	   line_stmtt
   p_childrenR   t   from_t   copied_nodest   to(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRv     s,    			c         C   s   |  j  j | d f d t } t |  r9 | j   } n  | j   d | k r | } x | j j d k rv | j } qX W| j d | k r | Sn  d  S(   Ni    t   include_prefixest
   file_inputRN   (   R   RN   (
   Rb   t   get_leaf_for_positionR'   R5   t   get_next_leaft   get_start_pos_of_prefixR   R
   R   R   (   Rc   t   old_lineR   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   5  s    c         C   s   d } x | |  j  j k r |  j |  } | j } |  j  j |  t j d | d j   d |  j  j | j d d  | |  j  j k s t	 |   |  j  j } q	 Wd S(   sy   
        Parses at least until the given line, but might just parse more until a
        valid state is reached.
        i    s/   parse_part from %s to %s (to %s in part parser)i   N(
   Ri   R   t   _try_parse_partR   t   add_parsed_nodesRp   Rq   R   R   R   (   Rc   Rm   R   R   RR   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRw   F  s    		c         C   sk   |  j  d 7_  |  j j } |  j | } |  j | | d | } t |  j d t |  _ |  j j	 d |  S(   s   
        Sets up a normal parser that uses a spezialized tokenizer to only parse
        until a certain position (or a bit longer if the statement hasn't
        ended.
        i   R^   t   error_recoveryt   tokens(
   Rg   Ri   R   Rs   t   _diff_tokenizeR   R`   R'   t   _active_parsert   parse(   Rc   Rm   R   t   lines_afterR   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   ]  s    		i    c         c   s  t  } t } g  } |  j | d  } |  j j } xM| D]E\ }	 }
 } } | d | | d f } |	 t j k r | j | d  | r t  } t } q7 q n  t } |	 t j k s |	 t j	 k r| rt
 |  d k r| j   | rh| rht |  \ }	 }
 } } d | k sd | k r7t j d d |  } nK | d t
 |  k s_t t |    | d t
 |  d k rd } n  t t j d | d | d f |  VPqhn |	 t j k rh| d | k rht |	 |
 | |  Vt |  j |  r7 | d d d f } x= t
 |  t |  k rF| j   t t j d | d  Vq
Wt t j d | d  VPqhq7 n  t |	 |
 | |  Vq7 Wd  S(   Ni   i    s   
s   s
   [^\n\r]+\ZR%   (   i   i    (   R'   RD   Ra   R   RF   R   R   t   appendR   R   R   t   popt   nextt   ret   subR   t   reprR   t	   ENDMARKERt   NEWLINERS   R`   t   int(   Rc   t   linesRm   R^   t   is_first_tokent   omitted_first_indentt   indentsR   RF   R>   t   stringR   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   s  sR    	
(		
(   R[   R\   t   __doc__Re   Rj   R   R   Rv   R   Rw   R   R   (    (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR_      s   			F		&			t   _NodesTreeNodec           B   sM   e  Z e d  d  Z d d  Z d   Z d   Z d d d  Z d   Z	 RS(	   t   _ChildrenGroups1   prefix children line_offset last_line_offset_leafc         C   s(   | |  _  g  |  _ | |  _ g  |  _ d  S(   N(   t	   tree_nodet   _children_groupsR   t   _node_children(   Rc   R   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRe     s    			c   	      C   s   g  } x |  j  D]y \ } } } } t | d j    } | | j | _ | d k r y t | | |  Wq t k
 r{ q Xn  | | 7} q W| |  j _ x | D] } |  j | _ q Wx |  j	 D] } | j
   q Wd  S(   Ni    (   R   R   t   get_first_leafR   R]   RZ   R   R   R   R   t   finish(	   Rc   R   R   t   children_partR^   t   last_line_offset_leaft
   first_leafR   t
   node_child(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR     s"    c         C   s   |  j  j |  d  S(   N(   R   R   (   Rc   t
   child_node(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   add_child_node  s    i    c         C   sK   | d  k r | d j   } n  |  j | | | |  } |  j j |  d  S(   Ni(   R   R4   R   R   R   (   Rc   R   R   R^   R   t   group(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   add_tree_nodes  s    c         C   s   d } |  j  r^ |  j  d } t | j  } | j d | j } t | |  r^ | d 8} q^ n  | t t |   d 7} | r | j d  r | j d  r | d 7} n  |  j	 r t
 | |  j	 d j |   S| S(   Ni    ii   s   
s   (   R   R   R   R   R^   R5   R   R   R<   R   t   maxt   get_last_line(   Rc   R=   R!   t   children_groupR7   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR     s    	&	N(
   R[   R\   R    R   R   Re   R   R   R   R   (    (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR     s   		Rh   c           B   sb   e  Z d    Z e d    Z d   Z d   Z d   Z d   Z d   Z	 d d  Z
 d	   Z RS(
   c         C   s=   t  |  |  _ |  j g |  _ | |  _ d |  _ d |  _ d  S(   NR%   (   R   t
   _base_nodet   _working_stackRb   t   _prefix_remainderR   (   Rc   R-   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRe     s
    		c         C   s   |  j  d j |  j  S(   Ni(   R   R   R   (   Rc   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR     s    c         C   s   | j  d } xv t r |  j d } | j } | j d k rb | j d j  d } | | k ru | Sn | j d k ru | S|  j j   q Wd  S(   Ni   iRN   R   (   R   R'   R   R   R
   R   R   (   Rc   t   indentation_nodet   indentationR   R   t   node_indentation(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   _get_insertion_node  s    		c         C   s   |  j  } |  j |  } | s2 | |  j  |  _  d  S| d j d k sK t  |  j | d  } | j j d k sv t  | j | |  |  j | d  d  S(   Ni    R:   RN   R   i(   RN   R   (   R   t   _remove_endmarkerR
   R   R   R   R   t   _update_tos(   Rc   t
   tree_nodest
   old_prefixR   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR     s    	c         C   s   | j  d k ro t |  } | j d t | j   |  j d j |  |  j j |  |  j | j d  n# t	 |  r |  j | j d  n  d  S(   NRN   R   R%   i(   RN   R   (
   R
   R   R   t   listR   R   R   R   R   RO   (   Rc   R   t   new_tos(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR      s    c         C   s   | d j    } | j d k } d |  _ | r t | j j d  | j j d   } | d k r | j | d  | j | d | _ |  _ q n  d |  _ | r | j |  _ | d  } n  | S(   sE   
        Helps cleaning up the tree nodes that get inserted.
        it	   endmarkerR%   s   
s   i   (   R4   R
   R   R   R   t   rfind(   Rc   R   R7   t   is_endmarkert
   separation(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   ,  s    	'/	c         C   sb   | d j  d k r g  S|  j | d  |  j t |  j  | | | |  j  \ } |  _ |  _ | S(   sy   
        Copies tree nodes from the old parser tree.

        Returns the number of tree nodes that were copied.
        i    R	   t
   error_node(   R	   R   (   R
   R   t   _copy_nodesR   R   R   (   Rc   R   Rm   R^   t	   new_nodes(    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   D  s    R%   c         C   s  g  } d } x | D] } | j  d | k r0 Pn  | j d k rC Pn  | j d k re | j d k re Pn  t |  | k r t |  r | j |  n  Pn  | j |  q W| s g  | | f S| d }	 | d }
 t } t |
  r|
 } x  | j d k r	| j d } q Wt |  } |  j	 | | g | j | |  \ } } } t
 |  d	 k  rf| j   d } q| srt  |	 j |  | } t } n  | r| d }
 |
 j d k st | d  rd } | j   x: | r| d }
 |
 j   j d k rPn  | j   qWqn  | rt | d j    r]| r]| d j   j } t | d t d } n  | r| d } | j d k r| j d } n  | j d k r| j d } n  | j d j   } | d k st  n | d j   } |	 j | | | |  | } d |  _ n  | | | f S(   NR%   i    R   R	   R   R   iRN   i   R   R:   R$   RI   RJ   RK   it   :(   R   R   (   R	   R   (   RJ   RK   (   R   R
   R   R8   RO   R   RD   R   R   R   R   R   R   R   R'   RY   R4   R5   R   R   R   R   R   (   Rc   t   working_stackRR   Rm   R^   R   R   t
   new_prefixR   t   tost	   last_nodet   had_valid_suite_lastRN   t	   suite_tost   suite_nodest   new_working_stackt   pt   lastR   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyR   Z  sz    

%
		

	

c         C   s$  |  j  j   y |  j j   } Wn t k
 r? d d g } n Xt |  } t | j  } t |  j	  } t
 |  d k s t  t
 |  d k r | d c t
 | d  7<n. | d c t
 |  d 7<t
 | d  | d <t d t |  |  j	 |  j  } |  j | _ |  j j j |  d  S(   Ni   i    iR%   (   R   R   Rb   R4   t
   IndexErrorR9   R   R   R   R   R   R   R   t   tupleR   R   R   R   (   Rc   R7   R   R   R   (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRx     s     "(   R[   R\   Re   t   propertyR   R   R   R   R   R   R   Rx   (    (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyRh     s   						_(   R   R   R   ((   R   R   R(   t   collectionsR    t   loggingt   parso.utilsR   t   parso.python.parserR   t   parso.python.treeR   t   parso.python.tokenizeR   t   parso.python.tokenR   t	   getLoggerR[   Rp   RD   Ry   R   R   R   R   R3   R8   R9   R5   RH   RO   RS   RY   Rz   RZ   R]   t   objectR_   R   Rh   (    (    (    s0   lib/python2.7/site-packages/parso/python/diff.pyt   <module>   s8   			*							
	B