
    e                        d 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 ddlmZ erddlmZ  G d	 d
e      ZddZy)z;Check for use of for loops that only check for a condition.    )annotations)TYPE_CHECKING)nodes)BaseChecker)assigned_boolonly_required_for_messagesreturns_bool)HIGH)PyLinterc                      e Zd ZdZddiZ ed      d	d       Ze	 	 	 	 	 	 d
d       Ze	 	 	 	 	 	 	 	 dd       Z	edd       Z
y)ConsiderUsingAnyOrAllCheckerconsider-using-any-or-allC0501)z`for` loop could be `%s`r   zYA for loop that checks for a condition and return a bool can be replaced with any or all.c                j   t        |j                        dk7  ry t        |j                  d   t        j                        sy t        |j                  d   j                               }t        d |D              ry |j                         }| j                  |||      rB|j                  j                  }| j                  ||      }| j                  d||t               y | j                  ||      rB|j                  j                  }| j                  ||      }| j                  d||t               y y )N   r   c              3  P   K   | ]  }t        |t        j                           y wN)
isinstancer   If).0childs     ?/usr/lib/python3/dist-packages/pylint/extensions/for_any_all.py	<genexpr>z9ConsiderUsingAnyOrAllChecker.visit_for.<locals>.<genexpr>+   s     Duz%*Ds   $&r   )nodeargs
confidence)lenbodyr   r   r   listget_childrenanynext_sibling_assigned_reassigned_returnedvaluename_build_suggested_stringadd_messager
   _if_statement_returns_bool)selfr   if_childrennode_after_loopfinal_return_boolsuggested_strings         r   	visit_forz&ConsiderUsingAnyOrAllChecker.visit_for#   s&   tyy>Q$))A,1499Q<4467DDD ++---dKQ / 5 5 : :#;;DBST+%	   **;H / 5 5 ; ;#;;DBST+%	    I    c                T    t        |       dk(  syt        | d         syt        |      S )zDetect for-loop, if-statement, return pattern:

        Ex:
            def any_uneven(items):
                for item in items:
                    if not item % 2 == 0:
                        return True
                return False
           Fr   )r   r	   )r*   r+   s     r   r(   z7ConsiderUsingAnyOrAllChecker._if_statement_returns_boolH   s0     ;1$KN+ O,,r/   c                T   | j                         }t        |      sy|D cg c]  }t        |t        j                        s|! }}|sy|d   j
                  d   }|j
                  d   }t        |t        j                        rt        |t        j                        sy|j
                  d   j                  }|j                  |k(  xr[ t        |t        j                        xr? t        |j                  t        j                        xr |j                  j                  |k(  S c c}w )al  Detect boolean-assign, for-loop, re-assign, return pattern:

        Ex:
            def check_lines(lines, max_chars):
                long_line = False
                for line in lines:
                    if len(line) > max_chars:
                        long_line = True
                    # no elif / else statement
                return long_line
        Fr   )previous_siblingr   r   r   Assigntargets
AssignNamer%   Returnr$   Name)	r   r*   r+   node_before_loopxassign_childrenfirst_targettarget_before_loopnode_before_loop_names	            r   r#   z:ConsiderUsingAnyOrAllChecker._assigned_reassigned_returned^   s     002-.&1QZ5<<5P1QQ 'q)11!4-55a8 |U%5%56-u/?/?@ 0 8 8 ; @ @!66 D?ELL9D?00%**=D  %%**.CC		
! Rs   D%D%c                v   | j                   j                         }| j                  j                         }t        | j                  d   j                               }t        |t        j                        r"|j                  dk(  r|j                  }|rdnd}n|rdnd}|j                         }| d| d| d	| d
S )zWhen a nodes.For node can be rewritten as an any/all statement, return a
        suggestion for that statement.

        'final_return_bool' is the boolean literal returned after the for loop if all
        conditions fail.
        r   notallznot allznot anyr!   (z for z in ))target	as_stringiternextr   r    r   r   UnaryOpopoperand)r   r,   loop_var	loop_iter	test_nodesuggested_functiontests          r   r&   z4ConsiderUsingAnyOrAllChecker._build_suggested_string   s     ;;((*II'')	12245	i/ILLE4I!))I*;.?U""$$%QtfE(4	{!LLr/   N)r   	nodes.ForreturnNone)r*   list[nodes.NodeNG]r+   nodes.NodeNGrQ   bool)r   rP   r*   rS   r+   rT   rQ   rU   )r   rP   r,   rU   rQ   str)__name__
__module____qualname__r%   msgsr   r.   staticmethodr(   r#   r&    r/   r   r   r      s    &D 
D   ;<" ="H -'-:F-	- -* )
)
&8)
KW)
	)
 )
V M Mr/   r   c                8    | j                  t        |              y r   )register_checkerr   )linters    r   registerr`      s    
8@Ar/   N)r_   r   rQ   rR   )__doc__
__future__r   typingr   astroidr   pylint.checkersr   pylint.checkers.utilsr   r   r	   pylint.interfacesr
   pylint.lint.pylinterr   r   r`   r\   r/   r   <module>ri      sC   
 B "    ' 
 #-EM; EMPBr/   