U
    \ShbS                     @  sR  d 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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 ddlmZ ed	Zed
Ze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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.    )annotationsN)	Signature)DEDENTINDENTNAMENEWLINENUMBEROPSTRING)COMMENTNL)Any)unparsez^\s*#: ?(.*)?
?$z^\s*$z^\s*(#.*)?$str)codereturnc                 C  s   |  ddS )N )replace)r    r   G/root/rtd-docs/venv/lib/python3.8/site-packages/sphinx/pycode/parser.pyfilter_whitespace   s    r   ast.ASTlist[ast.expr]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)
isinstanceastAssigntargetstarget)r   r   r   r   get_assign_targets   s    r!   ast.arg | None	list[str])r   selfr   c              	   C  s  |r
|j }| jj}|dkr&td|  |dkrV|dks@| j|krH| jgS td|  n|dkrg }| jD ].}z|t|| W qh tk
r   Y qhX qh|S |dkr| jjjdkr|r| jj|krdt| j	|d	  gS td|  n0|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)TupleList	Attributez%sr   r   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   r6   "   s>    	


r6   )sr   c                 C  s:   dddd}| |_ t|}|r2|ddS dS dS )z1Remove common leading indentation from docstring.Noner   c                   S  s   d S Nr   r   r   r   r   dummyQ   s    zdedent_docstring.<locals>.dummyz
 N)__doc__inspectgetdoclstriprstrip)r<   r@   	docstringr   r   r   dedent_docstringO   s    
rH   c                   @  sV   e Zd ZdZddddddddd	Zdd
dddZdd
dddZddddZdS )Tokenz)Better token wrapper for tokenize module.intr   ztuple[int, int]r   r=   )kindr7   startendsourcer   c                 C  s"   || _ || _|| _|| _|| _d S r?   )rK   r7   rL   rM   rN   )r$   rK   r7   rL   rM   rN   r   r   r   __init__`   s
    zToken.__init__bool)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   rJ   rK   r   r7   listtuple
ValueError)r$   rQ   r   r   r   __eq__h   s    



zToken.__eq__)
conditionsr   c                   s   t  fdd|D S )Nc                 3  s   | ]} |kV  qd S r?   r   ).0	candidater$   r   r   	<genexpr>u   s     zToken.match.<locals>.<genexpr>)any)r$   rV   r   rY   r   matcht   s    zToken.matchr>   c                 C  s    dt j| j d| j dS )Nz<Token kind=z value=>)tokenizetok_namerK   r7   striprY   r   r   r   __repr__w   s    zToken.__repr__N)r1   
__module____qualname__rB   rO   rU   r\   ra   r   r   r   r   rI   ]   s
   rI   c                   @  sJ   e Zd ZdddddZdddd	d
ZddddZdddddZdS )TokenProcessorr#   r=   )buffersr   c                   s2   t | || _t fdd| _d | _d | _d S )Nc                     s   t  S r?   )nextr   linesr   r   <lambda>       z)TokenProcessor.__init__.<locals>.<lambda>)iterre   r^   generate_tokenstokenscurrentprevious)r$   re   r   rg   r   rO   |   s
    zTokenProcessor.__init__rJ   r   linenor   c                 C  s   | j |d  S zReturns specified line.   re   r$   rq   r   r   r   get_line   s    zTokenProcessor.get_linezToken | Noner>   c                 C  s>   z| 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)rn   ro   rI   rf   rm   StopIterationrY   r   r   r   fetch_token   s    zTokenProcessor.fetch_tokenr   list[Token | None])	conditionr   c                 C  s   g }|   r|| j | j|kr$q| jtdgkrF|| tdg7 }q| jtdgkrh|| tdg7 }q| jtdgkr|| tdg7 }q|S )zlFetch tokens until specified token appeared.

        .. note:: This also handles parenthesis well.
        (){}[])rx   appendrn   r	   fetch_until)r$   rz   rm   r   r   r   r      s    
zTokenProcessor.fetch_untilN)r1   rb   rc   rO   rv   rx   r   r   r   r   r   rd   {   s   rd   c                      sD   e Zd ZdZddd fddZd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.
    r#   r=   rh   r   c                   s   t  | d | _d S r?   )superrO   commentr$   rh   r0   r   r   rO      s    zAfterCommentParser.__init__ry   r>   c                 C  s   g }|   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rqq| jr| jjttt	t
hkrqq|S )z%Fetch right-hand value of assignment.r{   r|   r}   r~   r   r   ;)rx   r   rn   r	   r   r   r   rK   r   r   r
   )r$   rm   r   r   r   fetch_rvalue   s     
zAfterCommentParser.fetch_rvaluec                 C  sX   |    }r*|tdgtts*| js tq | jtdgkr@|   | jtkrT| jj| _	dS )z3Parse the code and obtain comment after assignment.=N)
rx   r\   r	   r   r   rn   AssertionErrorr   r7   r   )r$   tokr   r   r   parse   s    
zAfterCommentParser.parse)r1   rb   rc   rB   rO   r   r   __classcell__r   r   r   r   r      s   r   c                      sp  e Zd ZdZdddd fd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ZddddddZ	ddddddZ
dddddZdddd d!Zd"d#d$d%Zd&dd'd(d)Zddd* fd+d,Zd-dd*d.d/Zd0dd*d1d2Zd3dd*d4d5Zd6dd*d7d8Zd9dd*d:d;Zd<dd*d=d>Zd?dd*d@dAZddd*dBdCZdDdd*dEdFZ  ZS )GVariableCommentPickerz7Python source code parser to pick up variable comments.r#   r   r=   )re   encodingr   c                   sl   t  | _|| _|| _g | _g | _d | _i | _i | _	d | _
i | _g | _i | _d | _d | _d | _t   d S r?   )	itertoolscountcounterre   r   contextcurrent_classescurrent_functioncommentsr   ro   	defordersfinals	overloadstypingtyping_finaltyping_overloadr   rO   )r$   re   r   r   r   r   rO      s     
zVariableCommentPicker.__init__zlist[str] | None)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).rO   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   rf   r   r   joinr$   r   qualnamer   r   r   	add_entry   s    
zVariableCommentPicker.add_entryc                 C  s$   |  |}|r | jd| d S r   )r   r   r   r   r   r   r   r   add_final_entry   s    
z%VariableCommentPicker.add_final_entryzast.FunctionDef)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   r   )r$   r   r   r   r   r   r   r   add_overload_entry   s
    z(VariableCommentPicker.add_overload_entry)r   r   r   c                 C  s2   |  |}|r.d|d d }|| j||f< d S Nr   r   )r   r   r   )r$   r   r   r   basenamer   r   r   add_variable_comment  s    
z*VariableCommentPicker.add_variable_commentr   )r   
annotationr   c                 C  s6   |  |}|r2d|d d }t|| j||f< d S r   )r   r   ast_unparser   )r$   r   r   r   r   r   r   r   add_variable_annotation  s    
z-VariableCommentPicker.add_variable_annotationr   rP   )
decoratorsr   c              	   C  sh   g }| j r|d| j   | jr,|| j |D ]2}zt||krJW  dS W q0 tk
r`   Y q0X q0dS )Nz%s.finalTF)r   r   r   r   r9   )r$   r   final	decoratorr   r   r   is_final  s    zVariableCommentPicker.is_finalc              	   C  sh   g }| j r|d| j   | jr,|| j |D ]2}zt||krJW  dS W q0 tk
r`   Y q0X q0dS )Nz%s.overloadTF)r   r   r   r   r9   )r$   r   overloadr   r   r   r   is_overload#  s    z!VariableCommentPicker.is_overloadr"   r>   c                 C  s@   | j r| j jjr| j jjd S | j r<| j jjr<| j jjd S dS )z8Returns the name of the first argument if in a function.r   N)r   argsposonlyargsrY   r   r   r   get_self3  s
    zVariableCommentPicker.get_selfrJ   rp   c                 C  s   | j |d  S rr   rt   ru   r   r   r   rv   ;  s    zVariableCommentPicker.get_liner   c                   s   t  | || _dS )z(Updates self.previous to the given node.N)r   visitro   r$   r   r   r   r   r   ?  s    zVariableCommentPicker.visitz
ast.Importc                 C  sn   |j D ]b}| |jp|j |jdkr6|jp0|j| _q|jdkrP|jpJ|j| _q|jdkr|jpd|j| _qdS )8Handles 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_ImportD  s    



z"VariableCommentPicker.visit_Importzast.ImportFromc                 C  sh   |j D ]\}| |jp|j |jdkr@|jdkr@|jp:|j| _q|jdkr|jdkr|jp^|j| _qdS )r   r   r   r   N)r   r   r   r   moduler   r   r   r   r   r   visit_ImportFromP  s    
z&VariableCommentPicker.visit_ImportFromz
ast.Assignc                   s  z0t |}t fdd|D g } |j}W n tk
rF   Y dS X t|drr|jrr|D ]} ||j q\n(t|dr|jr|D ]} ||j qt	||j
d g j|jd  }|  |jr
t|jr
|D ]$} |td|j  | qdS t|d|j
 rg }t|jd D ]@} |jd | }	t|	rj|td|	 n qtq2|rtdt|}
|D ]} ||
  | qdS |D ]} | qdS )	z3Handles Assign node and pick up a variable comment.c                   s   g | ]}t |  d qS )rY   )r6   r   )rW   trY   r   r   
<listcomp>_  s     z6VariableCommentPicker.visit_Assign.<locals>.<listcomp>Nr   type_commentz\1rs   
)r!   sumrv   rq   r2   hasattrr   r   r   r   
col_offsetre   r   r   
comment_rer\   r   subr   	indent_reranger   rH   r   reversed)r$   r   r   varnamescurrent_linevarnameparserZcomment_linesiZbefore_liner   r   rY   r   visit_AssignZ  sN     
z"VariableCommentPicker.visit_Assignzast.AnnAssignc                 C  s   |  | dS )z6Handles AnnAssign node and pick up a variable comment.N)r   r   r   r   r   visit_AnnAssign  s    z%VariableCommentPicker.visit_AnnAssignzast.Exprc                 C  s   t | jtjtjfrt |jtjrzpt| j}t|d | 	 }|D ]J}t |jj
tr`|jj
}n|jj
| jppd}| |t| | | qDW n tk
r   Y nX dS )z2Handles Expr node and pick up a comment if string.r   utf-8N)r   ro   r   r   	AnnAssignr7   r(   r!   r6   r   r<   r   decoder   r   rH   r   r2   )r$   r   r   r   r   rG   r   r   r   
visit_Expr  s    

z VariableCommentPicker.visit_Exprzast.Tryc                 C  s0   |j D ]}| | q|jD ]}| | q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_Tryzast.ClassDefc                 C  st   | j |j | |j | |jr2| |j | j|j || _|j	D ]}| 
| qL| j  | j   dS )z&Handles ClassDef node and set context.N)r   r   r   r   r   decorator_listr   r   ro   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 || _ |j
D ]}| | q^| j  d| _ dS )z)Handles FunctionDef node and set context.N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   visit_FunctionDef  s    



z'VariableCommentPicker.visit_FunctionDefzast.AsyncFunctionDefc                 C  s   |  | dS )z.Handles AsyncFunctionDef node and set context.N)r   r   r   r   r   visit_AsyncFunctionDef  s    z,VariableCommentPicker.visit_AsyncFunctionDef)r1   rb   rc   rB   rO   r   r   r   r   r   r   r   r   r   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s,   
2
r   c                      sf   e Zd ZdZddd fddZdddd	d
dZddddZdddddZddddZ  Z	S )DefinitionFinderzXPython source code parser to detect location of functions,
    classes and methods.
    r#   r=   r   c                   s(   t  | d | _g | _g | _i | _d S r?   )r   rO   r   r   indentsdefinitionsr   r   r   r   rO     s
    zDefinitionFinder.__init__r   ztuple[str, int, int])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_definitionr>   c                 C  s   |   }|dkrq|tkrq |tdgkrV| jdksD| jttttrV| j	dkr|| _	q |t
dgrp| d q |t
dgr| d q |tkr| jd q |tkr |   q dS )z1Parse the code to obtain location of definitions.N@classr   )rQ   NN)rx   r   r	   ro   r\   r   r   r   r   r   r   parse_definitionr   r   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:)rx   r   r   r7   r   r   rL   r   r	   r\   r   r   r   r   r   rM   r   )r$   r   r   funcname	start_posr   r   r   r     s    

z!DefinitionFinder.parse_definitionc                 C  sj   | j  }|d dkrf|\}}}| jjd d }t| |rJ|d8 }q0| ||||f | j  dS )zFinalize definition block.r   rQ   rs   N)	r   r   rn   rM   emptyline_rer\   rv   r   r   )r$   Z
definitionr   r   r   end_posr   r   r   r     s    


zDefinitionFinder.finalize_block)
r1   rb   rc   rB   rO   r   r   r   r   r   r   r   r   r   r     s   r   c                   @  sN   e Zd ZdZddd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``.
    r   r   r=   )r   r   r   c                 C  s8   t || _|| _i | _i | _i | _i | _g | _i | _d S r?   )	r   r   r   r   r   r   r   r   r   )r$   r   r   r   r   r   rO     s    
zParser.__init__r>   c                 C  s   |    |   dS )zParse the source code.N)parse_commentsr   rY   r   r   r   r   )  s    zParser.parsec                 C  sZ   t j| jdd}t| jd| j}|| |j| _|j| _|j	| _	|j
| _
|j| _dS )z$Parse the code and pick up comments.T)type_commentsN)r   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   9  s    zParser.parse_definitionN)r   )r1   rb   rc   rB   rO   r   r   r   r   r   r   r   r     s
   
r   )N)'rB   
__future__r   r   rC   r   rer^   r   r   r   r   r   r   r   r	   r
   r   r   r   r   Zsphinx.pycode.astr   r   compiler   r   r   r   r!   r6   rH   rI   rd   r   NodeVisitorr   r   r   r   r   r   r   <module>   s2   $


--- yL