
    %                        d Z ddlmZ ddlmZ ddlm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 ddlZ G d de      Z G d dej&                        Z G d de      Z G d de      Z G d de      Z G d de      Zd Z G d de      Zd Z G d de      ZegZeegZd Z  G d d e	jB                        Z"y)!zGA command that validates gcloud flags according to Cloud SDK CLI Style.    )absolute_import)division)unicode_literalsN)arg_parsers)base)
usage_text)
exceptions)log)filesc                       e Zd ZdZy)UnknownCheckExceptionz2An exception when unknown lint check is requested.N__name__
__module____qualname____doc__     lib/surface/meta/lint.pyr   r   #   s    :r   r   c                       e Zd ZdZy)LintExceptionzOne or more lint errors found.Nr   r   r   r   r   r   '   s    &r   r   c                       e Zd ZdZd Zy)	LintErrorzValidation failure.

  Attributes:
    name: str, The name of the validation that produced this failure.
    command: calliope.backend.CommandCommon, The offending command.
    msg: str, A message indicating what the problem was.
  c                     || _         || _        dj                  dj                  |j	                               |      | _        y )Nz[{cmd}]: {msg}.)cmdmsg)namecommandformatjoinGetPathr   )selfr   r   error_messages       r   __init__zLintError.__init__4   s<    DIDL&&HHW__&'] ' <DHr   N)r   r   r   r   r%   r   r   r   r   r   +   s    <r   r   c                   "    e Zd ZdZd Zd Zd Zy)CheckerzThe abstract base class for all the checks.

  Attributes:
    name: A string, the name of this Checker.
    description: string, command line description of this check.
  c                      y Nr   r#   groups     r   ForEveryGroupzChecker.ForEveryGroupC       r   c                      y r)   r   r#   r   s     r   ForEveryCommandzChecker.ForEveryCommandF   r-   r   c                     g S r)   r   r#   s    r   EndzChecker.EndI   s    Ir   N)r   r   r   r   r,   r0   r3   r   r   r   r'   r'   ;   s    		r   r'   c                   B     e Zd ZdZdZdZ fdZd Zd Zd Z	d Z
 xZS )	NameCheckerzGChecks if group,command and flags names have underscores or mixed case.	NameCheckz4Verifies all existing flags not to have underscores.c                 8    t         t        |           g | _        y r)   )superr5   r%   _issuesr#   	__class__s    r   r%   zNameChecker.__init__S   s    	+t%'DLr   c                 (   d|j                   v rN| j                  j                  t        t        j
                  |dj                  |j                                      |j                   j                         sh|j                   j                         sN| j                  j                  t        t        j
                  |dj                  |j                                      |j                         D ]   }t        d |j                  D              st        |j                        dk7  s|j                  d   dk7  r]| j                  j                  t        t        j
                  |d	j                  d
j                  |j                                           |j                  D ]k  }d}d|v rd|z  }|j                  d      r|j                         sd|z  }|s7| j                  j                  t        t        j
                  ||             m # y)z*Run name check for given command or group._z"command name [{0}] has underscoresr   r   r$   zcommand name [{0}] mixed casec              3   >   K   | ]  }|j                  d         yw)--N
startswith).0fs     r   	<genexpr>z(NameChecker._ForEvery.<locals>.<genexpr>i   s     A-@d#-@s      r   z-hzflag [{0}] has no long form,Nzflag [%s] has underscoresr@   z(long flag [%s] has upper case characters)cli_namer9   appendr   r5   r   r    islowerisupperGetSpecificFlagsanyoption_stringslenr!   rB   )r#   cmd_or_groupflagflag_option_stringr   s        r   	_ForEveryzNameChecker._ForEveryW   s    l###
ll)<CC##%& ' !!))+|/D/D/L/L/N
ll)7>>##%& ' --/AT-@-@AAt""#q(D,?,?,Bd,J
,,

i##"9@@((4../12 3
 !% 3 3
$$+.@@#))$/&..0:=OO#
,,

i##\N O !4 0r   c                 &    | j                  |       y r)   rS   r*   s     r   r,   zNameChecker.ForEveryGroup{       NN5r   c                 &    | j                  |       y r)   rU   r/   s     r   r0   zNameChecker.ForEveryCommand~       NN7r   c                     | j                   S r)   r9   r2   s    r   r3   zNameChecker.End       <<r   r   r   r   r   r   descriptionr%   rS   r,   r0   r3   __classcell__r;   s   @r   r5   r5   M   s+    O	$F+"OHr   r5   c                   B     e Zd ZdZdZdZ fdZd Zd Zd Z	d Z
 xZS )	BadListsCheckerz%Checks command flags that take lists.BadListsz,Verifies all flags implement lists properly.c                 8    t         t        |           g | _        y r)   )r8   ra   r%   r9   r:   s    r   r%   zBadListsChecker.__init__   s    	/4)+DLr   c                    |j                         D ]  }|j                  dvr| j                  j                  t	        t
        j                  |dj                  |j                  d   dj                  t        j                  |j                                                 t        |j                  t        j                        r y t        |j                  t        j                        rx|j                   r|j                  j"                  r| j                  j                  t	        t
        j                  |dj                  |j                  d                      St        |j                  t        j$                        sy|j                   r| j                  j                  t	        t
        j                  |d	j                  |j                  d                       y )
N)Nr   rF   zflag [{flg}] has nargs={nargs}r   z'{}')flgnargsr>   zDdict flag [{flg}] has no metavar and type.spec (at least one needed))re   z list flag [{flg}] has no metavar)rL   rf   r9   rI   r   ra   r   r    rN   six	text_type
isinstancetyper   	ArgObjectArgDictmetavarspecArgList)r#   rP   rQ   s      r   rS   zBadListsChecker._ForEvery   sf   --/	<	'I %% 077++A. --djj(AB 8 D	F 	G 
DII{44	5	DII{22	3		
,,

&++&04#6#6q#9:=> dii!4!45||
,,

i"''"4;;--a0 < 2	4 51 0r   c                 &    | j                  |       y r)   rU   r*   s     r   r,   zBadListsChecker.ForEveryGroup   rV   r   c                 &    | j                  |       y r)   rU   r/   s     r   r0   zBadListsChecker.ForEveryCommand   rX   r   c                     | j                   S r)   rZ   r2   s    r   r3   zBadListsChecker.End   r[   r   r\   r_   s   @r   ra   ra      s*    -	$>+5@r   ra   c                      t         j                  j                  t         j                  j                  t              d      } t        d t        j                  |       j                  d      D              S )z+Returns allowlisted set of gcloud commands.zgcloud_command_vocabulary.txtc              3   B   K   | ]  }|j                  d       s|  yw)#NrA   )rC   lines     r   rE   z3_GetAllowlistedCommandVocabulary.<locals>.<genexpr>   s$      #Jt__S! Js   
)	ospathr!   dirname__file__setr   ReadFileContentssplit)vocabulary_files    r    _GetAllowlistedCommandVocabularyr      sY     GGLL!:!@B/	 #--o>DDTJ# 
# #r   c                   <     e Zd ZdZdZdZ fdZd Zd Zd Z	 xZ
S )VocabularyCheckerz5Checks that command is the list of allowlisted names.AllowlistedNameCheckz+Verifies that every command is allowlisted.c                 V    t         t        |           t               | _        g | _        y r)   )r8   r   r%   r   
_allowlistr9   r:   s    r   r%   zVocabularyChecker.__init__   s"    	
T+-68DODLr   c                      y r)   r   r*   s     r   r,   zVocabularyChecker.ForEveryGroup   r-   r   c           	          |j                   | j                  vrK| j                  j                  t	        | j
                  |dj                  |j                                      y y )Nz%command name [{0}] is not allowlistedr>   )rH   r   r9   rI   r   r   r    r/   s     r   r0   z!VocabularyChecker.ForEveryCommand   sS    t.
ll)yy?FF ! " /r   c                     | j                   S r)   rZ   r2   s    r   r3   zVocabularyChecker.End   r[   r   )r   r   r   r   r   r]   r%   r,   r0   r3   r^   r_   s   @r   r   r      s$    =	$=+
	"r   r   c              #      K   |  t        j                  | j                        D ]  }t        |      D ]  }|   yw)zVisits each group in the CLI group tree.

  Args:
    group: backend.CommandGroup, root CLI subgroup node.
  Yields:
    group instance.
  N)rg   
itervaluesgroups_WalkGroupTree)r+   	sub_groupvalues      r   r   r      s8      	+>>%,,/i	*k + 0s   >A c                   "    e Zd ZdZd Zd Zd Zy)LinterzLints gcloud commands.c                     g | _         y r)   )_checksr2   s    r   r%   zLinter.__init__   s	    DLr   c                 D    | j                   j                   |              y r)   )r   rI   )r#   checks     r   AddCheckzLinter.AddCheck   s    LL r   c                 `   t        |      D ]j  }| j                  D ]  }|j                  |        t        j                  |j
                        D ]$  }| j                  D ]  }|j                  |        & l | j                  D cg c]  }|j                         D ]  }|  c}}S c c}}w )z2Runs registered checks on all groups and commands.)r   r   r,   rg   r   commandsr0   r3   )r#   
group_rootr+   r   r   issues         r   Runz
Linter.Run   s    
+<<%E"  ^^ENN3'\\E



( " 4 ,  $||E|eEE|EEEs   B*N)r   r   r   r   r%   r   r   r   r   r   r   r      s    !	Fr   r   c           	          t        j                         }| D ]1  }t        j                  |j                  |j
                  ddd|       3 |j                         S )N   N   z  )writer)ioStringIOr   WrapWithPrefixr   r]   getvalue)
check_listbufr   s      r   _FormatCheckListr     sK    
#e

E%%r2tCA  
r   c                   <    e Zd ZdZed        Zd Zed        Zd Zy)Lintz7Validate gcloud flags according to Cloud SDK CLI Style.c           
      P    | j                  dddg dt        t              z          y )NchecksCHECKS*zuA list of checks to apply to gcloud groups and commands.
If omitted will run all available checks.
Available Checks:
)rm   rf   defaulthelp)add_argumentr   _LINT_CHECKS)parsers    r   Argsz	Lint.Args  s5    
 |$	%  	&r   c                     | j                   j                         }|j                  d       t        j	                  ||j
                        S )NT)	recursive)_cli_power_users_only_TopElementLoadAllSubElementsr   _SetupAndRunr   )r#   argsr+   s      r   r   zLint.Run%  s>    &&224E	t,UDKK00r   c                 T   t               }g }|st        D ]  }|j                  |        nNt        d t        t        z   D              }|D ],  }||v r|j                  ||          |j                  |       . |rt        ddj                  |      z        |j                  |       S )z9Builds up linter and executes it for given set of checks.c              3   8   K   | ]  }|j                   |f  y wr)   )r   )rC   checkers     r   rE   z$Lint._SetupAndRun.<locals>.<genexpr>5  s!       ><g <<
!<s   zUnknown lint checks: %srG   )	r   _DEFAULT_LINT_CHECKSr   dictr   rI   r   r!   r   )r+   r   linterunknown_checksr   available_checkerss         r   r   zLint._SetupAndRun+  s     XFN'% (    >-< > > %&&
//,U3
4



&	  !
#chh~&>
>@ @ ::er   c                     t         j                  }|D ]  }|j                  |j                          |rt	        d      y )Nzthere were some lint errors.)r
   outPrintr   r   )r#   r   resultr   r   s        r   DisplayzLint.DisplayD  s9    WWFll599 899 r   N)	r   r   r   r   staticmethodr   r   r   r   r   r   r   r   r     s5    ?
& 
&1  0:r   r   )#r   
__future__r   r   r   r   rx   googlecloudsdk.callioper   r   r   googlecloudsdk.corer	   r
   googlecloudsdk.core.utilr   rg   	Exceptionr   Errorr   objectr   r'   r5   ra   r   r   r   r   r   r   r   Commandr   r   r   r   <module>r      s     N &  ' 	 	 / ( . * # * 
;I ;'J$$ '< < f $5' 5p1g 1h# 4 FV F.  
 4:4<< 4:r   