B
    A!p\                @   s  d Z ddl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	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 dd	lmZmZmZmZ dd
lmZ ddlmZ ddlmZ edZdZedZejdkZ ddiZ!e"ddhZ#dZ$dd Z%dd Z&edddd Z'dd Z(d d! Z)d"d# Z*d$d% Z+d&d' Z,d(d) Z-d*d+ Z.d,d- Z/d.d/ Z0d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEgifdFdGdHdDdIgifdJdKdLdMZ1e2dNdOZ3G dPdQ dQZ4G dRdS dSeZ5G dTdU dUe5Z6ejdkre6Z5dVdW Z7dS )Xz#variables checkers for Python code
    N)	lru_cache)
decorators)modutils)objects)InferenceContext)is_postponed_evaluation_enabled)IAstroidChecker	INFERENCEINFERENCE_FAILUREHIGH)get_global_option)BaseChecker)utilsz^_{2}[a-z]+_{2}$Z
__future__z_.*|^ignored_|^unused_)   r   Z_py_abcabcztyping.TYPE_CHECKINGZTYPE_CHECKINGzbuiltins.rangec             C   s^   y|  | j}W n tjk
r&   dS X x0|j|g D ]}t|tjr8|jtkr8dS q8W dS )z9Check if the name is a future import from another module.NT)	do_import_modulemodnameastroidAstroidBuildingExceptionlocalsget
isinstance
ImportFromFUTURE)stmtnamemoduleZ
local_node r   8lib/python3.7/site-packages/pylint/checkers/variables.py_is_from_future_importG   s    r   c                s$   t | tjo"t fdd| jD S )zEReturns True if stmt in inside the else branch for a parent For stmt.c             3   s    | ]}|  p| kV  qd S )N)	parent_of).0Z	else_stmt)r   r   r   	<genexpr>W   s    z%in_for_else_branch.<locals>.<genexpr>)r   r   ForanyZorelse)parentr   r   )r   r   in_for_else_branchT   s    r&   i  )maxsizec          	   C   sb   yt | |}W n ttfk
r*   dS X y|| }W n tk
rL   dS X t|tjr^|S dS )zget overridden method if anyN)nextZlocal_attr_ancestorsStopIterationKeyErrorr   r   FunctionDef)klassr   r%   Z	meth_noder   r   r   overridden_method[   s    r-   c             C   s`   d}|  j}|   j|krH| j|jkr6d|  }q\|jr\d|j }n|jr\d|j|f }|S )zxreturn extra information to add to the message for unpacking-non-sequence
    and unbalanced-tuple-unpacking errors
     z %sz defined at line %sz defined at line %s of %s)rootr   lineno	as_string)nodeinferedZmoreZinfered_moduler   r   r   _get_unpacking_extra_infom   s    
r4   c             C   s   d }}|r|j r|j  }|r0|j r0|j  }t|tjrVt| j tjtjfspdS ntdd ||fD rpdS g }xP||fD ]D}|}x:|rt|tjtjfs|	| P |j r|j  }qP qW q~W |rt
t|dkrdS |j|jk S )a   Detect that the given frames shares a global
    scope.

    Two frames shares a global scope when neither
    of them are hidden under a function scope, as well
    as any of parent scope of them, until the root scope.
    In this case, depending from something defined later on
    will not work, because it is still undefined.

    Example:
        class A:
            # B has the same global scope as `C`, leading to a NameError.
            class B(C): ...
        class C: ...

    NFc             s   s"   | ]}t |tjtjf V  qd S )N)r   r   ClassDefModule)r!   fr   r   r   r"      s    z'_detect_global_scope.<locals>.<genexpr>   )r%   scoper   r   r+   	Argumentsr$   r5   r6   appendlensetr0   )r2   framedefframeZ	def_scoper9   Zbreak_scopessZparent_scoper   r   r   _detect_global_scope}   s0    





rA   c             C   s   t  }||_| j|ddS )NF)asname)r   Z
lookupnameinfer)r2   r   contextr   r   r   _infer_name_module   s    rE   c             C   s   i }x|   D ]\}}tdd |D r*qx||D ]t}t|tjtjfsHq0xZ|jD ]P}d}|d dkrj|}n"|d ddks||kr|d }|rP||krP|||< qPW q0W qW t|  dd	 d
S )z Try to fix imports with multiple dots, by returning a dictionary
    with the import names expanded. The function unflattens root imports,
    like 'xml' (when we have both 'xml.etree' and 'xml.sax'), to 'xml.etree'
    and 'xml.sax' respectively.
    c             s   s*   | ]"}t |tjo t | tjV  qd S )N)r   r   
AssignNameassign_type	AugAssign)r!   r   r   r   r   r"      s   z#_fix_dot_imports.<locals>.<genexpr>Nr   *.c             S   s
   | d j S )Nr8   )
fromlineno)ar   r   r   <lambda>   s    z"_fix_dot_imports.<locals>.<lambda>)key)	itemsr$   r   r   r   Importnamesfindsorted)not_consumedrR   r   stmtsr   importsZsecond_namer   r   r   _fix_dot_imports   s$    

rX   c             C   sZ   | tjtjf}xB|D ]:}x4|jD ]*\}}|r>|| krNdS q$|r$|| kr$dS q$W qW dS )z
    Detect imports in the frame, with the required
    *name*. Such imports can be considered assignments.
    Returns True if an import for the given name was found.
    TN)nodes_of_classr   rQ   r   rR   )r   r>   rW   Zimport_nodeimport_nameimport_aliasr   r   r   _find_frame_imports   s    
r\   c             C   s6   x0| j D ]&\}}|r"||kr.dS q||krdS qW dS )NTF)rR   )r   global_namesrZ   r[   r   r   r   _import_name_is_global   s    r^   c             C   s   dd | D }t tj|S )Nc             s   s   | ]}t |jV  qd S )N)r=   rR   )r!   r   r   r   r   r"     s    z)_flattened_scope_names.<locals>.<genexpr>)r=   	itertoolschainfrom_iterable)iteratorvaluesr   r   r   _flattened_scope_names  s    rd   c                s&      tj}t fdd|D S )zN
    Checks if name_node has corresponding assign statement in same scope
    c             3   s   | ]}|j  j kV  qd S )N)r   )r!   rM   )	name_noder   r   r"     s    z$_assigned_locally.<locals>.<genexpr>)r9   rY   r   rF   r$   )re   Zassign_stmtsr   )re   r   _assigned_locally  s    rf   c             C   sh   t jt jt jt jf}xN|jt j|dD ]:}t|j	}t
|r&t|dd dkr&| j|jk r&dS q&W dS )N)Z
skip_klassr   r   TF)r   r+   r5   rQ   r   rY   Callr   
safe_inferfuncZis_builtin_objectgetattrr0   )r   r9   Z
skip_nodesZcallinferredr   r   r   _has_locals_call_after_node  s    
rl   )z#Using variable %r before assignmentzused-before-assignmentz=Used when a local variable is accessed before its assignment.)zUndefined variable %rzundefined-variablez,Used when an undefined variable is accessed.)z%Undefined variable name %r in __all__zundefined-all-variablez>Used when an undefined variable name is referenced in __all__.)z7Invalid object %r in __all__, must contain only stringszinvalid-all-objectz;Used when an invalid (non-string) object occurs in __all__.)zNo name %r in module %rzno-name-in-modulez-Used when a name cannot be found in a module.)z0Global variable %r undefined at the module levelzglobal-variable-undefinedzsUsed when a variable is defined through the "global" statement but the variable is not defined in the module scope.)z-Using global for %r but no assignment is donezglobal-variable-not-assignedzjUsed when a variable is defined through the "global" statement but no assignment to this variable is done.)zUsing the global statementzglobal-statementzUsed when you use the "global" statement to update a global variable. Pylint just try to discourage this usage. That doesn't mean you cannot use it !)z.Using the global statement at the module levelzglobal-at-module-levelzSUsed when you use the "global" statement at the module level since it has no effect)z	Unused %szunused-importz5Used when an imported module or variable is not used.)zUnused variable %rzunused-variablez-Used when a variable is defined but not used.)zUnused argument %rzunused-argumentz4Used when a function or method argument is not used.)z%Unused import %s from wildcard importzunused-wildcard-importz]Used when an imported module or variable is not used from a `'from X import *'` style import.)z-Redefining name %r from outer scope (line %s)zredefined-outer-namezDUsed when a variable's name hides a name defined in the outer scope.)zRedefining built-in %rzredefined-builtinz5Used when a variable or function override a built-in.)z/Redefining name %r from %s in exception handlerzredefine-in-handlerzHUsed when an exception handler assigns the exception to an existing name)z)Using possibly undefined loop variable %rzundefined-loop-variablezUsed when a loop variable (i.e. defined by a for loop or a list comprehension or a generator expression) is used outside the loop.zjPossible unbalanced tuple unpacking with sequence%s: left side has %d label(s), right side has %d value(s)zunbalanced-tuple-unpackingz>Used when there is an unbalanced tuple unpacking in assignmentZ	old_names)ZE0632zunbalanced-tuple-unpackingz%Attempting to unpack a non-sequence%szunpacking-non-sequencezKUsed when something which is not a sequence is used in an unpack assignment)ZW0633zunpacking-non-sequence)z Cell variable %s defined in loopzcell-var-from-loopzA variable used in a closure is defined in a loop. This will result in all closures using the same value for the closed-over variable.)zPossibly unused variable %rzpossibly-unused-variablezUsed when a variable is defined but might not be used. The possibility comes from the fact that locals() might be used, which could consume or not the said variable)z"Invalid assignment to %s in methodzself-cls-assignmentzKInvalid assignment to self or cls in instance or class method respectively.)ZE0601ZE0602ZE0603ZE0604ZE0611ZW0601ZW0602ZW0603ZW0604ZW0611ZW0612ZW0613ZW0614ZW0621ZW0622ZW0623ZW0631ZW0632ZE0633ZW0640ZW0641ZW0642ScopeConsumerzto_consume consumed scope_typec               @   s\   e Zd ZdZdd Zdd Zdd Zedd	 Zed
d Z	edd Z
dd Zdd ZdS )NamesConsumerzZ
    A simple class to handle consumed, to consume and scope type info of node locals
    c             C   s   t t|ji || _d S )N)rm   copyr   _atomic)selfr2   
scope_typer   r   r   __init__  s    zNamesConsumer.__init__c             C   s^   d ddd | jj D }|d ddd | jj D 7 }|d | jj7 }|S )Nz
to_consume : {:s}
z, c             S   s   g | ]\}}d  ||qS )z{}->{})format)r!   rO   valr   r   r   
<listcomp>  s   z*NamesConsumer.__repr__.<locals>.<listcomp>zconsumed : {:s}
c             S   s   g | ]\}}d  ||qS )z{}->{})rt   )r!   rO   ru   r   r   r   rv     s   zscope_type : {:s}
)rt   joinrp   
to_consumerP   consumedrr   )rq   msgr   r   r   __repr__  s    zNamesConsumer.__repr__c             C   s
   t | jS )N)iterrp   )rq   r   r   r   __iter__  s    zNamesConsumer.__iter__c             C   s   | j jS )N)rp   rx   )rq   r   r   r   rx     s    zNamesConsumer.to_consumec             C   s   | j jS )N)rp   ry   )rq   r   r   r   ry     s    zNamesConsumer.consumedc             C   s   | j jS )N)rp   rr   )rq   r   r   r   rr     s    zNamesConsumer.scope_typec             C   s   || j |< | j|= dS )z`
        Mark the name as consumed and delete it from
        the to_consume dictionary
        N)ry   rx   )rq   r   Znew_noder   r   r   mark_as_consumed  s    
zNamesConsumer.mark_as_consumedc             C   sX   |j }|j}| j|}|rTt|tjrT||d jkrT|d jjd }|j |krTd }|S )Nr   )r   r%   rx   r   r   r   Assigntargets)rq   r2   r   parent_node
found_nodeZlhsr   r   r   get_next_to_consume  s    
z!NamesConsumer.get_next_to_consumeN)__name__
__module____qualname____doc__rs   r{   r}   propertyrx   ry   rr   r~   r   r   r   r   r   rn     s   rn   c               @   s  e Zd ZdZeZdZeZdZ	dddddd	fd
ddddd	fdddddd	fdddddd	fdddddd	fde
dddd	fdddddd	ffZdd!d"Zejd#d$ Zejd%d& Zejd'd( Zed)d*d+ Zed)d,d- Zd.d/ Zed0d1d2d3d4d5d6d7 Zd8d9 Zed:d; Zd<d= Zd>d? Zd@dA ZdBdC ZdDdE ZdFdG Z dHdI Z!dJdK Z"dLdM Z#dNdO Z$dPdQ Z%dRdS Z&dTdU Z'dVdW Z(dXdY Z)dZd[ Z*e'Z+e*Z,ed\d]d^d_d2d`da Z-dbdc Z.ddde Z/dfdg Z0edhdidj Z1dkdl Z2dmdn Z3edodp Z4edqdr Z5dsdt Z6eje dudv Z7dwdx Z8edydzd{ Z9edyd|d} Z:ed~dddd Z;dd Z<dd Z=e=Z>e=Z?dd Z@dd ZAdd ZBd S )VariablesCheckerzchecks for
    * unused variables / imports
    * undefined variables
    * redefinition of variable from builtins or from an outer scope
    * use of variable before assignment
    * __all__ consistency
    * self/cls assignment
    Z	variablesrK   zinit-importr   Zynz<y_or_n>zBTells whether we should check for unused import in __init__ files.)defaulttypemetavarhelpzdummy-variables-rgxz;_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_Zregexpz<regexp>zYA regular expression matching the name of dummy variables (i.e. expected to not be used).zadditional-builtinsr   Zcsvz<comma separated list>zList of additional names supposed to be defined in builtins. Remember that you should avoid defining new builtins when possible.	callbacks)Zcb__cbz<callbacks>z|List of strings which can identify a callback function by name. A callback name must start or end with one of those strings.zredefining-builtins-modules)z	six.moveszpast.builtinszfuture.builtinsbuiltinsiozQList of qualified module names which can have objects that can redefine builtins.zignored-argument-nameszcArgument names that match this expression will be ignored. Default to name with leading underscore.zallow-global-unused-variablesTzGTells whether unused global variables should be treated as a violation.Nc             C   s.   t | | d | _d | _g | _g | _d| _d S )NF)r   rs   _to_consumeZ_checking_mod_attr_loop_variables_type_annotation_names_postponed_evaluation_enabled)rq   linterr   r   r   rs   P  s    zVariablesChecker.__init__c             C   s   t | dddS )Nzanalyse-fallback-blocksF)r   )r   )rq   r   r   r   _analyse_fallback_blocks[  s    z)VariablesChecker._analyse_fallback_blocksc             C   s   t | dg dS )Nzignored-modules)r   )r   )rq   r   r   r   _ignored_modules_  s    z!VariablesChecker._ignored_modulesc             C   s   t | dddS )Nzallow-global-unused-variablesT)r   )r   )rq   r   r   r   _allow_global_unused_variablesc  s    z/VariablesChecker._allow_global_unused_variableszredefined-outer-namec                s   dd |j tjD }| jj  fdd|D }xJ|D ]B}x<| jD ]2\}}||krDt||sD| jd||j	f|d P qDW q8W | j
||f d S )Nc             S   s   g | ]
}|j qS r   )r   )r!   varr   r   r   rv   j  s    z.VariablesChecker.visit_for.<locals>.<listcomp>c                s   g | ]}  |s|qS r   )match)r!   r   )	dummy_rgxr   r   rv   o  s    zredefined-outer-name)argsr2   )targetrY   r   rF   configdummy_variables_rgxr   r&   add_messagerL   r;   )rq   r2   Zassigned_toZvariableZ	outer_forZouter_variablesr   )r   r   	visit_forg  s    


zVariablesChecker.visit_forc             C   s   | j   | | d S )N)r   pop_store_type_annotation_names)rq   r2   r   r   r   	leave_for  s    
zVariablesChecker.leave_forc             C   sx   t |dg| _t|| _xZ|j D ]L\}}t|r$t|d s$| 	|d s$|dkr\q$| j
d||d d q$W dS )znvisit module : update consumption analysis variable
        checks globals doesn't overrides builtins
        r   r   r   zredefined-builtin)r   r2   N)rn   r   r   r   r   rP   r   
is_builtinis_inside_except _should_ignore_redefined_builtinr   )rq   r2   r   rV   r   r   r   visit_module  s    
zVariablesChecker.visit_modulezunused-importzunused-wildcard-importzredefined-builtinzundefined-all-variablezinvalid-all-objectzunused-variablec             C   s^   t | jdkst| j j}d|jkr4| || | | | jj	sP|j
rPdS | | dS )z$leave module: check globals
        r8   __all__N)r<   r   AssertionErrorr   rx   r   
_check_all_check_globalsr   Zinit_importpackage_check_imports)rq   r2   rU   r   r   r   leave_module  s    

zVariablesChecker.leave_modulec          	   C   sb  t |d}|tjkrd S x>t|ddD ],}yt | }W n tjk
rZ   w,Y nX |tjkrhq,|jspq,t|tj	rt|j
ts| jd| |d q,|j
}||kr||= q,||jkr,|js| jd|f|d q,tj|jd }tj|dkr,|jd	 | }yt|d	 W q, tk
rD   | jd|f|d Y q, tk
rX   Y q,X q,W d S )
Nr   eltsr   zinvalid-all-object)r   r2   zundefined-all-variabler   rs   rJ   )r(   Zigetattrr   Uninferablerj   rC   InferenceErrorr%   r   ZConstvaluestrr   r1   r   r   ospathsplitextfilebasenamer   r   Zfile_from_modpathsplitImportErrorSyntaxError)rq   r2   rU   assignedZeltZelt_namer   r   r   r   r   r     sD    



zVariablesChecker._check_allc             C   s(   | j }t|tjsdS |j}| tkS )NF)r%   r   r   ZIftestr1   TYPING_TYPE_CHECKS_GUARDS)r2   r%   r   r   r   r   _is_type_checking_import  s
    z)VariablesChecker._is_type_checking_importc             C   sD   | j r
d S x4| D ](\}}x|D ]}| jd|f|d q"W qW d S )Nzunused-variable)r   r2   )r   rP   r   )rq   rU   r   Znodesr2   r   r   r   r     s
    
zVariablesChecker._check_globalsc             C   s  t |}t }x|D ]|\}}xp|jD ]d}|d  }}|dkrH|}|d }	||krZq*|||	fkrhq*|| t|tjst|tjr|jst|tjrt	
|rq*|	dkrq*|	d krd| }
nd||	f }
| |s| jd|
|d q*t|tjr*|jtkr*t	
|rq*t||rq*|| jkr,q*|dkrH| jd	||d q*|	d krbd
||jf }
n||j|	f}d| }
| |s*| jd|
|d q*W qW | `d S )Nr   rI   r8   _z	import %sz%s imported as %szunused-import)r   r2   zunused-wildcard-importz%s imported from %sz%s imported from %s as %s)rX   r=   rR   addr   r   rQ   r   r   SPECIAL_OBJsearchr   r   r   r   r   r   )rq   rU   Zlocal_namescheckedr   r   rW   Z	real_nameZimported_nameZas_namerz   Zfieldsr   r   r   r     sR    





zVariablesChecker._check_importsc             C   s   | j t|d dS )z:visit class: update consumption analysis variable
        classN)r   r;   rn   )rq   r2   r   r   r   visit_classdef&  s    zVariablesChecker.visit_classdefc             C   s   | j   dS )z:leave class: update consumption analysis variable
        N)r   r   )rq   r   r   r   r   leave_classdef+  s    zVariablesChecker.leave_classdefc             C   s   | j t|d dS )z;visit lambda: update consumption analysis variable
        lambdaN)r   r;   rn   )rq   r2   r   r   r   visit_lambda1  s    zVariablesChecker.visit_lambdac             C   s   | j   dS )z;leave lambda: update consumption analysis variable
        N)r   r   )rq   r   r   r   r   leave_lambda6  s    zVariablesChecker.leave_lambdac             C   s   | j t|d dS )z<visit genexpr: update consumption analysis variable
        comprehensionN)r   r;   rn   )rq   r2   r   r   r   visit_generatorexp<  s    z#VariablesChecker.visit_generatorexpc             C   s   | j   dS )z<leave genexpr: update consumption analysis variable
        N)r   r   )rq   r   r   r   r   leave_generatorexpA  s    z#VariablesChecker.leave_generatorexpc             C   s   | j t|d dS )z=visit dictcomp: update consumption analysis variable
        r   N)r   r;   rn   )rq   r2   r   r   r   visit_dictcompG  s    zVariablesChecker.visit_dictcompc             C   s   | j   dS )z=leave dictcomp: update consumption analysis variable
        N)r   r   )rq   r   r   r   r   leave_dictcompL  s    zVariablesChecker.leave_dictcompc             C   s   | j t|d dS )z<visit setcomp: update consumption analysis variable
        r   N)r   r;   rn   )rq   r2   r   r   r   visit_setcompR  s    zVariablesChecker.visit_setcompc             C   s   | j   dS )z<leave setcomp: update consumption analysis variable
        N)r   r   )rq   r   r   r   r   leave_setcompW  s    zVariablesChecker.leave_setcompc             C   s   | j t|d | jds.| jds.dS | j}x| D ]\}}t	|rVqB||krt
|tjs|| d }t
|tjr|jtkrqB|j}| ||s| jd||f|d qBt|rB| |sB| jd||d qBW dS )zNvisit function: update consumption analysis variable and check locals
        functionzredefined-outer-namezredefined-builtinNr   )r   r2   )r   r;   rn   r   is_message_enabledr/   globalsrP   r   r   r   r   Globalr   r   r   rL   _is_name_ignoredr   r   r   )rq   r2   Zglobsr   r   Z
definitionliner   r   r   visit_functiondef]  s(    


z"VariablesChecker.visit_functiondefc             C   sJ   | j j}t|tjr"t|jtjs.t|tjr8| j j}n|}|oH||S )N)	r   r   r   r   rF   r%   r:   Zignored_argument_namesr   )rq   r   r   Zauthorized_rgxZregexr   r   r   r     s    
z!VariablesChecker._is_name_ignoredc                s  |  ||rd S t tjrP|dkrPt jd dkrPt jd d tjrPd S t|tjtjtj	frx|rxt
||rxd S tt  dd  jjD }  } j }|rt|tjrt|rtnt}	nt}	||kr|rD jdkr||d krd S t| j}
|
d k	r&||
 kr&d S  jtjkrD jdkrDd S t fdd	| jjD rdd S t  rtd S | j!d
|||	d n|jrt|jtj"tj#fr||krd S t|tjtj	fr|j$d \}}|p|}t%| & rd}nt|tjr:|d k	rd||f }nd| }| j!d||d d S t|tj	r|d k	rdd||j'|f }nd||j'f }| j!d||d d S d}| j!|||d d S )N	__class__r8   r   c             S   s   g | ]
}|j qS r   )r   )r!   argr   r   r   rv     s    z5VariablesChecker._check_is_unused.<locals>.<listcomp>staticmethod)rs   __new__c             3   s&   | ]} j |p j |V  qd S )N)r   
startswithendswith)r!   cb)r2   r   r   r"     s   z4VariablesChecker._check_is_unused.<locals>.<genexpr>zunused-argument)r   r2   
confidencezpossibly-unused-variablez%s imported as %sz	import %szunused-import)r   r2   z%s imported from %s as %sz%s imported from %szunused-variable)(r   r   r   r+   r<   r   r5   r   rQ   r   r^   listr_   r`   argnamesr   Z
kwonlyargs	is_methodr%   r>   r   Zhas_known_basesr	   r
   r   r   r-   r   Z	PYMETHODSr$   r   r   Z(is_registered_in_singledispatch_functionr   r   Z	AnnAssignrR   rl   r9   r   )rq   r   r2   r   r]   nonlocal_namesr   r   r,   r   Z
overriddenqnamerB   Zmessage_namerz   r   )r2   r   _check_is_unused  sz     








z!VariablesChecker._check_is_unusedc       	      C   s   |j r| |j  |jr2x|jD ]}| | q W | j j}| jdsf| jdsf| jdsfdS t	|rtdS |
 }|r| rdS t|tj}t|tj}x*| D ]\}}| |||d || qW dS )z4leave function: check function's locals are consumedzunused-variablezpossibly-unused-variablezunused-argumentNr   )Ztype_comment_returns_store_type_annotation_nodeZtype_comment_argsr   r   rx   r   r   r   Zis_errorr   Zis_abstractrd   rY   r   r   NonlocalrP   r   )	rq   r2   Zargument_annotationrU   r   r]   r   r   rV   r   r   r   leave_functiondef  s&    
z"VariablesChecker.leave_functiondefzglobal-variable-undefinedzglobal-variable-not-assignedzglobal-statementzglobal-at-module-levelc       
   	   C   s&  |  }t|tjr&| jd|d dS | }d}| j}x|jD ]}y|	|}W n tj
k
rp   g }Y nX tdd ||dD  }|s|r| jd||d	 d
}qDx\|D ]<}	t|	tjr|	j|jkr| jd||d	 P |	  |krP qW |rD| jd||d	 d
}qDW |r"| jd|d dS )z/check names imported exists in the global scopezglobal-at-module-level)r2   NTc             s   s   | ]}t |tjjV  qd S )N)r   r   node_classesrQ   )r!   Zlocalr   r   r   r"   $  s   z0VariablesChecker.visit_global.<locals>.<genexpr>r   zglobal-variable-not-assigned)r   r2   Fzredefined-builtinzglobal-variable-undefinedzglobal-statement)r>   r   r   r6   r   r/   r9   r   rR   rj   NotFoundErrorr$   r   rF   r   Zspecial_attributes)
rq   r2   r>   r   Zdefault_messageZlocals_r   Zassign_nodesZnot_defined_locally_by_importZanoder   r   r   visit_global  s>    	


zVariablesChecker.visit_globalc                s    fdd}|   t tjtjfs*d S t|jtjr<d S t|tjrl|j|  r| j	d||j
d n`|  }|}xRt|tjs||krP |j}qzW | r| st  tjs| j	d||j
d d S )Nc                  s   t  jtjo jj kS )N)r   r%   r   rg   ri   r   )
node_scoper   r   _is_direct_lambda_call@  s    zLVariablesChecker._check_late_binding_closure.<locals>._is_direct_lambda_callzcell-var-from-loop)r2   r   )r9   r   r   Lambdar+   r%   r:   Comprehensionr    r   r   r#   	statementZReturn)rq   r2   Zassignment_noder   Zassign_scopeZ	maybe_forr   )r   r   _check_late_binding_closure?  s&    

z,VariablesChecker._check_late_binding_closurec             C   s  | j dsd S dd ||d D }|rR|d js@|d jrX|d  |rXg }n|d d }xLt|dd  D ]8\}}||  |rt||  |sqv|	| qvW |}t
|dkrd S |d  }t|tjtjtjfr| | k	sd S t|tjs| jd||d d S yt|j }W n( tjk
rX   | jd||d Y nX t|tjrz| tkrzd S tjtjtjtjtjf}	t||	s| jd||d d S t|dt|dg }
|
s| jd||d d S )	Nzundefined-loop-variablec             S   s   g | ]}t |d r|qS )rG   )hasattr)r!   r   r   r   r   rv   b  s    z2VariablesChecker._loopvar_name.<locals>.<listcomp>r8   r   )r   r2   r   rP   ) r   r   lookupZis_statementr%   r   r    	enumerater&   r;   r<   rG   r   r   r#   r   ZGeneratorExpr   r(   r|   rC   r   ZInstancer   BUILTIN_RANGEListTupleZDictSetr   Z	FrozenSetrj   )rq   r2   r   ZastmtsZ_astmtsir   Zassignrk   	sequenceselementsr   r   r   _loopvar_name^  sT    	zVariablesChecker._loopvar_namec             C   s   t |tjsdS |j| jjkS )NF)r   r   r   r   r   Zredefining_builtins_modules)rq   r   r   r   r   r     s    z1VariablesChecker._should_ignore_redefined_builtinzredefine-in-handlerc             C   s<   x6t |jD ]&}t |\}}|r| jd||d qW d S )Nzredefine-in-handler)r   r2   )r   Zget_all_elementsr   Zclobber_in_exceptr   )rq   r2   r   Z
clobberingr   r   r   r   visit_excepthandler  s    z$VariablesChecker.visit_excepthandlerc             C   s   t | tjr| | d S )N)r   rG   r   rH   
visit_name)rq   r2   r   r   r   visit_assignname  s    z!VariablesChecker.visit_assignnamec             C   s   |  | d S )N)r  )rq   r2   r   r   r   visit_delname  s    zVariablesChecker.visit_delnamec             C   s`   d}t |tjr\|  |kr\trP| |jjkpZ| |jjkpZ| |jjkpZ| |jj	kpZ|j
| }|S )NF)r   r   r+   r   PY3Kr   ZannotationsZkwonlyargs_annotationsZvarargannotationZkwargannotationr    )r2   r>   in_annotation_or_defaultr   r   r   _defined_in_function_definition  s    z0VariablesChecker._defined_in_function_definitionc	                s   d}	d}
d}||k	r"t | ||}	n|jd krJ |jksDt d rd}	n~t|tjsft|  tjolt	| }|s|
  d rd}	||kot|tjj }n& |jkrt fdd| D  }	|dkr t|tjr  |jkr t|tjo| |jko|j  d j|jk  }	nt|tjrt|tjrtrd| |jkrd||jrdd }	}
|	r|j|jkr|j  d j|jk rd}	t| jtjr|j|jk}	nd|rd}	nX|	o|j|jk}	|	r|j|jkrt|tjr||kr|| r||k	rd}	|	|
|fS )NTFr8   c             3   s$   | ]}t |tjo |jkV  qd S )N)r   r   r   rR   )r!   child)r   r   r   r"     s   z:VariablesChecker._is_variable_violation.<locals>.<genexpr>r   r   )rA   r%   scope_attrsr   Zbuiltin_lookupr   r+   r>   r   rf   r/   r   r   r   r   r$   get_childrenr5   r:   defaultsrL   r  Zreturnsr    r   r0   )r2   r   defnoder   defstmtr>   r?   base_scope_typerecursive_klass
maybee0601annotation_returnuse_outer_definitionZforbid_lookupr   )r   r   _is_variable_violation  sZ    




 

z'VariablesChecker._is_variable_violationc             C   sP   |j }|  }| ||}|r0|j j}n|j}t|tjsF|oL||k S )a  
        Return True if the node is in a local class scope, as an assignment.

        :param node: Node considered
        :type node: astroid.Node
        :return: True if the node is in a local class scope, as an assignment. False otherwise.
        :rtype: bool
        )	r   r   r9   r  r%   r   r   r   r5   )rq   r2   r   r>   r  Zframe_localsr   r   r   _ignore_class_scope4  s    z$VariablesChecker._ignore_class_scopec             C   s  |  }|jdkr*| jdr&tdS |j}| }t	|sXt
|sXt||rht| jd }nt| jd }| j| j}x0t|ddD ]}| j| }|jdkr||kr|dkr||d ks| |rq||jkr&|jdkr| ||s&t|j| d }	| ||	 | || P ||}
|
dkr<qt|j| d }	|	dk	rR| ||	 |	  }| }||ko||ot|tjo|j|jk}|rt|rt	|r| j |k	rP | |||	||||||	\}}}|rq|rRt |sRt!||d	sR||ko>t|tj"tj#f}|s`|s`|s`t|tj$rt%|t&sR| j'r|r|| j(ksR| j)d
||d n|dkr| j'rt|tj*sR| j)d||d n|dkrRt|tjr6||j(kr6t|jtj+r$|j|jkr4| j)d||d n| j)d
||d n|jdkrR| j)d
||d |,||
 | || P qW |tj-j.kst/|s|| j0j1kst%|t&s| j)d
||d dS )zbcheck that a name is defined if the current scope and doesn't
        redefine a built-in
        Nz.py   r8   rK   r   r   r   )	NameErrorzundefined-variable)r   r2   r   zused-before-assignment)r2   r   )2r   rL   r/   r   r   r   r   r9   r   Zis_default_argumentZis_func_decoratorZis_ancestor_namer<   r   rr   ranger  ry   $_has_homonym_in_upper_function_scopeZassign_parentr   r   r   rx   r>   r    r   r   r5   Zis_inside_lambdar%   r  Zis_defined_beforeZare_exclusiveZDelNamerF   ZDeleteZnode_ignores_exceptionr  r   r   r   r+   r:   r~   r6   r  r   r   additional_builtins)rq   r2   r   r   r>   Zstart_indexr  r   Zcurrent_consumerr  r   r  r?   r  r  r  r  Zdefined_by_stmtr   r   r   r  Y  s    












zVariablesChecker.visit_namec             C   s<   x6| j |d dd D ]}|jdkr|j|jkrdS qW dS )a  
        Return True if there is a node with the same name in the to_consume dict of an upper scope
        and if that scope is a function

        :param node: node to check for
        :type node: astroid.Node
        :param index: index of the current consumer inside self._to_consume
        :type index: int
        :return: True if there is a node with the same name in the to_consume dict of an upper scope
                 and if that scope is a function
        :rtype: bool
        r8   NrK   r   TF)r   rr   r   rx   )rq   r2   indexZ	_consumerr   r   r   r    s    z5VariablesChecker._has_homonym_in_upper_function_scopezno-name-in-modulec          	   C   s|   | j st|rdS xb|jD ]X\}}|d}ytt||d }W n tjk
r\   wY nX | 	|||dd  qW dS )z check modules attribute accessesNrJ   r   r8   )
r   r   is_from_fallback_blockrR   r   r(   rE   r   ZResolveError_check_module_attrs)rq   r2   r   r   partsr   r   r   r   visit_import+  s    
zVariablesChecker.visit_importc             C   s   | j st|rdS |jd}y||d }W n tjk
rH   dS X | |||dd }|shdS x0|j	D ]&\}}|dkrqp| |||d qpW dS )z check modules attribute accessesNrJ   r   r8   rI   )
r   r   r  r   r   r   r   r   r  rR   )rq   r2   Z
name_partsr   r   r   r   r   r   visit_importfrom;  s    z!VariablesChecker.visit_importfromzunbalanced-tuple-unpackingzunpacking-non-sequencezself-cls-assignmentc             C   sv   |  | t|jd tjtjfs&dS |jd  }y&t|j	}|dk	rX| 
||| W n tjk
rp   dS X dS )zCheck unbalanced tuple unpacking for assignments
        and unpacking non-sequences as well as in case self/cls
        get assigned.
        r   N)_check_self_cls_assignr   r   r   r   r   iteredr   rh   r   _check_unpackingr   )rq   r2   r   r3   r   r   r   visit_assignP  s    
zVariablesChecker.visit_assignc             C   sB   t |tjr| j|j n"| jtdd |tjD  d S )Nc             s   s   | ]}|j V  qd S )N)r   )r!   Z
annotationr   r   r   r"   l  s   z?VariablesChecker._store_type_annotation_node.<locals>.<genexpr>)	r   r   Namer   r;   r   extendr   rY   )rq   type_annotationr   r   r   r   d  s    z,VariablesChecker._store_type_annotation_nodec             C   s   |j }|sd S | |j  d S )N)r%  r   )rq   r2   r%  r   r   r   r   r  s    z-VariablesChecker._store_type_annotation_namesc                s   dd |j D  | }t fdd|jD }|rB| j }t|tjjrd|	 rdd|
 kshdS | }|sxdS |d }dd |j D }||kr| jd	||d
 dS )z&Check that self/cls don't get assignedc             S   s   h | ]}t |tjr|jqS r   )r   r   rF   r   )r!   r   r   r   r   	<setcomp>}  s   z:VariablesChecker._check_self_cls_assign.<locals>.<setcomp>c             3   s,   | ]$}t |tjr t|j@ r|V  qd S )N)r   r   r   r=   rR   )r!   r  )assign_namesr   r   r"     s   z:VariablesChecker._check_self_cls_assign.<locals>.<genexpr>zbuiltins.staticmethodNr   c             s   s"   | ]}t |tjjr|jV  qd S )N)r   r   r   rF   r   )r!   r   r   r   r   r"     s   zself-cls-assignment)r2   r   )r   r9   r$   Zbodyr%   r   r   Zscoped_nodesr+   r   Zdecoratornamesr   r   )rq   r2   r9   Znonlocals_with_same_nameZargument_namesZself_cls_nameZtarget_assign_namesr   )r'  r   r  {  s(    


z'VariablesChecker._check_self_cls_assignc             C   s   t |rdS t |rdS |tjkr*dS t|jtjrZt|jtj	rZ|jj
|jjkrZdS t|tjtjfr| }t|t|krtdd |D rdS | jd|t||t|t|fd n"t |s| jd|t||fd dS )zS Check for unbalanced tuple unpacking
        and unpacking non sequences.
        Nc             s   s   | ]}t |tjV  qd S )N)r   r   ZStarred)r!   r   r   r   r   r"     s    z4VariablesChecker._check_unpacking.<locals>.<genexpr>zunbalanced-tuple-unpacking)r2   r   zunpacking-non-sequence)r   Zis_inside_abstract_classZis_comprehensionr   r   r   r%   r:   r   r#  r   Zvarargr   r   r   r<   r$   r   r4   Zis_iterable)rq   r3   r2   r   rc   r   r   r   r!    s4    



z!VariablesChecker._check_unpackingc             C   s   t |tjst|x|r|d}|dkr2d}P y(t||d  }|tjkrXdS W q tj	k
r   |j
| jkr|dS | jd||j
f|d dS  tjk
r   dS X qW |r|r|j
nd}| jd|d||fd dS t |tjr|S dS )zcheck that module_names (list of string) are accessible through the
        given module
        if the latest access name corresponds to a module, return it
        r   __dict__Nzno-name-in-module)r   r2   rJ   )r2   r   )r   r   r6   r   r   r(   rj   rC   r   r   r   r   r   r   rw   )rq   r2   r   Zmodule_namesr   r   r   r   r   r    s4    


z$VariablesChecker._check_module_attrs)N)Cr   r   r   r   r   Z__implements__r   MSGSZmsgsZpriorityIGNORED_ARGUMENT_NAMESZoptionsrs   r   Zcachedpropertyr   r   r   r   Zcheck_messagesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Zvisit_asyncfunctiondefZleave_asyncfunctiondefr   r   r   r   r   r  r  r  r  r  r  r  r  r  r"  r   r   Zleave_assignZ
leave_withr  r!  r  r   r   r   r   r     s   
0<"_/Hl% A"*r   c                   sL   e Zd ZdZdd Zdd Z fddZ fdd	Zd
d Zdd Z	  Z
S )VariablesChecker3kz!Modified variables checker for 3kc             C   s   | j t|d dS )z=visit dictcomp: update consumption analysis variable
        r   N)r   r;   rn   )rq   r2   r   r   r   visit_listcomp  s    z!VariablesChecker3k.visit_listcompc             C   s   | j   dS )z=leave dictcomp: update consumption analysis variable
        N)r   r   )rq   r   r   r   r   leave_listcomp  s    z!VariablesChecker3k.leave_listcompc                s   |  | tt| | d S )N)_check_metaclassessuperr+  r   )rq   r2   )r   r   r   r     s    
z$VariablesChecker3k.leave_functiondefc                s   |  | tt| | d S )N)r.  r/  r+  r   )rq   r2   )r   r   r   r      s    
zVariablesChecker3k.leave_modulec             C   sV   g }x.|  D ]"}t|tjr|| || qW x|D ]\}}||d q:W dS )z. Update consumption analysis for metaclasses. N)r	  r   r   r5   r$  _check_classdef_metaclassesr   )rq   r2   ry   Z
child_nodescope_localsr   r   r   r   r.    s    z%VariablesChecker3k._check_metaclassesc       	      C   s*  |j s
g S g }| }d }t|j tjr2|j j}n|r@| j}d }t||}|rx<| j	d d d D ](\}}}||}|rf|
||f P qfW |d kr&|s&d }t|j tjr|j j}nt|j tjr|j  }|d k	r&|tjjks&t|s&|| jjks&||jks&| jd||fd |S )NrK   zundefined-variable)r2   r   )Z
_metaclass	metaclassr   r   r#  r   r/   METACLASS_NAME_TRANSFORMSr   r   r;   Z	Attributer1   r6   r  r   r   r   r  r   r   )	rq   r,   r   ry   r2  r   foundr1  r   r   r   r   r0    s<    





z.VariablesChecker3k._check_classdef_metaclasses)r   r   r   r   r,  r-  r   r   r.  r0  __classcell__r   r   )r   r   r+    s   r+  c             C   s   |  t|  dS )z-required method to auto register this checkerN)Zregister_checkerr   )r   r   r   r   register@  s    r6  )8r   ro   	functoolsr   r_   collectionsr   sysrer   r   r   r   Zastroid.contextr   Zpylint.checkers.utilsr   Zpylint.interfacesr   r	   r
   r   Zpylint.utilsr   Zpylint.checkersr   r   compiler   r   r*  version_infor  r3  	frozensetr   r   r   r&   r-   r4   rA   rE   rX   r\   r^   rd   rf   rl   r)  
namedtuplerm   rn   r   r+  r6  r   r   r   r   <module>$   s   


A#

C          P