B
    dR                 @   s~  d 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 ddlm	Z	m
Z
mZmZmZmZmZ ddlmZmZ ddlmZmZmZmZmZ ddlmZ dd	lmZmZ ed
ZedZedZe e dddZ!ej"eej# dddZ$d%ej"eej% ee  dddZ&e e dddZ'G dd dZ(G dd dZ)G dd de)Z*G dd  d ej+Z,G d!d" d"e)Z-G d#d$ d$Z.dS )&z,Utilities parsing and analyzing Python code.    N)OrderedDict)	Signature)DEDENTINDENTNAMENEWLINENUMBEROPSTRING)COMMENTNL)AnyDictListOptionalTuple)ast)parseunparsez^\s*#: ?(.*)?
?$z^\s*$z^\s*(#.*)?$)codereturnc             C   s   |  ddS )N )replace)r    r   a/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/sphinx/pycode/parser.pyfilter_whitespace   s    r   )noder   c             C   s   t | tjr| jS | jgS dS )z3Get list of targets from Assign and AnnAssign node.N)
isinstancer   Assigntargetstarget)r   r   r   r   get_assign_targets   s    r"   )r   selfr   c          	   C   s$  |r
|j }| jj}|dkr*td|   n|dkrZ|dksD| j|krL| jgS td|  n|dkrg }x8| jD ].}y|t|| W qn tk
r   Y qnX qnW |S |dkr| jjjdkr|r| jj|krdt| j	|d	  gS td|  n2|d
k r| gS |dkrt| j|S t
d| dS )zConvert assignment-AST to variable names.

    This raises `TypeError` if the assignment does not create new variable::

        ary[0] = 'foo'
        dic["bar"] = 'baz'
        # => TypeError
    )IndexNumSliceStr	Subscriptz%r does not create new variableNameNz*The assignment %r is not instance variable)r   r   	Attributez%sr   strStarredzUnexpected node name %r)arg	__class____name__	TypeErrorideltsextendget_lvar_namesvalueattrNotImplementedError)r   r#   Zself_idZ	node_namememberseltr   r   r   r4       s4    	


r4   )sr   c             C   s:   dddd}| |_ t|}|r2|ddS dS dS )z1Remove common leading indentation from docstring.N)r   c               S   s   d S )Nr   r   r   r   r   dummyL   s    zdedent_docstring.<locals>.dummyz
 )__doc__inspectgetdoclstriprstrip)r:   r;   	docstringr   r   r   dedent_docstringJ   s    
rC   c               @   sf   e Zd ZdZeeeeef eeef eddddZee	dddZ
ee	d	d
dZedddZdS )Tokenz)Better token wrapper for tokenize module.N)kindr5   startendsourcer   c             C   s"   || _ || _|| _|| _|| _d S )N)rE   r5   rF   rG   rH   )r#   rE   r5   rF   rG   rH   r   r   r   __init__[   s
    zToken.__init__)otherr   c             C   sf   t |tr| j|kS t |tr(| j|kS t |ttfrJ| j| jgt|kS |d krVdS td| d S )NFzUnknown value: %r)r   intrE   r+   r5   listtuple
ValueError)r#   rJ   r   r   r   __eq__c   s    



zToken.__eq__)
conditionsr   c                s   t  fdd|D S )Nc             3   s   | ]} |kV  qd S )Nr   ).0	candidate)r#   r   r   	<genexpr>p   s    zToken.match.<locals>.<genexpr>)any)r#   rP   r   )r#   r   matcho   s    zToken.match)r   c             C   s   dt j| j | j f S )Nz<Token kind=%r value=%r>)tokenizetok_namerE   r5   strip)r#   r   r   r   __repr__r   s    zToken.__repr__)r/   
__module____qualname__r=   rK   r   r   r+   rI   boolrO   rU   rY   r   r   r   r   rD   X   s   rD   c               @   sV   e Zd Zee ddddZeedddZee	 dd	d
Z
eee	 dddZdS )TokenProcessorN)buffersr   c                s2   t | || _t fdd| _d | _d | _d S )Nc                  s   t  S )N)nextr   )linesr   r   <lambda>{       z)TokenProcessor.__init__.<locals>.<lambda>)iterr^   rV   generate_tokenstokenscurrentprevious)r#   r^   r   )r`   r   rI   x   s
    zTokenProcessor.__init__)linenor   c             C   s   | j |d  S )zReturns specified line.   )r^   )r#   rh   r   r   r   get_line   s    zTokenProcessor.get_line)r   c             C   s>   y| j | _tt| j | _ W n tk
r6   d| _ Y nX | j S )z_Fetch the next token from source code.

        Returns ``None`` if sequence finished.
        N)rf   rg   rD   r_   re   StopIteration)r#   r   r   r   fetch_token   s    zTokenProcessor.fetch_token)	conditionr   c             C   s   g }x|   r|| j | j|kr(P q| jtdgkrJ|| tdg7 }q| jtdgkrl|| tdg7 }q| jtdgkr|| tdg7 }qW |S )zlFetch tokens until specified token appeared.

        .. note:: This also handles parenthesis well.
        (){}[])rl   appendrf   r	   fetch_until)r#   rm   re   r   r   r   ru      s    

zTokenProcessor.fetch_until)r/   rZ   r[   r   r+   rI   rK   rj   r   rD   rl   r   ru   r   r   r   r   r]   w   s   r]   c                   sL   e Zd ZdZee dd fddZee dddZddd	d
Z	  Z
S )AfterCommentParserzPython source code parser to pick up comments after assignments.

    This parser takes code which starts with an assignment statement,
    and returns the comment for the variable if one exists.
    N)r`   r   c                s   t  | d | _d S )N)superrI   comment)r#   r`   )r.   r   r   rI      s    zAfterCommentParser.__init__)r   c             C   s   g }x|   r|| j | jtdgkr<|| tdg7 }q| jtdgkr^|| tdg7 }q| jtdgkr|| tdg7 }q| jtkr|| t7 }q| jtdgkrP q| jjttt	t
fkrP qW |S )z%Fetch right-hand value of assignment.rn   ro   rp   rq   rr   rs   ;)rl   rt   rf   r	   ru   r   r   rE   r   r   r
   )r#   re   r   r   r   fetch_rvalue   s     

zAfterCommentParser.fetch_rvaluec             C   sT   x$|   tdgtts$| jstqW | jtdgkr<|   | jtkrP| jj| _	dS )z3Parse the code and obtain comment after assignment.=N)
rl   rU   r	   r   r   rf   AssertionErrorrz   r5   rx   )r#   r   r   r   r      s    
zAfterCommentParser.parse)r/   rZ   r[   r=   r   r+   rI   rD   rz   r   __classcell__r   r   )r.   r   rv      s   rv   c                   s  e Zd ZdZee edd fddZeeee  dddZeddd	d
Z	eddddZ
ejddddZeeddddZeejddddZeej edddZeej edddZeej dddZeeddd Zejdd! fd"d#Zejdd!d$d%Zejdd!d&d'Zejdd!d(d)Zej dd!d*d+Z!ej"dd!d,d-Z#ej$dd!d.d/Z%ej&dd!d0d1Z'ejdd!d2d3Z(ej)dd!d4d5Z*  Z+S )6VariableCommentPickerz7Python source code parser to pick up variable comments.N)r^   encodingr   c                sn   t  | _|| _|| _g | _g | _d | _t | _	i | _
d | _i | _g | _i | _d | _d | _d | _t   d S )N)	itertoolscountcounterr^   r   contextcurrent_classescurrent_functionr   commentsannotationsrg   	defordersfinals	overloadstypingtyping_finaltyping_overloadrw   rI   )r#   r^   r   )r.   r   r   rI      s     
zVariableCommentPicker.__init__)namer   c             C   sD   | j r4| jr.| jd dkr.| jdd |g S dS n| j|g S dS )z;Get qualified name for given object as a list of string(s).rI   N)r   r   r   )r#   r   r   r   r   get_qualname_for   s
    z&VariableCommentPicker.get_qualname_forc             C   s(   |  |}|r$t| j| jd|< d S )N.)r   r_   r   r   join)r#   r   qualnamer   r   r   	add_entry   s    
zVariableCommentPicker.add_entryc             C   s$   |  |}|r | jd| d S )Nr   )r   r   rt   r   )r#   r   r   r   r   r   add_final_entry   s    
z%VariableCommentPicker.add_final_entry)funcr   c             C   sB   ddl m} | |j}|r>| jd|g }||| d S )Nr   )signature_from_astr   )Zsphinx.util.inspectr   r   r   r   
setdefaultr   rt   )r#   r   r   r   r   r   r   r   add_overload_entry   s
    z(VariableCommentPicker.add_overload_entry)r   rx   r   c             C   s2   |  |}|r.d|d d }|| j||f< d S )Nr   r   )r   r   r   )r#   r   rx   r   basenamer   r   r   add_variable_comment  s    
z*VariableCommentPicker.add_variable_comment)r   
annotationr   c             C   s6   |  |}|r2d|d d }t|| j||f< d S )Nr   r   )r   r   r   r   )r#   r   r   r   r   r   r   r   add_variable_annotation	  s    
z-VariableCommentPicker.add_variable_annotation)
decoratorsr   c          	   C   sh   g }| j r|d| j   | jr,|| j x6|D ].}yt||krHdS W q2 tk
r^   Y q2X q2W dS )Nz%s.finalTF)r   rt   r   r   r7   )r#   r   final	decoratorr   r   r   is_final  s    

zVariableCommentPicker.is_finalc          	   C   sh   g }| j r|d| j   | jr,|| j x6|D ].}yt||krHdS W q2 tk
r^   Y q2X q2W dS )Nz%s.overloadTF)r   rt   r   r   r7   )r#   r   overloadr   r   r   r   is_overload  s    

z!VariableCommentPicker.is_overload)r   c             C   sJ   | j r| j jjr| j jjd S | j rBt| j jddrB| j jjd S dS dS )z8Returns the name of the first argument if in a function.r   posonlyargsN)r   argsgetattrr   )r#   r   r   r   get_self/  s    zVariableCommentPicker.get_self)rh   r   c             C   s   | j |d  S )zReturns specified line.ri   )r^   )r#   rh   r   r   r   rj   :  s    zVariableCommentPicker.get_line)r   r   c                s   t  | || _dS )z(Updates self.previous to the given node.N)rw   visitrg   )r#   r   )r.   r   r   r   >  s    zVariableCommentPicker.visitc             C   sr   xl|j D ]b}| |jp|j |jdkr8|jp2|j| _q|jdkrR|jpL|j| _q|jdkr|jpf|j| _qW dS )z8Handles Import node and record the order of definitions.r   ztyping.finalztyping.overloadN)namesr   asnamer   r   r   r   )r#   r   r   r   r   r   visit_ImportC  s    


z"VariableCommentPicker.visit_Importc             C   sl   xf|j D ]\}| |jp|j |jdkrB|jdkrB|jp<|j| _q|jdkr|jdkr|jp`|j| _qW dS )z8Handles Import node and record the order of definitions.r   r   r   N)r   r   r   r   moduler   r   )r#   r   r   r   r   r   visit_ImportFromO  s    z&VariableCommentPicker.visit_ImportFromc                s  y0t |}t fdd|D g } |j}W n tk
rD   dS X t|drt|jrtxH|D ]} ||j q\W n,t|dr|jrx|D ]} ||j qW t	||j
d g j|jd  }|  |jrt|jrx,|D ]$} |td|j  | qW dS t|d|j
 rg }xNt|jd D ]<} |jd | }	t|	rv|td|	 nP q>W |rtdt|}
x$|D ]} ||
  | qW dS x|D ]} | qW dS )	z3Handles Assign node and pick up a variable comment.c                s   g | ]}t |  d qS ))r#   )r4   r   )rQ   t)r#   r   r   
<listcomp>]  s    z6VariableCommentPicker.visit_Assign.<locals>.<listcomp>Nr   type_commentz\1ri   
)r"   sumrj   rh   r0   hasattrr   r   r   rv   
col_offsetr^   r   rx   
comment_rerU   r   subr   	indent_rerangert   rC   r   reversed)r#   r   r    varnamescurrent_linevarnameparserZcomment_linesiZbefore_linerx   r   )r#   r   visit_AssignY  sF    




z"VariableCommentPicker.visit_Assignc             C   s   |  | dS )z6Handles AnnAssign node and pick up a variable comment.N)r   )r#   r   r   r   r   visit_AnnAssign  s    z%VariableCommentPicker.visit_AnnAssignc             C   s   t | jtjtjfrt |jtjrytt| j}t|d | 	 }xR|D ]J}t |jj
trb|jj
}n|jj
| jprd}| |t| | | qFW W n tk
r   Y nX dS )z2Handles Expr node and pick up a comment if string.r   zutf-8N)r   rg   r   r   	AnnAssignr5   r'   r"   r4   r   r:   r+   decoder   r   rC   r   r0   )r#   r   r    r   r   rB   r   r   r   
visit_Expr  s    


z VariableCommentPicker.visit_Exprc             C   s8   x|j D ]}| | qW x|jD ]}| | q"W dS )zHandles Try node and processes body and else-clause.

        .. note:: pycode parser ignores objects definition in except-clause.
        N)bodyr   Zorelse)r#   r   Zsubnoder   r   r   	visit_Try  s    zVariableCommentPicker.visit_Tryc             C   sx   | j |j | |j | |jr2| |j | j|j || _x|j	D ]}| 
| qNW | j  | j   dS )z&Handles ClassDef node and set context.N)r   rt   r   r   r   decorator_listr   r   rg   r   r   pop)r#   r   childr   r   r   visit_ClassDef  s    
z$VariableCommentPicker.visit_ClassDefc             C   s   | j dkr| |j | |jr.| |j | |jrD| | | j	|j || _ x|j
D ]}| | q`W | j  d| _ dS )z)Handles FunctionDef node and set context.N)r   r   r   r   r   r   r   r   r   rt   r   r   r   )r#   r   r   r   r   r   visit_FunctionDef  s    


z'VariableCommentPicker.visit_FunctionDefc             C   s   |  | dS )z.Handles AsyncFunctionDef node and set context.N)r   )r#   r   r   r   r   visit_AsyncFunctionDef  s    z,VariableCommentPicker.visit_AsyncFunctionDef),r/   rZ   r[   r=   r   r+   rI   r   r   r   r   r   FunctionDefr   r   ASTr   exprr\   r   r   r-   r   rK   rj   r   Importr   
ImportFromr   r   r   r   r   Exprr   Tryr   ClassDefr   r   AsyncFunctionDefr   r}   r   r   )r.   r   r~      s,   
0
r~   c                   st   e Zd ZdZee dd fddZeeeeef ddddZ	dd	d
dZ
eddddZdd	ddZ  ZS )DefinitionFinderzXPython source code parser to detect location of functions,
    classes and methods.
    N)r`   r   c                s(   t  | d | _g | _g | _i | _d S )N)rw   rI   r   r   indentsdefinitions)r#   r`   )r.   r   r   rI     s
    zDefinitionFinder.__init__)r   entryr   c             C   s4   | j r&| j d d dkr&|d dkr&n
|| j|< dS )zAdd a location of definition.r   r   defN)r   r   )r#   r   r   r   r   r   add_definition  s    $zDefinitionFinder.add_definition)r   c             C   s   x|   }|dkrP q|tkr q|tdgkrZ| jdksH| jttttrZ| j	dkr|| _	q|t
dgrt| d q|t
dgr| d q|tkr| jd q|tkr|   qW dS )z1Parse the code to obtain location of definitions.N@classr   )rJ   NN)rl   r   r	   rg   rU   r   r   r   r   r   r   parse_definitionr   rt   finalize_block)r#   tokenr   r   r   r     s$    
zDefinitionFinder.parse)typr   c             C   s   |   }| j|j d| j}| jr<| jjd }d| _n
|jd }| tdg |   	t
tr| t | j|||f n"| ||||jd f | j  dS )zParse AST of definition.r   r   N:)rl   r   rt   r5   r   r   rF   ru   r	   rU   r   r   r   r   r   rG   r   )r#   r   r   funcname	start_posr   r   r   r     s    

z!DefinitionFinder.parse_definitionc             C   sn   | j  }|d dkrj|\}}}| jjd d }xt| |rL|d8 }q2W | ||||f | j  dS )zFinalize definition block.r   rJ   ri   N)	r   r   rf   rG   emptyline_rerU   rj   r   r   )r#   Z
definitionr   r   r   end_posr   r   r   r     s    

zDefinitionFinder.finalize_block)r/   rZ   r[   r=   r   r+   rI   r   rK   r   r   r   r   r}   r   r   )r.   r   r     s   r   c               @   sN   e Zd ZdZdeeddddZdddd	Zddd
dZddddZdS )ParserzyPython source code parser to pick up variable comments.

    This is a better wrapper for ``VariableCommentPicker``.
    utf-8N)r   r   r   c             C   s8   t || _|| _i | _i | _i | _i | _g | _i | _d S )N)	r   r   r   r   r   r   r   r   r   )r#   r   r   r   r   r   rI     s    
zParser.__init__)r   c             C   s   |    |   dS )zParse the source code.N)parse_commentsr   )r#   r   r   r   r   %  s    zParser.parsec             C   sT   t | j}t| jd| j}|| |j| _|j| _|j| _|j	| _	|j
| _
dS )z$Parse the code and pick up comments.TN)r   r   r~   
splitlinesr   r   r   r   r   r   r   )r#   treeZpickerr   r   r   r   *  s    

zParser.parse_commentsc             C   s$   t | jd}|  |j| _dS )z0Parse the location of definitions from the code.TN)r   r   r   r   r   )r#   r   r   r   r   r   5  s    zParser.parse_definition)r   )	r/   rZ   r[   r=   r+   rI   r   r   r   r   r   r   r   r     s
   
r   )N)/r=   r>   r   rerV   collectionsr   r   r   r   r   r   r   r   r	   r
   r   r   r   r   r   r   r   r   Zsphinx.pycode.astr   r   r   compiler   r   r   r+   r   r   r   r"   r-   r4   rC   rD   r]   rv   NodeVisitorr~   r   r   r   r   r   r   <module>   s2   $


 *-- zK