
    lQ                         S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKJr	  SSK
Jr  SSKJr  SS	KJr  SSKJr  SSKrSS
KJr  S r " S S\5      r  SS jr " S S\5      rg)a  A class for projecting and transforming JSON-serializable objects.

From the Cloud SDK doc "DD: gcloud resource projection algorithm":

  Algorithm

  The algorithm represents a resource R and projection P as trees. P is used
  to color the nodes of R (with the colors {0, 1, 2, 3}) as follows:

  1. Initialize the nodes in R to (id, 0, identity).
  2. Do a DFS on P. Let p be the projection subtree and r be the resource
     subtree at each level. Let f be a flag value at each level, and initialize
     f to the flag value of the root node of P.
     2.1. For each id i in p that is also in r, set r[i].flag |= p[i].flag | f,
          and r[i].transform = p[i].transform if  r[i].transform != identity and
          p[i].transform != identity.
     2.2. If p contains a slice then repeat step 2.1 with i = slice.
     2.3. If r[i].flag is 0 then prune the search at this node, otherwise
     2.4. descend to the next level with r = r[i], p = p[i], and f = r[i].flag.
  3. At the end of the search the nodes of R will be colored with the values
     {0, 1, 2, 3}. The projected keys are the set of the longest paths from the
     root of R ending with a flag value >= 2.

  Remarks

  If the initial value of f is PROJECT or PROJECT* (2 or 3) then all keys in R
  are projected. Non-leaf keys may be projected in this model, resulting in dict
  or list values instead of scalars.

Example usage:

  projector = resource_projector.Compile(expression)
  for resource in resources:
    obj = projector.Evaluate(resource)
    OperateOnProjectedResource(obj)
    )absolute_import)division)unicode_literalsN)messages)encoding)resource_projection_parser)resource_property)rangec                 4    [        5       R                  U 5      $ )zReturns resource or a JSON-serializable copy of resource.

Args:
  resource: The resource object.

Returns:
  The original resource if it is a primitive type object, otherwise a
  JSON-serializable copy of resource.
)CompileEvaluate)resources    6lib/googlecloudsdk/core/resource/resource_projector.pyMakeSerializabler   G   s     
		H	%%    c                   l    \ rS rSrSr  SS jrS rS rS rS r	S r
SS	 jrS
 rS rS rS rS rSrg)	ProjectorT   a  Projects a resource using a ProjectionSpec.

A projector is a method that takes an 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.

Attributes:
  _projection: The projection object.
  _been_here_done_that: A set of the current object id()'s being projected.
    Used to catch recursive objects like datetime.datetime.max.
  _by_columns: True if Projector projects to a list of columns.
  _columns: self._projection.Columns() column attributes.
  _ignore_default_transforms: Ignore default projection transforms if True.
  _retain_none_values: Retain dict entries with None values.
  _transforms_enabled_attribute: The projection.Attributes()
    transforms_enabled setting.
  _transforms_enabled: Projection attribute transforms enabled if True,
    disabled if False, or set by each Evaluate().
c                 
   Xl         X l        U R                   R                  5       U l        X0l        X@l        [        5       U l        UR                  5       nSU;   a  SU l	        OSU;   a  SU l	        OSU l	        SU;   U l
        g)a  Constructor.

Args:
  projection: A ProjectionSpec (parsed resource projection expression).
  by_columns: Project to a list of columns if True.
  ignore_default_transforms: Ignore default projection transforms if True.
  retain_none_values: project dict entries with None values.

transformsTzno-transformsFNzjson-decode)_projection_by_columnsColumns_columns_ignore_default_transforms_retain_none_valuesset_been_here_done_that
Attributes_transforms_enabled_attribute_json_decode)self
projection
by_columnsignore_default_transformsretain_none_values
attributess         r   __init__Projector.__init__j   s     "!$$,,.DM&?#1 #D&&(Jz!+/d(	J	&+0d(+/d(%3Dr   c                 ~    U R                   b  U R                   $ UR                  SU R                  R                  4;   $ )zReturns True if transform is enabled.

Args:
  transform: The resource_projection_parser._Transform object.

Returns:
  True if the transform is enabled, False if not.
N)_transforms_enabledactiver   )r"   	transforms     r   _TransformIsEnabledProjector._TransformIsEnabled   s>     +%%%d&6&6&=&=>>>r   c                 \   X0R                   R                  :  a  gU(       a{  UR                  (       aj  UR                  R                  (       aO  U R	                  UR                  R                  5      (       a%  UR                  R                  R                  U5      $ U R                  XUSS9$ )a  Applies projection.attribute.transform in projection if any to obj.

Args:
  obj: An object.
  projection: Projection _Tree node.
  flag: A bitmask of DEFAULT, INNER, PROJECT.

Returns:
  The transformed obj if there was a transform, otherwise the original obj.
NTleaf)r   PROJECT	attributer-   r.   r   _Project)r"   objr#   flags       r   _ProjectAttributeProjector._ProjectAttribute   s     &&&z++
0D0D0N0N$$Z%9%9%C%CDD!!++44S99==$T=::r   c                 N   0 n[        5       n[        U[        R                  5      (       a+  [        R                  " U5      US'   UR                  S5        OL UR                  [        UR                  5       Vs/ s H  ofR                  5       (       d  M  UPM     sn5        [        U5       H  nUR                  S5      (       a  M  Xu;   a  M"   [        X5      n[        US5      (       a  MA  Un	XrR                  ;   aX  UR                  U   n
XR                  R                  -  n	XR                   R"                  :  a  M  U R%                  XU	5      XG'   M  U R'                  XR                   R)                  5       U	5      XG'   M     U$ s  snf ! [         a     Nf = f!    M  = f)a  Converts class object to a dict.

Private and callable attributes are omitted in the dict.

Args:
  obj: The class object to convert.
  projection: Projection _Tree node.
  flag: A bitmask of DEFAULT, INNER, PROJECT.

Returns:
  The dict representing the class object.
datetime)maxmin
resolutiontzinfo___call__)r   
isinstancer;   six	text_typeupdatedir	__class__isupperAttributeError
startswithgetattrhasattrtreer4   r7   r   INNERr5   r8   GetEmpty)r"   r6   r#   r7   rexcludeaattrvaluefchild_projections              r   _ProjectClassProjector._ProjectClass   sh    	AeG#x(()) mmC(a
m nn;<3s}}#5E#5a#5EF C				" 

	#	#
a		 %??40	'',,,%%%
 --;((0@0@0I0I0KQO3 4 H; F s6   "F :F
F
F F
F 
FFF$c                    U(       d  U$ 0 n [         R                  " U5        [         R                  " U5       H  u  pVUnXRR                  ;   aU  UR                  U   nXxR                  R
                  -  nXpR                  R                  :  a  MX  U R                  XhU5      nO*U R                  X`R                  R                  5       U5      nUc?  U R                  (       d.  XpR                  R                  :  d  M  U R                  (       d  M   Xd[        R                  " U5      '   M     U=(       d    S$ ! [         a     gf = f! [          a	    XdU'    GM!  f = f)zProjects a dictionary object.

Args:
  obj: A dict.
  projection: Projection _Tree node.
  flag: A bitmask of DEFAULT, INNER, PROJECT.

Returns:
  The projected obj.
N)rC   	iteritems
ValueErrorrM   r4   r7   r   rN   r5   r8   rO   r   r3   r   r   DecodeUnicodeError)	r"   r6   r#   r7   reskeyvalrU   rV   s	            r   _ProjectDictProjector._ProjectDict   s'    j
C	mmC MM#&
a		%??3/	'',,,%%%
 mmC15$$S*:*:*C*C*EqI
/T55
''
'DMMM	&)hooc"
## '( ;$-  (  	c(	s#   D8 E8
EEEEc                   ^ Tc  gT(       d  / $  [        T5      n TS   n[	        / 5      nSnUR
                  (       d  X0R                  R                  :  a  gOUR
                   H  nUcT  X0R                  R                  :  d(  UR
                  U   R                  R                  (       a  UR
                  U   nMX  MZ  [        U[        R                  5      (       d  M{  U[        [        T5      * [        T5      5      ;   d  M  UR                  U5        M     X0R                  R                  :  a!  U(       d  U R                  R                  5       nU(       d  U(       d  gSnU(       a  S/[        T5      -  n	OS/[!        U4S jU 5       5      S-   -  n	U(       a  [        [        T5      5      OU H  nTU   n
U
c  M  UnXrR
                  ;   a/  UR
                  U   nU(       a  XR                  R                  -  nOUnU(       aF  XR                  R                  -  nXR                  R"                  :  a  U R%                  XU5      n
OSn
U
c  M  US:  a  U[        T5      -  nX:  a  UnXU'   M     US:  a  gU(       a  U	SUS-    $ U	$ ! [         a    [        T5      m GNf = f! [         a!     [        T5      m GN! [         a      gf = ff = f)zProjects a list, tuple or set object.

Args:
  obj: A list, tuple or set.
  projection: Projection _Tree node.
  flag: A bitmask of DEFAULT, INNER, PROJECT.

Returns:
  The projected obj.
Nr   c              3   N   >#    U  H  oS :  a  U[        T5      -   OUv   M     g7f)r   N)len).0xr6   s     r   	<genexpr>)Projector._ProjectList.<locals>.<genexpr>F  s"     H1a%!c#h,Q6s   "%   )rf   	TypeErrorsortedlistr   rM   r   r3   r4   r7   rB   rC   integer_typesr
   addrO   r<   rN   r5   )r"   r6   r#   r7   r@   indicesslicedindexmaxindexr^   r`   rU   rV   s    `           r   _ProjectListProjector._ProjectList  s    {i
c(aF "gGF??	  ((	( 
) ??%=&&...ooe$..33__U+F 4 1 122uc#hYC11
++e
 # '''((*f 6 HFc#hc FcHHH1LMc$*s3x7Jc 
 a	//	!%??51
$$
$! " 
	'',,,  &&& cQ7## 
	S		%jK 8P !| #)3qA1c1q  Sk  3i sF   J. J J+'J. *J++J. .
K9K
KKKKc                 j   [        U5      nXPR                  ;   a  gUc  GO[        U[        R                  5      (       d  [        U[        R
                  5      (       a  [        U[        R
                  5      (       a  [        R                  " U5      nU R                  (       a~  UR                  S5      (       a  UR                  S5      (       d,  UR                  S5      (       a<  UR                  S5      (       a&   U R                  [        R                  " U5      X#US9$ GO[        U[        [         ["        45      (       d  [        U[        R$                  5      (       a  GOt[        U[&        5      (       a!  [        R                  " [)        U5      5      nGO>[        U[*        R,                  5      (       a  UR.                  nGOU R                  R1                  U5        SSKJn  SSKn[        U[*        R8                  5      (       a  [:        R<                  " U5      nO[        XR8                  5      (       a  SS	KJn  UR=                  U5      nOj[        XR8                  5      (       a  UR@                  RC                  U5      nO4[E        US
5      (       a  [E        US5      (       a  U RG                  XU5      nU(       a|  URH                  (       ak  URH                  RJ                  (       aP  U RM                  URH                  RJ                  5      (       a&  URH                  RJ                  RO                  U5      nOzX0RP                  RR                  :  d  U(       aZ  URT                  (       aI  [E        US
5      (       a8  [E        US5      (       a   U RW                  XU5      nO U R]                  XU5      nU R                  R_                  U5        U$ U(       a  U$ U Ra                  XU5      $ ! [         a     N'f = f! [X        [Z        4 a    Sn N\f = f! [X        [Z        4 a    Sn Ntf = f)a|  Evaluate() helper function.

This function takes a resource obj and a preprocessed projection. obj
is a dense subtree of the resource schema (some keys values may be missing)
and projection is a sparse, possibly improper, subtree of the resource
schema. Improper in that it may contain paths that do not exist in the
resource schema or object. _Project() traverses both trees simultaneously,
guided by the projection tree. When a projection tree path reaches an
non-existent obj tree path the projection tree traversal is pruned. When a
projection tree path terminates with an existing obj tree path, that obj
tree value is projected and the obj tree traversal is pruned.

Since resources can be sparse a projection can reference values not present
in a particular resource. Because of this the code is lenient on out of
bound conditions that would normally be errors.

Args:
  obj: An object.
  projection: Projection _Tree node.
  flag: A bitmask of DEFAULT, INNER, PROJECT.
  leaf: Do not call _ProjectAttribute() if True.

Returns:
  An object containing only the key:values selected by projection, or obj if
  the projection is None or empty.
Nz{"}[]r1   r   )message)json_format__iter___fieldsitems)1idr   rB   rC   rD   binary_typer   r\   r!   rJ   endswithr5   jsonloadsr[   boolfloatcomplexro   	bytearraybytesprotorpc_messageEnumnamerp   cloudsdk.google.protobufr{   protoMessageprotorpc_encodingMessageToDictr|   rG   to_dictrL   rW   r4   r-   r.   r   r   r3   rM   ra   IOErrorrl   ru   discardr8   )	r"   r6   r#   r7   r2   objidprotobuf_messager   protobuf_encodings	            r   r5   Projector._Projectu  s   6 sGE)))	
	C	'	':c3??+K+K 
C	)	)ooc"



..

3<<#4#4
..

#,,s"3"3	tzz#
tL
L S40
1
1
S#++
,
,
	C	#	#OOE#J'c	C)..	/	/HHc
##E*F	C)11	2	2--c2c3344M--c2c==))mm##C(sJ''73	+B+B  $7
--



(
(

"
":#7#7#A#A
B
B"",,55c:%%---
Z((3  ##CT:C##CT:C ''.j 3ID223DIIg  	
	P 9% C
 9% Cs6   >$O5 P +P 5
PPPPP21P2c                     Xl         g)zoSets the projection to list-of-columns mode.

Args:
  enable: Enables projection to a list-of-columns if True.
N)r   r"   enables     r   SetByColumnsProjector.SetByColumns  s
     r   c                     Xl         g)ziSets the ignore default transforms mode.

Args:
  enable: Disable default projection transforms if True.
N)r   r   s     r   SetIgnoreDefaultTransforms$Projector.SetIgnoreDefaultTransforms  s
     '-#r   c                     Xl         g)zuSets the projection to retain-none-values mode.

Args:
  enable: Enables projection to a retain-none-values if True.
N)r   r   s     r   SetRetainNoneValuesProjector.SetRetainNoneValues  s
      &r   c                    U R                   U l        U R                  (       a  U R                  (       d  U R                  (       a  SU l        U R
                  R                  nOU R
                  R                  n[        US5      (       a  UR                  5       nU R                  XR
                  R                  5       U5      $ U R                  XR
                  R                  5       U R
                  R                  5      nU R                   c  U R                  (       + U l        / nU R                   H  nUR                  (       a   [        R                   " X5R                  5      OUnUR"                  R$                  (       aO  U R'                  UR"                  R$                  5      (       a%  UR"                  R$                  R)                  Xa5      nUR+                  U5        M     U$ )a  Serializes/projects/transforms obj.

A default or empty projection expression simply converts a resource object
to a JSON-serializable copy of the object.

Args:
  obj: An object.

Returns:
  A JSON-serializeable object containing only the key values selected by
    the projection. The return value is a deep copy of the object: changes
    to the input object do not affect the JSON-serializable copy.
Fr   )r    r+   r   r   r   r   DEFAULTr3   rL   r   r5   TreerO   r   r_   r	   Getr4   r-   r.   r   append)r"   r6   r7   obj_serializedcolumnscolumnr`   s          r   r   Projector.Evaluate  sv     $AAD4==	#( ''''	(	)	)""$]]3 0 0 5 5 7>>]]&&($*:*:*B*BN ))1%)%D%D!DdG-- ZZ 




; 

 
			#	#(@(@



$
$) ) ((11#;nnS   Nr   c                     U R                   $ )znReturns the ProjectionSpec object for the projector.

Returns:
  The ProjectionSpec object for the projector.
)r   )r"   s    r   
ProjectionProjector.Projection  s     r   )	r   r   r   r   r!   r   r   r+   r    N)FFF)F)__name__
__module____qualname____firstlineno____doc__r(   r.   r8   rW   ra   ru   r5   r   r   r   r   r   __static_attributes__ r   r   r   r   T   sS    * -2CH42?;*7r&Pm2^_JB-&*Xr   r   c                 J    [         R                  " XU[        S9n[        XSUS9$ )a  Compiles a resource projection expression.

Args:
  expression: The resource projection string.
  defaults: resource_projection_spec.ProjectionSpec defaults.
  symbols: Transform function symbol table dict indexed by function name.
  by_columns: Project to a list of columns if True.
  retain_none_values: Retain dict entries with None values.

Returns:
  A Projector containing the compiled expression ready for Evaluate().
)defaultssymbolscompiler)r$   r&   )r   Parser   r   )
expressionr   r   r$   r&   r#   s         r   r   r   #  s.     *//WwH*	:&8
: :r   c                   2   ^  \ rS rSrSrU 4S jrS rSrU =r$ )IdentityProjectori7  z>A no-op resource projector that preserves the original object.c                 R   > [         [        U ]  [        R                  " 5       5        g N)superr   r(   r   r   )r"   rG   s    r   r(   IdentityProjector.__init__:  s    	
T+,F,L,L,NOr   c                     U$ r   r   )r"   r6   s     r   r   IdentityProjector.Evaluate=  s    Jr   r   )	r   r   r   r   r   r(   r   r   __classcell__)rG   s   @r   r   r   7  s    FP r   r   ) NNFF)r   
__future__r   r   r   r;   r   apitools.base.protorpcliter   r   apitools.base.pyr   r   googlecloudsdk.core.resourcer   r	   googlecloudsdk.core.utilrC   	six.movesr
   r   objectr   r   r   r   r   r   <module>r      s`    #J '  '   C : C : - 
 
&L L^ DI$:(	 r   