B
    A!p\S                 @   s   d 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 Zd(dd	Zejed
ddZejdkZdZejZdddddddddddddddZG dd dZG d d! d!eZG d"d# d#eZG d$d% d%ejZd&d' ZdS ))z,Checks for various exception related errors.    N)checkers)utils)
interfacesc              C   s"   dd } t t| }dd |D S )Nc             S   s   t | tot| tS )N)
isinstancetype
issubclassBaseException)obj r
   9lib/python3.7/site-packages/pylint/checkers/exceptions.py	predicate&   s    z&_builtin_exceptions.<locals>.predicatec             S   s   h | ]\}}|j qS r
   )__name__).0_excr
   r
   r   	<setcomp>*   s    z&_builtin_exceptions.<locals>.<setcomp>)inspectZ
getmembersbuiltins)r   membersr
   r
   r   _builtin_exceptions%   s    r   c             c   sv   t | tjtjfrHx0| jD ]&}t|}|r|tjk	r||fV  qW dS x(| |D ]}|tjkrdqT| |fV  qTW dS )z
    Recursively generate nodes inferred by the given statement.
    If the inferred value is a list or a tuple, recurse on the elements.
    Returns an iterator which yields tuples in the format
    ('original node', 'infered node').
    N)	r   astroidListTupleeltsr   
safe_inferUninferableZinfer)ZstmtcontexteltinferredZinferedr
   r
   r   _annotated_unpack_infer-   s    

r   )bodyreturnc             C   s"   x| D ]}t |tjrdS qW dS )z:Return true if the given statement node raise an exceptionTF)r   r   ZRaise)r    noder
   r
   r   _is_raising@   s    
r#   )   r   )r   	Exception)zBad except clauses order (%s)zbad-except-orderzUsed when except clauses are not in the correct order (from the more specific to the more generic). If you don't fix the order, some exceptions may not be caught by the most specific handler.)z6Raising %s while only classes or instances are allowedzraising-bad-typeztUsed when something which is neither a class, an instance or a string is raised (i.e. a `TypeError` will be raised).)zFException context set to something which is not an exception, nor Nonezbad-exception-contextzkUsed when using the syntax "raise ... from ...", where the exception context is not an exception, nor None.)z2The raise statement is not inside an except clausezmisplaced-bare-raiseag  Used when a bare raise is not used inside an except clause. This generates an error, since there are no active exceptions to be reraised. An exception to this rule is represented by a bare raise inside a finally clause, which might work, as long as an exception is raised inside the try block, but it is nevertheless a code smell that must not be relied upon.)zBRaising a new style class which doesn't inherit from BaseExceptionzraising-non-exceptionzOUsed when a new style class which doesn't inherit from BaseException is raised.)z8NotImplemented raised - should raise NotImplementedErrorznotimplemented-raisedzAUsed when NotImplemented is raised instead of NotImplementedError)z>Catching an exception which doesn't inherit from Exception: %szcatching-non-exceptionzcUsed when a class which doesn't inherit from Exception is used as an exception in an except clause.)zNo exception type(s) specifiedzbare-exceptzDUsed when an except clause doesn't specify exceptions type to catch.)z!Catching too general exception %szbroad-exceptzWUsed when an except catches a too general exception, possibly burying unrelated errors.)z,Catching previously caught exception type %szduplicate-exceptzQUsed when an except catches a type that was already caught by a previous handler.)z%The except handler raises immediatelyztry-except-raisezUsed when an except handler uses raise as its first or only operator. This is useless because it raises back the exception immediately. Remove the raise operator or the entire try-except-raise block!)z;Exception to catch is the result of a binary "%s" operationzbinary-op-exceptionz~Used when the exception to catch is of the form "except A or B:".  If intending to catch multiple, rewrite as "except (A, B):")z?Exception arguments suggest string formatting might be intendedzraising-format-tuplezUsed when passing multiple arguments to an exception constructor, the first of them a string literal containing what appears to be placeholders intended for formatting)zInvalid exception operation. %szwrong-exception-operationzUsed when an operation is done against an exception, but the operation is not valid for the exception in question. Usually emitted when having binary operations between exceptions in except handlers.)ZE0701ZE0702ZE0703ZE0704ZE0710ZE0711ZE0712ZW0702ZW0703ZW0705ZW0706ZW0711ZW0715ZW0716c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	BaseVisitorz/Base class for visitors defined in this module.c             C   s   || _ || _d S )N)_checker_node)selfZcheckerr"   r
   r
   r   __init__   s    zBaseVisitor.__init__c             C   s8   |j j }t| d| d }|r*|| n
| | d S )NZvisit_)	__class__r   lowergetattrvisit_default)r)   r"   nameZdispatch_methr
   r
   r   visit   s
    
zBaseVisitor.visitc             C   s   dS )z)Default implementation for all the nodes.Nr
   )r)   r"   r
   r
   r   r.      s    zBaseVisitor.visit_defaultN)r   
__module____qualname____doc__r*   r0   r.   r
   r
   r
   r   r&      s   r&   c               @   s    e Zd ZdZdd Zdd ZdS )ExceptionRaiseRefVisitorz4Visit references (anything that is not an AST leaf).c             C   s    |j dkr| jjd| jd d S )NNotImplementedznotimplemented-raised)r"   )r/   r'   add_messager(   )r)   r/   r
   r
   r   
visit_name   s    
z#ExceptionRaiseRefVisitor.visit_namec             C   s   t |jtjr| |j t|jdkrt |jd tjrt |jd jt	r|jd j}d|kspd|krd|kr| j
jd| jd d S )N   r   %{}zraising-format-tuple)r"   )r   funcr   Namer7   lenargsConstvaluestrr'   r6   r(   )r)   Zcallmsgr
   r
   r   
visit_call   s    z#ExceptionRaiseRefVisitor.visit_callN)r   r1   r2   r3   r7   rD   r
   r
   r
   r   r4      s   r4   c               @   s<   e Zd ZdZdd Zdd ZeZdd Zdd	 Zd
d Z	dS )ExceptionRaiseLeafVisitorz1Visitor for handling leaf kinds of a raise value.c             C   s*   t |jts&| jjd| j|jjjd d S )Nzraising-bad-type)r"   r?   )r   rA   rB   r'   r6   r(   r+   r   )r)   Zconstr
   r
   r   visit_const   s    z%ExceptionRaiseLeafVisitor.visit_constc             C   s   |j }| | d S )N)_proxiedvisit_classdef)r)   instanceclsr
   r
   r   visit_instance   s    z(ExceptionRaiseLeafVisitor.visit_instancec             C   sD   t |s@t |r@|jr.| jjd| jd n| jjd| jd d S )Nzraising-non-exception)r"   znonstandard-exception)r   inherit_from_std_exhas_known_basesZnewstyler'   r6   r(   )r)   rJ   r
   r
   r   rH      s    z(ExceptionRaiseLeafVisitor.visit_classdefc             C   sz   t s
|js"| jjd| jdd d S |jd }t|}|rD|tjkrHd S t	|tj
rl|jjdkrl| | n
| | d S )Nzraising-bad-typetuple)r"   r?   r   Instance)PY3Kr   r'   r6   r(   r   r   r   r   r   rO   r+   r   r.   r0   )r)   Z
tuple_nodefirstr   r
   r
   r   visit_tuple   s    


z%ExceptionRaiseLeafVisitor.visit_tuplec             C   s(   t |d|jj}| jjd| j|d d S )Nr/   zraising-bad-type)r"   r?   )r-   r+   r   r'   r6   r(   )r)   r"   r/   r
   r
   r   r.     s    z'ExceptionRaiseLeafVisitor.visit_defaultN)
r   r1   r2   r3   rF   rK   Zvisit_exceptioninstancerH   rR   r.   r
   r
   r
   r   rE      s   rE   c            	       s   e Zd ZdZejZdZeZ	dZ
deddddef d	ffZ fd
dZeddddddddd Zdd Zdd Zdd Zdd Zeddd Zedd d! Zed"d#d$d%d&d'd(d)d* Z  ZS )+ExceptionsCheckerzException related checks.
exceptionszovergeneral-exceptionsZcsvz<comma-separated class names>zHExceptions that will emit a warning when being caught. Defaults to "%s".z, )defaultr   metavarhelpc                s   t  | _ tt|   d S )N)r   superrS   open)r)   )r+   r
   r   rZ   !  s    zExceptionsChecker.openznonstandard-exceptionzmisplaced-bare-raisezraising-bad-typezraising-non-exceptionznotimplemented-raisedzbad-exception-contextzraising-format-tuplec             C   s   |j d kr| | d S tr,|jr,| | |j }t| || y| d }W n tj	k
rh   Y nX |r~t
| || d S )N)r   _check_misplaced_bare_raiserP   cause_check_bad_exception_contextr4   r0   r   r   InferenceErrorrE   )r)   r"   exprZinferred_valuer
   r
   r   visit_raise%  s    




zExceptionsChecker.visit_raisec             C   s   |  }t|tjr*| r*|jdkr*d S |}tjtjf}x|rTt|j|sT|j}q<W tjf}|rnt|j|s|| jd|d d S )N__exit__zmisplaced-bare-raise)r"   )	scoper   r   ZFunctionDefZ	is_methodr/   ExceptHandlerparentr6   )r)   r"   rc   ZcurrentZignoresZexpectedr
   r
   r   r\   A  s    

z-ExceptionsChecker._check_misplaced_bare_raisec             C   sl   t |j}|tjdfkrdS t|tjrD|jdk	rh| jd|d n$t|tj	sht 
|sh| jd|d dS )z}Verify that the exception context is properly set.

        An exception context can be only `None` or an exception.
        Nzbad-exception-context)r"   )r   r   r]   r   r   r   r@   rA   r6   ClassDefrL   )r)   r"   r]   r
   r
   r   r^   V  s    
z.ExceptionsChecker._check_bad_exception_contextc             C   s   t |tjrHdd |jD }tdd |D r2d S tdd |D rHd S t |tjst |tjr|jd krt |j	tjr|j	jd ks|j	
|r| jd|j	| fd n| jd|j	| fd d S t|s|j| jkrt|r| jd|j	|jfd d S )Nc             S   s   g | ]}t |qS r
   )r   r   )r   r   r
   r
   r   
<listcomp>j  s    zCExceptionsChecker._check_catching_non_exception.<locals>.<listcomp>c             s   s   | ]}|t jkV  qd S )N)r   r   )r   r"   r
   r
   r   	<genexpr>k  s    zBExceptionsChecker._check_catching_non_exception.<locals>.<genexpr>c             s   s(   | ] }|ot |pt | V  qd S )N)r   rL   rM   )r   r"   r
   r
   r   rh   o  s   zcatching-non-exception)r"   r?   )r   r   r   r   anyallrf   r@   rA   r   Z	parent_ofr6   	as_stringr   rL   r/   r   rM   )r)   handlerr   partr   r
   r
   r   _check_catching_non_exceptiong  s6    


z/ExceptionsChecker._check_catching_non_exceptionc       	         s   dd }d}d }g }x|j D ]~}|rj||}|s6d}P x2|D ]*}t| t fdd|D r<d}P q<W t|jd gr|jd jd krd}|}||}qW |r| jd|d	 d S )
Nc             S   sB   g }| j r>t| j }t|tjr4dd |jD }n
|r>|g}|S )Nc             S   s   h | ]}t |tjr|qS r
   )r   r   r=   )r   Z	exceptionr
   r
   r   r     s   zdExceptionsChecker._check_try_except_raise.<locals>.gather_exceptions_from_handler.<locals>.<setcomp>)r   r   r   r   r   r   r   )rl   rT   Zexceptions_in_handlerr
   r
   r   gather_exceptions_from_handler  s    zQExceptionsChecker._check_try_except_raise.<locals>.gather_exceptions_from_handlerFc             3   s    | ]}t t | V  qd S )N)r   Zis_subclass_ofr   )r   Zexc_in_bare_handler)inferred_currentr
   r   rh     s   z<ExceptionsChecker._check_try_except_raise.<locals>.<genexpr>r   Tztry-except-raise)r"   )handlersr   r   ri   r#   r    r   r6   )	r)   r"   ro   Z
bare_raiseZhandler_having_bare_raiseZexcs_in_bare_handlerrl   Zexcs_in_current_handlerZexc_in_current_handlerr
   )rp   r   _check_try_except_raise  s0    



z)ExceptionsChecker._check_try_except_raisezwrong-exception-operationc             C   s<   t |jtjr8d|j |j f }| jd||fd d S )Nz Did you mean '(%s, %s)' instead?zwrong-exception-operation)r"   r?   )r   re   r   rd   leftrk   rightr6   )r)   r"   
suggestionr
   r
   r   visit_binop  s
    zExceptionsChecker.visit_binopc             C   sH   t |jtjrDd|j ddd |jD f }| jd||fd d S )Nz Did you mean '(%s, %s)' instead?z, c             s   s   | ]\}}|  V  qd S )N)rk   )r   r   Zoperandr
   r
   r   rh     s    z2ExceptionsChecker.visit_compare.<locals>.<genexpr>zwrong-exception-operation)r"   r?   )	r   re   r   rd   rs   rk   joinZopsr6   )r)   r"   ru   r
   r
   r   visit_compare  s
    zExceptionsChecker.visit_comparezbare-exceptzbroad-exceptztry-except-raisezbinary-op-exceptionzbad-except-orderzcatching-non-exceptionzduplicate-exceptc          	   C   s  |  | g }t|j}xt|jD ]\}}|jdkrtt|jsR| jd|d ||d k rrd}| jd||d q&t|jt	j
r| jd||jjd q&ytt|j}W n t	jk
r   w&Y nX x|D  ]\}}	|	t	jkrqt|	t	jrt|	r|	j}	| ||	| t|	t	js qd	d
 |	 D }
x:|D ]2}||
kr8d|j|	jf }| jd|j|d q8W |	j| jjkr|	 jtjkrt|js| jd|	j|jd |	|kr| jd|	j|jd qW |dd
 |D 7 }q&W dS )zcheck for empty exceptNzbare-except)r"   r8   z-empty except clause should always appear lastzbad-except-order)r"   r?   zbinary-op-exceptionc             S   s   g | ]}t |tjr|qS r
   )r   r   rf   )r   Zancr
   r
   r   rg     s   z5ExceptionsChecker.visit_tryexcept.<locals>.<listcomp>z%s is an ancestor class of %szbroad-except)r?   r"   zduplicate-exceptc             S   s   g | ]\}}|qS r
   r
   )r   r   r   r
   r
   r   rg   ,  s    )rr   r>   rq   	enumerater   r#   r    r6   r   r   ZBoolOpoplistr   r_   r   rO   r   rL   rG   rn   rf   Z	ancestorsr/   ZconfigZovergeneral_exceptionsrootZEXCEPTIONS_MODULE)r)   r"   Zexceptions_classesZnb_handlersindexrl   rC   Zexcsrm   r   Zexc_ancestorsZprevious_excr
   r
   r   visit_tryexcept  sX    







z!ExceptionsChecker.visit_tryexcept)r   r1   r2   r3   r   ZIAstroidCheckerZ__implements__r/   MSGSZmsgsZpriorityOVERGENERAL_EXCEPTIONSrw   ZoptionsrZ   r   Zcheck_messagesra   r\   r^   rn   rr   rv   rx   r~   __classcell__r
   r
   )r+   r   rS     sD   12

rS   c             C   s   |  t|  dS )z-required method to auto register this checkerN)Zregister_checkerrS   )Zlinterr
   r
   r   register/  s    r   )N)r3   r   r   systypingr   Zpylintr   Zpylint.checkersr   r   r   r   r   boolr#   version_inforP   r   r   ZBUILTINS_NAMEr   r&   r4   rE   ZBaseCheckerrS   r   r
   r
   r
   r   <module>   sF   


	7  &