o $aR@sdZddlZddlZddlZddlZddlmZddlmZddlm Z m Z m Z m Z m Z mZmZddlmZmZddlmZmZmZmZmZddlmZdd lmZmZed Zed Zed Zd e de fddZ!dej"deej#fddZ$d&dej"dej%dee fddZ&de de fddZ'GdddZ(GdddZ)Gddde)Z*Gd d!d!ej+Z,Gd"d#d#e)Z-Gd$d%d%Z.dS)'z sphinx.pycode.parser ~~~~~~~~~~~~~~~~~~~~ Utilities parsing and analyzing Python code. :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. N) OrderedDict) Signature)DEDENTINDENTNAMENEWLINENUMBEROPSTRING)COMMENTNL)AnyDictListOptionalTuple)ast)parseunparsez^\s*#: ?(.*) ? ?$z^\s*$z ^\s*(#.*)?$codereturncCs |ddS)N  )replace)rr6/usr/lib/python3/dist-packages/sphinx/pycode/parser.pyfilter_whitespaces rnodecCst|tjr |jS|jgS)z3Get list of targets from Assign and AnnAssign node.) isinstancerAssigntargetstarget)rrrrget_assign_targets s r"selfc Cs |r|j}|jj}|dvrtd||dkr*|dus |j|kr$|jgStd||dvrKg}|jD]}z |t||Wq3tyHYq3w|S|dkro|jjjdkri|ri|jj|kridt|j |d gStd||d krv|gS|d krt|j|St d |) zConvert assignment-AST to variable names. This raises `TypeError` if the assignment does not create new variable:: ary[0] = 'foo' dic["bar"] = 'baz' # => TypeError )IndexNumSliceStr Subscriptz%r does not create new variableNameNz*The assignment %r is not instance variable)rr Attributez%srstrStarredzUnexpected node name %r) arg __class____name__ TypeErrorideltsextendget_lvar_namesvalueattrNotImplementedError)rr#self_id node_namememberseltrrrr4(s6        r4scCs2ddd}||_t|}|r|ddSdS)z1Remove common leading indentation from docstring.rNcSsdSNrrrrrdummyTszdedent_docstring..dummyz rN)__doc__inspectgetdoclstriprstrip)r<r> docstringrrrdedent_docstringRs  rGc @steZdZdZdededeeefdeeefdeddf d d Zd ede fd d Z dede fddZ defddZ dS)Tokenz)Better token wrapper for tokenize module.kindr5startendsourcerNcCs"||_||_||_||_||_dSr=)rIr5rJrKrL)r#rIr5rJrKrLrrr__init__cs  zToken.__init__othercCsbt|tr |j|kSt|tr|j|kSt|ttfr%|j|jgt|kS|dur+dStd|)NFzUnknown value: %r)rintrIr+r5listtuple ValueError)r#rNrrr__eq__ks     z Token.__eq__ conditionscstfdd|DS)Nc3s|]}|kVqdSr=r).0 candidater#rr xszToken.match..)any)r#rTrrWrmatchwsz Token.matchcCsdtj|j|jfS)Nz)tokenizetok_namerIr5striprWrrr__repr__zs zToken.__repr__) r/ __module__ __qualname__rArOr rr+rMboolrSrZr^rrrrrH`s"  rHc@sXeZdZdeeddfddZdedefddZdefd d Z d e deefd d Z dS)TokenProcessorbuffersrNcs2t|||_tfdd|_d|_d|_dS)NcstSr=)nextrlinesrrsz)TokenProcessor.__init__..)iterrcr[generate_tokenstokenscurrentprevious)r#rcrrerrMs  zTokenProcessor.__init__linenocC|j|dSzReturns specified line.rcr#rmrrrget_linezTokenProcessor.get_linecCs>z|j|_tt|j|_W|jStyd|_Y|jSw)z_Fetch the next token from source code. Returns ``None`` if sequence finished. N)rkrlrHrdrj StopIterationrWrrr fetch_tokens zTokenProcessor.fetch_token conditioncCsg}|rJ||j|j|kr |S|jtdgkr%||tdg7}n!|jtdgkr6||tdg7}n|jtdgkrF||tdg7}|s|S)zlFetch tokens until specified token appeared. .. note:: This also handles parenthesis well. (){}[])rvappendrkr fetch_until)r#rwrjrrrrs   zTokenProcessor.fetch_until) r/r_r`rr+rMrOrsrHrvr rrrrrrbs  rbcsJeZdZdZdeeddffdd ZdeefddZd 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. rfrNcst|d|_dSr=)superrMcommentr#rfr.rrrMs  zAfterCommentParser.__init__cCsg}|rg||j|jtdgkr||tdg7}nF|jtdgkr.||tdg7}n5|jtdgkr?||tdg7}n$|jtkrL||t7}n|jtdgkrV |S|jjttt t fvrc |S|s|S)z%Fetch right-hand value of assignment.rxryrzr{r|r};) rvr~rkr rrrrIrrr )r#rjrrr fetch_rvalues&  zAfterCommentParser.fetch_rvaluecCsh|tdgtts|jsJ|tdgttr |jtdgkr&||jtkr2|jj|_dSdS)z3Parse the code and obtain comment after assignment.=N) rvrZr rr rkrr5rrWrrrrs  zAfterCommentParser.parser@) r/r_r`rArr+rMrHrr __classcell__rrrrrs rcseZdZdZdeededdffdd Zdedeeefd d Zdeddfd d Z deddfd dZ de j ddfddZ dededdfddZdede jddfddZdee jdefddZdee jdefddZdee jfddZdedefd d!Zd"e jddffd#d$ Zd"e jddfd%d&Zd"e jddfd'd(Zd"e jddfd)d*Zd"e j ddfd+d,Z!d"e j"ddfd-d.Z#d"e j$ddfd/d0Z%d"e j&ddfd1d2Z'd"e j ddfd3d4Z(d"e j)ddfd5d6Z*Z+S)7VariableCommentPickerz7Python source code parser to pick up variable comments.rcencodingrNcsnt|_||_||_g|_g|_d|_t|_ i|_ d|_ i|_ g|_ i|_d|_d|_d|_tdSr=) itertoolscountcounterrcrcontextcurrent_classescurrent_functionrcomments annotationsrl defordersfinals overloadstyping typing_finaltyping_overloadrrM)r#rcrrrrrMs zVariableCommentPicker.__init__namecCs>|jr|jr|jddkr|jdd|gSdS|j|gS)z;Get qualified name for given object as a list of string(s).rMN)rrr)r#rrrrget_qualname_fors  z&VariableCommentPicker.get_qualname_forcCs,||}|rt|j|jd|<dSdSN.)rrdrrjoinr#rqualnamerrr add_entrys zVariableCommentPicker.add_entrycCs(||}|r|jd|dSdSr)rrr~rrrrradd_final_entrys z%VariableCommentPicker.add_final_entryfunccCsFddlm}||j}|r!|jd|g}|||dSdS)Nr)signature_from_astr)sphinx.util.inspectrrrr setdefaultrr~)r#rrrrrrradd_overload_entrys  z(VariableCommentPicker.add_overload_entryrcCs6||}|rd|dd}||j||f<dSdSNrr)rrr)r#rrrbasenamerrradd_variable_comment s z*VariableCommentPicker.add_variable_comment annotationcCs:||}|rd|dd}t||j||f<dSdSr)rrrr)r#rrrrrrradd_variable_annotations z-VariableCommentPicker.add_variable_annotation decoratorsc Cdg}|jr |d|j|jr||j|D]}z t||vr%WdSWqty/YqwdS)Nz%s.finalTF)rr~rrr7)r#rfinal decoratorrrris_final   zVariableCommentPicker.is_finalc Cr)Nz %s.overloadTF)rr~rrr7)r#roverloadrrrr is_overload'rz!VariableCommentPicker.is_overloadcCs"|jr|jjjr|jjjdSdS)z8Returns the name of the first argument if in a function.rN)rargsrWrrrget_self7szVariableCommentPicker.get_selfrmcCrnrorqrrrrrrs>rtzVariableCommentPicker.get_linercst|||_dS)z(Updates self.previous to the given node.N)rvisitrlr#rrrrrBs  zVariableCommentPicker.visitcCsn|jD]1}||jp |j|jdkr|jp|j|_q|jdkr(|jp%|j|_q|jdkr4|jp2|j|_qdS)8Handles Import node and record the order of definitions.rz typing.finalztyping.overloadN)namesrasnamerrrrr#rrrrr visit_ImportGs    z"VariableCommentPicker.visit_ImportcCsh|jD].}||jp |j|jdkr |jdkr |jp|j|_q|jdkr1|jdkr1|jp/|j|_qdS)rrrrN)rrrrmodulerrrrrrvisit_ImportFromSs z&VariableCommentPicker.visit_ImportFromc szt|}tfdd|Dg}|j}Wn ty"YdSwt|dr8|jr8|D] }||jq-nt|drL|jrL|D] }||jqBt ||j dgj |jd}| |j rt|j r|D]}|td|j |qmdSt|d|j rg}t|jdD]}|jd|} t| r|td| q|rtdt|} |D] }|| |qdS|D]}|qdS) z3Handles Assign node and pick up a variable comment.csg|] }t|dqS)rW)r4r)rUtrWrr asz6VariableCommentPicker.visit_Assign..Nr type_commentz\1rp )r"sumrsrmr0hasattrrrrr col_offsetrcrr comment_rerZrsubr indent_reranger~rGrreversed) r#rr varnames current_linevarnameparser comment_linesi before_linerrrWr visit_Assign]sN      z"VariableCommentPicker.visit_AssigncC||dS)z6Handles AnnAssign node and pick up a variable comment.N)rrrrrvisit_AnnAssignrtz%VariableCommentPicker.visit_AnnAssigncCst|jtjtjfrUt|jtjrWz9t|j}t|d| }|D]%}t|jj t r0|jj }n |jj |j p8d}||t|||q"WdStyTYdSwdSdS)z2Handles Expr node and pick up a comment if string.rutf-8N)rrlrr AnnAssignr5r'r"r4rr<r+decoderrrGrr0)r#rr rrrFrrr visit_Exprs"     z VariableCommentPicker.visit_ExprcCs0|jD]}||q|jD]}||qdS)zHandles Try node and processes body and else-clause. .. note:: pycode parser ignores objects definition in except-clause. N)bodyrorelse)r#rsubnoderrr visit_Trys    zVariableCommentPicker.visit_TrycCst|j|j||j||jr||j|j|j||_|j D]}| |q&|j |j dS)z&Handles ClassDef node and set context.N) rr~rrrdecorator_listrrrlrrpopr#rchildrrrvisit_ClassDefs      z$VariableCommentPicker.visit_ClassDefcCs|jdurA||j||jr||j||jr"|||j |j||_|j D]}| |q/|j d|_dSdS)z)Handles FunctionDef node and set context.N) rrrrrrrrrr~rrrrrrrvisit_FunctionDefs          z'VariableCommentPicker.visit_FunctionDefcCr)z.Handles AsyncFunctionDef node and set context.N)rrrrrvisit_AsyncFunctionDefrtz,VariableCommentPicker.visit_AsyncFunctionDef),r/r_r`rArr+rMrrrrr FunctionDefrrASTrexprrarrr-rrOrsrImportr ImportFromrrrrrExprrTryrClassDefrrAsyncFunctionDefrrrrrrrs.   0  rcsteZdZdZdeeddffdd Zdedeeeefddfd d Z dd d Z d eddfddZ dddZ Z S)DefinitionFinderzXPython source code parser to detect location of functions, classes and methods. rfrNcs(t|d|_g|_g|_i|_dSr=)rrMrrindents definitionsrrrrrMs  zDefinitionFinder.__init__rentrycCs6|jr|jdddkr|ddkrdS||j|<dS)zAdd a location of definition.rrdefN)rr)r#rrrrradd_definitions$zDefinitionFinder.add_definitioncCs |}|dur dS|tkrnJ|tdgkr-|jdus$|jttttr-|j dur,||_ n-|t dgr:| dn |t dgrG| dn|tkrR|j dn|tkrZ|q)z1Parse the code to obtain location of definitions.TN@classr)rNNN)rvr r rlrZrr rrrrparse_definitionrr~finalize_block)r#tokenrrrrs*   zDefinitionFinder.parsetypcCs|}|j|jd|j}|jr|jjd}d|_n|jd}|tdg| t t rB|t |j |||fdS|||||jdf|jdS)zParse AST of definition.rrN:)rvrr~r5rrrJrr rZr rrrrrKr)r#rrfuncname start_posrrrrs    z!DefinitionFinder.parse_definitioncCs||j}|ddkr<|\}}}|jjdd}t||r,|d8}t||s |||||f|jdSdS)zFinalize definition block.rrNrpN) rrrkrK emptyline_rerZrsrr)r# definitionrrrend_posrrrr s   zDefinitionFinder.finalize_blockr@)r/r_r`rArr+rMrrOrrrrrrrrrrs  rc@sFeZdZdZddededdfddZdd d Zdd d Zdd dZdS)ParserzyPython source code parser to pick up variable comments. This is a better wrapper for ``VariableCommentPicker``. rrrrNcCs8t||_||_i|_i|_i|_i|_g|_i|_dSr=) rrrrrrrrr)r#rrrrrrMs  zParser.__init__cCs||dS)zParse the source code.N)parse_commentsrrWrrrr)s z Parser.parsecCsTt|j}t|jd|j}|||j|_|j|_|j|_|j |_ |j |_ dS)z$Parse the code and pick up comments.TN) rrr splitlinesrrrrrrr)r#treepickerrrrr.s   zParser.parse_commentscCs$t|jd}||j|_dS)z0Parse the location of definitions from the code.TN)rrrrr)r#rrrrr9s zParser.parse_definition)rr@) r/r_r`rAr+rMrrrrrrrrs   rr=)/rArBrrer[ collectionsrrrrrrrrr r r r rr rrrrsphinx.pycode.astrrrcompilerrrr+rrrr"r-r4rGrHrbr NodeVisitorrrrrrrrs4   $     *--vK