
    O                         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Z G d de      Z	 	 ddZy)z5A class for parsing a resource projection expression.    )absolute_import)division)unicode_literalsN)resource_exceptions)resource_filter)resource_lex)resource_projection_spec)resource_transformc                       e Zd ZdZddgZdgZddZ G d de      Z G d	 d
e      Z	d Z
d Zd Zd Zd Zd Zd ZddZy)Parsera  Resource projection expression parser.

  A projection is an expression string that contains a list of resource keys
  with optional attributes. This class parses a projection expression into
  resource key attributes and a tree data structure that is used by a projector.

  A projector is a method that takes a JSON-serializable object and a
  projection as input and produces a new JSON-serializable object containing
  only the values corresponding to the keys in the projection. Optional
  projection key attributes may transform the values in the resulting
  JSON-serializable object.

  In the Cloud SDK projection attributes are used for output formatting.

  A default or empty projection expression still produces a projector that
  converts a resource to a JSON-serializable object.

  Attributes:
    __key_attributes_only: Parse projection key list for attributes only.
    _projection: The resource_projection_spec.ProjectionSpec to parse into.
    _root: The projection _Tree tree root node.
    _snake_headings: Dict used to disambiguate key attribute labels.
    _snake_re: Compiled re for converting key names to angry snake case.
  optionalreversewrapNc                 j    d| _         t        j                  ||||      | _        i | _        d| _        y)a!  Constructor.

    Args:
      defaults: resource_projection_spec.ProjectionSpec defaults.
      symbols: Transform function symbol table dict indexed by function name.
      aliases: Resource key alias dictionary.
      compiler: The projection compiler method for nested projections.
    FdefaultssymbolsaliasescompilerN)_Parser__key_attributes_onlyr	   ProjectionSpec_projection_snake_headings	_snake_re)selfr   r   r   r   s        >lib/googlecloudsdk/core/resource/resource_projection_parser.py__init__zParser.__init__?   s8     "'D/>>7GhPDDDN    c                       e Zd ZdZd Zy)Parser._TreezDefines a Projection tree node.

    Attributes:
      tree: Projection _Tree node indexed by key path.
      attribute: Key _Attribute.
    c                      i | _         || _        y N)tree	attribute)r   r$   s     r   r   zParser._Tree.__init__V   s    di dnr   N)__name__
__module____qualname____doc__r    r   r   _Treer    N   s    !r   r*   c                       e Zd ZdZd Zd Zy)Parser._Attributea  Defines a projection key attribute.

    Attribute semantics, except transform, are caller defined.  e.g., the table
    formatter uses the label attribute for the column heading for the key.

    Attributes:
      align: The column alignment name: left, center, or right.
      flag: The projection algorithm flag, one of DEFAULT, INNER, PROJECT.
      hidden: Attribute is projected but not displayed.
      label: A string associated with each projection key.
      optional: Column data is optional if True.
      order: The column sort order, None if not ordered. Lower values have
        higher sort precedence.
      reverse: Reverse column sort if True.
      skip_reorder: Don't reorder this attribute in the next _Reorder().
      subformat: Sub-format string.
      transform: obj = func(obj,...) function applied during projection.
      width: Fixed column width.
      wrap: Column can be wrapped if True.
    c                     t         j                  | _        || _        d| _        d | _        d | _        d | _        d | _        d| _	        d | _
        d | _        d | _        d | _        y )NF)r	   ALIGN_DEFAULTalignflaghiddenlabelr   orderr   skip_reorder	subformat	transformwidthr   )r   r0   s     r   r   zParser._Attribute.__init__p   s]    +99djdidkdjdmdjdlddndndjdir   c           
         g }| j                   r|j                  d       | j                  r|j                  d       | j                  r|j                  d       | j                  r|j                  d       |r!dj                  dj                  |            }nd}dj                  | j                  | j                  d	nt        j                  | j                        | j                  | j                  nd
| j                  z   d
z   | j                  | j                  r| j                  j                  nd | j                  | j                  |      S )Nr1   r   r   r5   z, [{0}]| zK({flag}, {order}, {label}, {align}, {active}, {wrap}, {transform}{options})	UNORDERED')r0   r3   r2   r/   activer   r6   options)r1   appendr   r   r5   formatjoinr0   r3   six	text_typer2   r/   r6   r=   r   )r   optionr>   s      r   __str__zParser._Attribute.__str__~   s   f	h	j!	i 	k"	""388F#34''-vyy JJ. %47MM$**4M'+zz'9s@$&)@*

26....dyy NN! (. 
(#$r   N)r%   r&   r'   r(   r   rE   r)   r   r   
_Attributer,   Z   s    *$r   rF   c                 Z   | j                   t        j                  d      | _         d}t        |      D ]t  }t	        |t
        j                        s| j                   j                  d|      j                         }|r	|dz   |z   }n|}|| j                  vsdd| j                  |<    |S  |S )a  Returns an ANGRY_SNAKE_CASE string representation of a parsed key.

    For key input [A, B, C] the headings [C, C_B, C_B_A] are generated. The
    first heading not in self._snake_headings is added to self._snake_headings
    and returned.

    Args:
        key: A parsed resource key and/or list of strings.

    Returns:
      The ANGRY_SNAKE_CASE string representation of key, adding components
        from right to left to disambiguate from previous ANGRY_SNAKE_CASE
        strings.
    z)((?<=[a-z0-9])[A-Z]+|(?!^)[A-Z](?=[a-z]))r:   z_\1_   )
r   recompilereversed
isinstancerB   string_typessubupperr   )r   keyr2   index	key_snakes        r   _AngrySnakeCasezParser._AngrySnakeCase   s     ~~zz"MNdnE#	E3++	,NN&&vu5;;=	c/E)%%,,,()$

u
%
L  Lr   c                 j   | j                   }|dd D ]  }|j                  }||v rN||   j                  }|j                  | j                  j
                  k7  rS| j                  j                  |_        n7| j                  | j                  | j                  j                              ||<   ||   } |j                  }|r|d   nd}||v }|r||   j                  }| j                  sVt        | j                  j                         D cg c]  }|j                  |k(  s| c}      rt        j                  |      }| j                  r|j                  sd|_        nt!        |t"        j$                        r/d|v r+t        j&                  |d         ||<   ||   j                  }nC|}| j                  r|j                  rd|_        |s|j(                  r| j                  |      ||<   |j                  9|j                  |_        | j                  r| xj*                  dz  c_        d|_        |j.                  |j.                  |_        n"|j.                  | j1                  |      |_        |j2                  t4        j6                  k7  r|j2                  |_        |j8                  |j8                  |_        n|j8                  d|_        |j:                  |j:                  |_        n|j:                  d|_        |j(                  r|j(                  |_        |j<                  r|j<                  |_        |j>                  |j>                  |_        n|j>                  d|_        |j@                  |j@                  |_         n|j@                  d|_         | j                  jC                  |j.                  ||       | j                  r|j                  r8| j                  j
                  |_        | j                  jE                  ||       y|s| j                  jF                  |_        yyc c}w )zPropagates default attribute values and adds key to the projection.

    Args:
      key: The parsed key to add.
      attribute_add: Parsed _Attribute to add.
    Nr:   FTrI   )$_rootr#   r$   r0   r   PROJECTINNERr*   rF   r   anyColumnsrQ   copyr3   r1   rM   rB   integer_typesdeepcopyr6   _Parser__key_order_offsetr4   r2   rT   r/   r	   r.   r   r   r5   r7   r   AddAliasAddKeyDEFAULT)	r   rQ   attribute_add
projectionnamer#   r$   name_in_treecols	            r   _AddKeyzParser._AddKey   s    J CR__d	J((	>>T--555++11).ZZ0@0@0F0F GHT
:j  ??D3r7rD4<Lt*&&i((
d..668K8sCGGsNs8K
L IIi(	''y 		D#++	,==d,d4jt*&&i  i		#	#				##ZZ	*T
 &%++io		#	#1$!%	&%++io		 ,,S1io6DDD%++io)(11i				# i('//i				"i)33i)33i&%++io		 io%$))in		inioosI>%%)9)9''//in
c9-''//in { Ls   P0P0c                 t      fd j                   r$  j                  j                         d _         yy)zRecursively adds self.__key_order_offset to non-zero attribute order.

    This slides established attribute.order out of the way so new
    attribute.order in projection composition take precedence.
    c                 "   | j                         D ]{  }|j                  j                  rQ|j                  j                  rd|j                  _        n)|j                  xj                  j                  z  c_         |j
                         } y)a;  Adds self.__key_order_offset to unmarked attribute.order.

      A DFS search that visits each attribute once. The search clears
      skip_reorder attributes marked skip_reorder, otherwise it adds
      self.__key_order_offset to attribute.order.

      Args:
        tree: The attribute subtree to reorder.
      FN)valuesr$   r3   r4   r_   r#   )r#   node_AddOffsetToOrderr   s     r   rm   z*Parser._Reorder.<locals>._AddOffsetToOrder  sb     ++-$>>^^((*/DNN'NN  D$;$;; $))$  r   r   N)r_   rW   r#   )r   rm   s   `@r   _ReorderzParser._Reorder  s0    %$ 

( !d r   c                 T   	 | j                   j                  dd      }| j                   j                         }| j                   j                  dd      r!d}| j                   j                  ddd      }nd}|j	                  d	      r|d
d }d}nd}|| j
                  v r?|st        j                  dj                  | j                   j                  |                  |rK|| j                  vr=t        j                  dj                  | j                   j                  |                  |dk(  r]|s=t        j                  dj                  | j                   j                  |                  | j                  j                  |||       n|dk(  rW|t        j                  vr=t        j                  dj                  | j                   j                  |                  ||_        n|dk(  r|xs d|_        n|dk(  r|xs d|_        n~|dk(  r||_        nq|dk(  r||_        nd|dk(  r||_        nW|dk(  r||_        nJ|dk(  r||_        n=t        j                  dj                  | j                   j                  |                  | j                   j                  d      sy)aS  Parses one or more key attributes and adds them to attribute.

    The initial ':' has been consumed by the caller.

    Args:
      key: The parsed key name of the attributes.
      attribute: Add the parsed transform to this resource_projector._Attribute.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.
    Tz=:,)Fspace=eoi_okz:,)rq   convertno-   Nzvalue not expected [{0}].zvalue expected [{0}].aliaszCannot unset alias [{0}].r/   zUnknown alignment [{0}].r@   r:   r2   r   r   sortr7   r   zUnknown key attribute [{0}].:)_lexTokenGetPositionIsCharacter
startswith_BOOLEAN_ATTRIBUTESr   ExpressionSyntaxErrorr@   Annotate_OPTIONAL_BOOLEAN_ATTRIBUTESr   r`   r	   
ALIGNMENTSr/   r5   r2   r   r   r3   r7   r   )r   rQ   r$   re   hereboolean_valuevalues          r   _ParseKeyAttributeszParser._ParseKeyAttributes2  sn    YY__V5_1dYY""$d			s4		0		UDA??5!ab$%%	))	)#99)001C1CD1IJL LT)J)JJ!77#**499+=+=d+CDF 	F	#99)001C1CD1IJL L!!%i87?0;;;#99(//		0B0B40HIK K	8#kr	7?+2	:"	9!	6>	7?	6>	!77*11$))2D2DT2JKM 	MYY""3'e r   c                 <   | j                   j                         \  }}| j                   j                  dd      r?| j                   j                  |j	                         | j
                  j                        }nd}| j                  s|s| j                  r|r|st        j                  |      }n%| j                  | j
                  j                        }|j                  s||_        n1|r/|j                  j                  j                  |j                         | j                   j                          | j                   j                  d      r| j                  ||       |j                  r|j                  j                   r| j
                  j"                  j%                  t'        j(                  d            fd}t+        j,                  t*        j.                  |i      }t1        j2                  |j                  j                   |	      j5                        sy|j6                  ]|s[|j                  rO| j9                  |j                  j:                  g|j                  j                  d
   j<                  z         |_        | j?                  ||       y)a  Parses a key and optional attributes from the expression.

    The parsed key is appended to the ordered list of keys via _AddKey().
    Transform functions and key attributes are also handled here.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.
    (Trs   Nr{   conditionalsc                     t        |d       S r"   )getattr)
unused_objrestrictionunused_patternr   s      r   EvalGlobalRestrictionz/Parser._ParseKey.<locals>.EvalGlobalRestriction  s    |[$77r   )r   )r   r   ) r|   KeyWithAttributer   	Transformpopr   r=   r   r\   rF   rX   r6   _transformsextend	SkipSpacer   conditionalr   getr
   GetTypeDataNamer	   r   GLOBAL_RESTRICTION_NAMEr   CompileEvaluater2   rT   re   argsrh   )r   rQ   r$   add_transformr   r   r   s         @r   	_ParseKeyzParser._ParseKeyr  s    YY//1NCyyS.ii))#'')T5E5E5L5LMmm&&t11i ))I&i//$"2"2":":;i)i	%%,,]-F-FGIIyyS!
sI.y22>>%%--11

,
,^
<>l8 *88+CC(*+h $$



)
)%Xl34 	sy/B/B,,##
$



)
)!
,
1
123io 	LLi r   c                 x   | j                   j                  d      ry	 | j                          | j                   j                          | j                   j                  d      ry| j                   j                  d      s<t	        j
                  dj                  | j                   j                                     )zParses a comma separated list of keys.

    The initial '(' has already been consumed by the caller.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.
    )N,z*Expected ) in projection expression [{0}].)r|   r   r   r   r   r   r@   r   )r   s    r   
_ParseKeyszParser._ParseKeys  s     yyS!

nn
ii			s	#YY""3'!778??		""$&' 	' r   c                    	 | j                   j                  dd      }|r| j                   j                  d      r| j                   j                  ddd      }nd}t        |t        j
                        r"|j                  d	d
      j                  dd      }| j                  j                  ||       |j                  d      r| j                  j                  |dd        n| j                  j                  d|z          | j                   j                  d      ry| j                   j                  d      s<t        j                  dj                  | j                   j                                     v)zParses a comma separated [no-]name[=value] projection attribute list.

    The initial '[' has already been consumed by the caller.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.
    Tz=,])Frp   rr   z,])ru   rI   z\n
z\t	rw   rx   N]r   z#Expected ] in attribute list [{0}].)r|   r}   r   rM   rB   rN   replacer   AddAttributer   DelAttributer   r   r@   r   )r   re   r   s      r   _ParseAttributeszParser._ParseAttributes  s,    YY__V5_1d	99  %))//%ud/C%%eS--.--t,44UDA%%%dE2??5!



'
'QR
1



'
'
5			s	#YY""3'!771889K9K9MNP 	P# r   c                    | j                   j                         | _        | j                  s^| j                  | j	                  | j                   j
                              | _        | j                   j                  | j                         | j                   j                  | j                  | j	                  | j                   j                                     |rt        j                  || j                         | _        d}d| _        | j                  j                         r| j                  j                  d      r]| j                  sd}| j                   j                          | j!                          | j                  rd| _        | j#                          n| j                  j                  d      r| j%                          n| j                  j                  d      rd| _        d| _        n| j                  j)                         }| j                  j+                  d      }|j-                         s=t/        j0                  dj3                  | j                  j5                  |                  | j                   j7                  |       d}| j                  j                         rd	| _        |r| j                   j                          | j                   S )
a  Parse a projection expression.

    An empty projection is OK.

    Args:
      expression: The resource projection expression string.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.

    Returns:
      A ProjectionSpec for the expression.
    Fr   [r{   Tr   z:([zName expected [{0}].N)r   GetRootrW   r*   rF   rb   SetRootSetEmptyrX   r   Lexerr|   r   r   r   Defaultsr   rn   r   r_   r~   r}   isalphar   r   r@   r   SetName)r   
expressionr   r   re   s        r   ParsezParser.Parse  s    !!))+DJ::::dood.>.>.F.FGHdj
tzz*

4??4#3#3#;#;<=?$$Z1A1ABdih#(d II!99  %++H%%'
//
'').D&MMOYY""3'



!YY""3''+$
$$%$
!&&($'$%;;&--dii.@.@.FGI I



"
"4
((+ II!, di	!!#r   )NNNNr"   )r%   r&   r'   r(   r   r   r   objectr*   rF   rT   rh   rn   r   r   r   r   r   r)   r   r   r   r   "   sg    2 $Y/"(
!f 
!=$6 =$~<\0|":>@3!j'*P81r   r   c                 >    t        ||||      j                  |       S )a  Parses a resource projector expression.

  Args:
    expression: The resource projection expression string.
    defaults: resource_projection_spec.ProjectionSpec defaults.
    symbols: Transform function symbol table dict indexed by function name.
    aliases: Resource key alias dictionary.
    compiler: The projection compiler method for nested projections.

  Returns:
    A ProjectionSpec for the expression.
  r   )r   r   )r   r   r   r   r   s        r   r   r     s$     
7G!
##(5#45r   )r:   NNNN)r(   
__future__r   r   r   r\   rJ   googlecloudsdk.core.resourcer   r   r   r	   r
   rB   r   r   r   r)   r   r   <module>r      sH     < &  '  	 < 8 5 A ; 
gV gT ?C5r   