
                            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SKJr  SSKJr  SSKrSr\R,                  " S5      r\R,                  " SR1                  \S95      r\R,                  " S5      rSrSrSr " S S\5      r " S S\5      r  " S S\5      r! " S S\5      r" " S S\5      r# " S  S!\5      r$ " S" S#\5      r% " S$ S%\R>                  \5      r& " S& S'\&5      r' " S( S)\&5      r( " S* S+\&5      r) " S, S-\&5      r* " S. S/\&5      r+ " S0 S1\,5      r- " S2 S3\,5      r.S4 r/S5 r0 " S6 S7\&5      r1 " S8 S9\15      r2 " S: S;\15      r3 " S< S=\15      r4 " S> S?\15      r5 " S@ SA\15      r6 " SB SC\,5      r7SD r8 " SE SF\,5      r9\9" 5       r:SG r;SH r<SI r=SJ r>g)Kaj  Manage parsing resource arguments for the cloud platform.

The Parse() function and Registry.Parse() method are to be used whenever a
Google Cloud API resource is indicated in a command-line argument.
URLs, bare names with hints, and any other acceptable spelling for a resource
will be accepted, and a consistent python object will be returned for use in
code.
    )absolute_import)division)unicode_literalsN)apis_internal)	apis_util)resource)
exceptions)
properties)map)urllib)zipz[a-zA-Z_]+(?:\.[a-zA-Z0-9_]+)+z!(https?://[^/]+/[^/]+/[^/]+/)(.+)z!(?P<collection>{collection})\.get
collectionz^gs://([^/]*)(?:/(.*))?$z&https://www.googleapis.com/storage/v1/z*https://storage.googleapis.com/storage/v1/zhttps://storage.googleapis.com/c                       \ rS rSrSrSrg)Error8   zExceptions for this module. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       $lib/googlecloudsdk/core/resources.pyr   r   8   s    #r   r   c                       \ rS rSrSrSrg)_ResourceWithoutGetException<   z+Exception for resources with no Get method.r   Nr   r   r   r   r   r   <   s    3r   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )BadResolverException@   z6Exception to signal that a resource has no Get method.c                 F   > [         [        U ]  SR                  US95        g )Nzbad resolver for [{param}])param)superr!   __init__format)selfr$   	__class__s     r   r&   BadResolverException.__init__C   s$    	
.$++%+8:r   r   r   r   r   r   r   r&   r   __classcell__r)   s   @r   r!   r!   @   s    >: :r   r!   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )AmbiguousAPIExceptionH   z5Exception for when two APIs try to define a resource.c                 Z   > [         [        U ]  SR                  U[	        U5      S95        g )Nz:collection [{collection}] defined in multiple APIs: {apis})r   apis)r%   r/   r&   r'   repr)r(   r   	base_urlsr)   s      r   r&   AmbiguousAPIException.__init__K   s1    	
/DKK!i 	L 	"#r   r   r+   r-   s   @r   r/   r/   H   s    =# #r   r/   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )AmbiguousResourcePathR   z<Exception for when API path maps to two different resources.c                 J   > [         [        U ]  SR                  X5      5        g )NzOThere already exists parser {0} for same path, can not register another one {1})r%   r7   r&   r'   )r(   parser1parser2r)   s      r   r&   AmbiguousResourcePath.__init__U   s#    	
/	++16'+CEr   r   r+   r-   s   @r   r7   r7   R   s    DE Er   r7   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )#ParentCollectionResolutionException[   zMException for when the parent collection cannot be computed automatically.
  c                 f   > [         [        U ]  SR                  USR	                  U5      S95        g )NzuCould not resolve the parent collection of collection [{collection}]. No collections found with parameters [{params}], r   params)r%   r>   r&   r'   join)r(   r   rC   r)   s      r   r&   ,ParentCollectionResolutionException.__init___   s6    	
-t=	::@&!$))F*; ;A ;=>r   r   r+   r-   s   @r   r>   r>   [   s    > >r   r>   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )!ParentCollectionMismatchExceptionf   zGException when the parent collection does not have the expected params.c           
         > [         [        U ]  SR                  X!SR	                  U5      SR	                  U5      S95        g )NzThe parent collection [{parent_collection}] of collection [{collection}] does have have the expected parameters. Expected [{expected_params}], found [{actual_params}].rA   )parent_collectionr   expected_paramsactual_params)r%   rG   r&   r'   rD   )r(   r   rJ   rK   rL   r)   s        r   r&   *ParentCollectionMismatchException.__init__i   sB    	
+T;	88>/ IIo6))M2 9? 945r   r   r+   r-   s   @r   rG   rG   f   s    O5 5r   rG   c                       \ rS rSrSrSrg)	UserErrort   z)Exceptions that are caused by user input.r   Nr   r   r   r   rO   rO   t   s    1r   rO   c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )InvalidResourceExceptionx   z5A collection-path that was given could not be parsed.c                 h   > SR                  US9nU(       a  USU-   -  n[        [        U ]  U5        g )Nz!could not parse resource [{line}]linez: )r'   r%   rR   r&   )r(   rV   reasonmessager)   s       r   r&   !InvalidResourceException.__init__{   s7    188d8CGg	
"D27;r   r   Nr+   r-   s   @r   rR   rR   x   s    =< <r   rR   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ ) WrongResourceCollectionException   z7A command line that was given had the wrong collection.c                 `   > [         [        U ]  SR                  XUS95        X l        X0l        g )NzGwrong collection: expected [{expected}], got [{got}], for path [{path}]expectedgotpath)r%   r\   r&   r'   ra   rb   )r(   r`   ra   rb   r)   s       r   r&   )WrongResourceCollectionException.__init__   s8    	
*D:	T  34 HIr   )ra   rb   r+   r-   s   @r   r\   r\      s    ? r   r\   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )RequiredFieldOmittedException   z6A command line that was given did not specify a field.c                 F   > [         [        U ]  SR                  X!S95        g )Nz_value for field [{expected}] in collection [{collection_name}] is required but was not provided)r`   collection_name)r%   re   r&   r'   )r(   rh   r`   r)   s      r   r&   &RequiredFieldOmittedException.__init__   s,    	
'7	((. )/ )@Ar   r   r+   r-   s   @r   re   re      s    >A Ar   re   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )UnknownCollectionException   ;A command line that was given did not specify a collection.c                 F   > [         [        U ]  SR                  US95        g )Nzunknown collection for [{line}]rU   )r%   rk   r&   r'   )r(   rV   r)   s     r   r&   #UnknownCollectionException.__init__   s$    	
$d4)00d0;=r   r   r+   r-   s   @r   rk   rk      s    C= =r   rk   c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )InvalidCollectionException   rm   c                 |   > SR                  US9nU(       a  USR                  US9-  n[        [        U ]  U5        g )Nz!unknown collection [{collection}]r   z for API version [{version}])version)r'   r%   rq   r&   )r(   r   api_versionrX   r)   s       r   r&   #InvalidCollectionException.__init__   sB    188J8OG/66{6KKg	
$d4W=r   r   rZ   r+   r-   s   @r   rq   rq      s    C> >r   rq   c                   D    \ rS rSrSrS r S
S jr  SS jrS rS r	S	r
g)_ResourceParser   zFClass that turns command-line arguments into a cloud resource message.c                     Xl         X l        g)zCreate a _ResourceParser for a given collection.

Args:
  registry: Registry, The resource registry this parser belongs to.
  collection_info: resource_util.CollectionInfo, description for collection.
N)registrycollection_info)r(   r{   r|   s      r   r&   _ResourceParser.__init__   s     M*r   Nc                    [         R                  " U5      nU R                  R                  U5      n[        R
                  " XQ5      nU(       d0  [        USR                  U R                  R                  U5      5      eU R                  R                  U5      nUR                  5       nU(       a$  [        [        R                  R                  U5      n[        U R                   U R                  U[#        [%        Xx5      5      US9$ )a  Parse relative name into a Resource object.

Args:
  relative_name: str, resource relative name.
  base_url: str, base url part of the api which manages this resource.
  subcollection: str, id of subcollection. See the api resource module
      (googlecloudsdk/generated_clients/apis/API_NAME/API_VERSION/resources.py).
  url_unescape: bool, if true relative name parameters will be unescaped.

Returns:
  Resource representing this name.

Raises:
  InvalidResourceException: if relative name doesn't match collection
      template.
zBIt is not in {0} collection as it does not match path template {1})param_valuesendpoint_url)r   UniversifyAddressr|   GetPathRegExrematchrR   r'   	full_name	GetParamsgroupsr   r   parseunquoteResourcer{   dictr   )	r(   relative_namebase_urlsubcollectionurl_unescapepath_templater   rC   fieldss	            r   ParseRelativeName!_ResourceParser.ParseRelativeName   s    $ ..x8H((55mDMHH]2E$

N6$&&00-@B B !!++M:F\\^F6<<''0fDMM4#7#7!%c&&9!:!)+ +r   c                 b  ^ [         R                  " U5      nTb   U R                  TX4S9$ U R                  R                  U5      n
[        UR                  5       5      R                  U
5      (       dP  [        SR                  [        UR                  5       5      [        U
5      U R                  R                   5      5      e[#        5       (       a  [$        R'                  TU R                  R                   US9nUR(                  n[+        U5      [+        U
5      :  a*  [-        TU
UR.                  (       a  UR0                  S9eSS9e[+        U5      [+        U
5      :  a  US/[+        U
5      [+        U5      -
  -  -  n[3        U5      nOS/[+        U
5      -  nTUS'   [5        [7        X5      5      nUR9                  5        HR  u  pUb  M
  UR;                  U5      nU(       a  [=        U5      (       a  U" 5       OUX'   M?  U(       d  MH  U" U5      X'   MT     [?        U R@                  U R                  UX5      nU$ ! [         af    U R                  R                  U5      nU R                  U5      n[        U4S jU 5       5      n	U	(       a  [        SR                  T5      5      e GNf = f)	a  Given a command line and some keyword args, get the resource.

Args:
  resource_id: str, Some identifier for the resource.
      Can be None to indicate all params should be taken from kwargs.
  kwargs: {str:(str or func()->str)}, flags (available from context) or
      resolvers that can help parse this resource. If the fields in
      collection-path do not provide all the necessary information,
      kwargs will be searched for what remains.
  base_url: use this base url (endpoint) for the resource, if not provided
      default corresponding api version base url will be used.
  subcollection: str, name of subcollection to use when parsing this path.
  validate: bool, Validate syntax. Use validate=False to handle IDs under
    construction. An ID can be:
      fully qualified - All parameters are specified and have valid syntax.
      partially qualified - Some parameters are specified, all have valid
        syntax.
      under construction - Some parameters may be missing or too short and
        not meet the syntax constraints. With additional characters they
        would have valid syntax. Used by completers that build IDs from
        strings character by character. Completers need to do the
        string => parameters => string round trip with validate=False to
        handle the "add character TAB" cycle.
  default_resolver: func(str) => str, a default param resolver function
    called if kwargs doesn't resolve a param.

Returns:
  protorpc.messages.Message, The object containing info about this resource.

Raises:
  InvalidResourceException: If the provided collection-path is malformed.
  WrongResourceCollectionException: If the collection-path specified the
      wrong collection.
  RequiredFieldOmittedException: If the collection-path's path did not
      provide enough fields.
  GRIPathMismatchException: If the number of path segments in the GRI does
      not match the expected format of the URL for the given resource
      collection.
  ValueError: if parameter set in kwargs is not subset of the resource
      parameters.
Nr   r   c              3   2   >#    U  H  oS -   T;   v   M     g7f)/Nr   ).0prefixresource_ids     r   	<genexpr>2_ResourceParser.ParseResourceId.<locals>.<genexpr>  s      "E6CFSLK'ms   zInvalid value: {}zPProvided params {} is not subset of the resource parameters {} for collection {}r   validater   )!r   r   r   rR   r|   GetPathGetFieldNamesFromPathallrO   r'   r   setkeysissubset
ValueErrorsortedr   _GRIsAreEnabledGRI
FromStringpath_fieldslenGRIPathMismatchExceptionis_fully_qualifiedr   reversedr   r   itemsgetcallabler   r{   )r(   r   kwargsr   r   r   default_resolverrb   path_prefixescontains_all_fieldsrC   grir   r   r$   valueresolverrefs    `                r   ParseResourceId_ResourceParser.ParseResourceId   s   X ..x8H%%( & I 	I !!++M:F v{{}&&v..6&'&&0023 3 NN;&*&:&:&D&D$,  .c f	Vs6{	"&),)?)?s~~K 	KEIK 	K v;V$4&CK#f+566fvF#ffRjF+,L$**,		 E"h	,4X,>,>hjH.u5 - 4==$"6"6+CJm & 
##++M:2248! "E6C"E E -44[AB
B

s   H> >A,J.-J.c                     [        UR                  S5      5       VVs/ s H  u  p#US-  S:X  d  M  U(       d  M  UPM     snn$ s  snnf )zExtract field names from uri template path.

Args:
  path: str, uri template path.

Returns:
  list(str), list of field names in the template path.
r      r   )	enumeratesplit)r(   rb   idxr   s       r   r   %_ResourceParser.GetFieldNamesFromPathB  sR     #,JJsO##;37a< 	" 	 #  s   AAAc                     SnU R                   R                   H  nSR                  XS9nM     SR                  U R                   R                  US9$ )N z[{path}]/{param})rb   r$   z[{collection}::]{path})r   rb   )r|   rC   r'   r   )r(   path_strr$   s      r   __str___ResourceParser.__str__Q  s[    H%%,,#***Fh -#**''11 + B Br   )r|   r{   )Nr   F)Nr   TN)r   r   r   r   r   r&   r   r   r   r   r   r   r   r   rx   rx      s3    N+ JO +F AE'+gRBr   rx   c                      ^  \ rS rSrSrS rU 4S jrS rS rS r	S r
SS	 jrS
 rS rS rSS jrS rS rS rS rS rSrU =r$ )r   iY  z#Information about a Cloud resource.c                    Xl         X l        U(       a  XPl        O%[        R                  " UR
                  5      U l        X0l        UR                  U5      U l        UR                  U5      U l
        [        R                  " U5       H*  u  pgUc  [        UR                  U5      e[        XU5        M,     SR!                  U R                  ["        R$                  " U R                  U R'                  5       5      5      U l        U R                  R*                  S;   a.  [,        R.                  R1                  U R(                  5      U l        SU l        g)a  Create a Resource object that may be partially resolved.

To allow resolving of unknown params to happen after parse-time, the
param resolution code is in this class rather than the _ResourceParser
class.

Args:
  registry: Registry, The resource registry this parser belongs to.
  collection_info: resource_util.CollectionInfo, The collection description
      for this resource.
  subcollection: str, id for subcollection of this collection.
  param_values: {param->value}, A list of values for parameters.
  endpoint_url: str, override service endpoint url for this resource. If
       None default base url of collection api will be used.
Raises:
  RequiredFieldOmittedException: if param_values have None value.
Nz{0}{1})computestoragecertificatemanagerT)	_registry_collection_info_endpoint_urlr   r   r   _subcollectionr   _pathr   _paramssix	iteritemsre   r   setattrr'   uritemplateexpandAsDict
_self_linkapi_namer   r   r   _initialized)r(   r{   r|   r   r   r   r$   r   s           r   r&   Resource.__init__\  s   & N+'(::

"
"d ( ((7DJ",,];DLl3	+O,E,EuMMd5! 4
 ooK..tzz4;;=IKDO%% *@ @ ,,T__=doDr   c                 |   > [        U SS 5      b  [        SR                  U5      5      e[        [        U ]  X5        g )Nr   z<Cannot set attribute {0}. Resource references are immutable.)getattrNotImplementedErrorr'   r%   r   __setattr__)r(   keyr   r)   s      r   r   Resource.__setattr__  s>    t^T*6//5vc{< < 
(D%c1r   c                 6    [        SR                  U5      5      e)Nz?Cannot delete attribute {0}. Resource references are immutable.)r   r'   )r(   r   s     r   __delattr__Resource.__delattr__  s    
	--3VC[: :r   c                 x    U R                   R                  nU R                  (       a  US-   U R                  -   $ U$ )N.)r   r   r   )r(   r   s     r   
CollectionResource.Collection  s8    &&00J# 3 333r   c                     U R                   $ rZ   )r   r(   s    r   GetCollectionInfoResource.GetCollectionInfo  s       r   c                 V    U R                   (       a  [        X R                   S   5      $ g )Nr   r   r   r   s    r   NameResource.Name  s     ||T<<+,,r   c                 :   U(       a  [         R                  R                  OS n[        U R                   Vs/ s H  nX2" [        X5      SS94PM     sn5      n[         R                  R                  [        R                  " U R                  U5      5      $ s  snf )a  Relative resource name.

A URI path ([path-noscheme](http://tools.ietf.org/html/rfc3986#appendix-A))
without the leading "/". It identifies a resource within the API service.
For example:
  "shelves/shelf1/books/book2"

Args:
  url_escape: bool, if true would url escape each parameter.
Returns:
   Unescaped part of SelfLink which is essentially base_url + relative_name.
   For example if SelfLink is
     https://pubsub.googleapis.com/v1/projects/myprj/topics/mytopic
   then relative name is
     projects/myprj/topics/mytopic.
c                     U $ rZ   r   )xsafes     r   <lambda>'Resource.RelativeName.<locals>.<lambda>  s    r   r   )r   )
r   r   quoter   r   r   r   r   r   r   )r(   
url_escapeescape_funckeffective_paramss        r   RelativeNameResource.RelativeName  s    " )3&,,$$8IK,,	 Q [)3	4	 ! <<4::'78: :	 s   Bc           
          [         R                  " U R                   Vs/ s H  o[        X5      /PM     sn5      $ s  snf )z5Returns resource reference parameters and its values.)collectionsOrderedDictr   r   r(   r$   s     r   r   Resource.AsDict  s=    ""7;||	
7CeGD()|	
 	
s   <c                 X    U R                    Vs/ s H  n[        X5      PM     sn$ s  snf )z"Returns resource reference values.r   r  s     r   AsListResource.AsList  s#    .2ll;lUGD l;;;s   'c                     U R                   $ )zReturns URI for this resource.r   r   s    r   SelfLinkResource.SelfLink  s    ??r   c                    U R                   SS nU R                  R                  U R                  R                     U R                  R
                     nU(       aA   X1   nUR                  R                  S5      nXR:w  a  [        U R                  5       XU5      eO[        R                  " U5       HS  u  pgUR                  R                  S5      U:X  d  M&  UR                  R                  S5      U R                  ;   d  MQ  Un  O   U(       dB  [        R                  " U5       H(  u  pgUR                  R                  S5      U:X  d  M&  Un  O   U(       d  [!        U R                  5       U5      eU Vs0 s H  o[#        X5      _M     n	nU R                  R%                  SU	US9n
U
$ ! [         a    [        U5      ef = fs  snf )a  Gets a reference to the parent of this resource.

If parent_collection is not given, we attempt to automatically determine it
by finding the collection within the same API that has the correct set of
URI parameters for what we expect. If the parent collection cannot be
automatically determined, it can be specified manually.

Args:
  parent_collection: str, The full collection name of the parent resource.
    Only required if it cannot be automatically determined.

Raises:
  ParentCollectionResolutionException: If the parent collection cannot be
    determined or doesn't exist.
  ParentCollectionMismatchException: If the given or auto-resolved parent
   collection does not have the expected URI parameters.

Returns:
  Resource, The reference to the parent resource.
Nr   r   r   )r   r   parsers_by_collectionr   r   ru   KeyErrorrk   r|   r   rG   r   r   r   r   r   r>   r   Parse)r(   rJ   parent_paramsall_collectionsparent_parseractual_parent_paramsr   parserr   parent_param_valuesr   s              r   ParentResource.Parent  s   * LL"%Mnn::&&((,(=(=(I(IKO <': +::DDRH		./OO0 " 	" 
/ !$o >
*"",,R0MA""**2.$**<(

	 !? "%--"@J##--b1]B * #A 1OO}. 	. 9FF1gd..F
..

t%8*;  =CJ9  <():;;<2 Gs   F+ 7G+Gc                     U R                   $ rZ   r  r   s    r   r   Resource.__str__
      ??r   c                 p    [        U[        5      (       a!  U R                  5       UR                  5       :H  $ gNF)
isinstancer   r	  r(   others     r   __eq__Resource.__eq__  s*    %""]]_ 000r   c                 D    U R                  5       UR                  5       :  $ rZ   )r	  r  s     r   __lt__Resource.__lt__  s    ==?U^^---r   c                 ,    [        U R                  5      $ rZ   )hashr   r   s    r   __hash__Resource.__hash__  s      r   c                     U R                   $ rZ   r  r   s    r   __repr__Resource.__repr__  r  r   )r   r   r   r   r   r   r   r   )FrZ   )r   r   r   r   r   r&   r   r   r   r   r   r   r   r  r	  r  r   r  r"  r&  r)  r   r,   r-   s   @r   r   r   Y  s]    +*X2:
!:4<
:x
.! r   r   c                      [         R                  R                  R                  R	                  5       =(       d5    [         R                  R                  R
                  R                  5       S:H  $ )z!Returns True if GRIs are enabled.r   )r
   VALUEScore
enable_griGetBoolresource_completion_styleGetr   r   r   r   r     sO    



 
 
+
+
3
3
5 J



 
 
:
:
>
>
@E
IKr   c                 *    U R                  S5      S   $ )zGet the API name from a collection name like 'api.parents.children'.

Args:
  collection: str, The collection name.

Returns:
  str: The API name.
r   r   )r   r   s    r   _APINameFromCollectionr3  "  s     
		#	q	!!r   c                       \ rS rSrSrSrg)GRIExceptioni.  z*Base class for all GRI related exceptions.r   Nr   r   r   r   r5  r5  .  s    2r   r5  c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidGRIFormatExceptioni3  z2Exception for when a GRI is syntactically invalid.c                 F   > [         [        U ]  SR                  US95        g )NzlThe given GRI [{gri}] is invalid and could not be parsed.
Valid GRIs take the form of: a:b:c::api.collection)r   )r%   r7  r&   r'   )r(   r   r)   s     r   r&   "InvalidGRIFormatException.__init__6  s#    	
#T3	==CVV_r   r   r+   r-   s   @r   r7  r7  3  s    : r   r7  c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )#InvalidGRICollectionSyntaxExceptioni=  zLException for when the collection part of a GRI is syntactically invalid.
  c                 F   > [         [        U ]  SR                  XS95        g )NzZThe given GRI [{gri}] could not be parsed because the collection [{collection}] is invalid)r   r   )r%   r;  r&   r'   )r(   r   r   r)   s      r   r&   ,InvalidGRICollectionSyntaxException.__init__A  s$    	
-t=	$$*FsF$Jr   r   r+   r-   s   @r   r;  r;  =       r   r;  c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )GRICollectionMismatchExceptioniH  zLException for when the parsed GRI collection does not match the expected.
  c                 J   > [         [        U ]  SR                  UUUS95        g )NzThe given GRI [{gri}] could not be parsed because collection [{expected_collection}] was expected but [{parsed_collection}] was provided. Provide a GRI with the correct collection or drop the specified collection.)r   expected_collectionparsed_collection)r%   r@  r&   r'   )r(   r   rB  rC  r)   s       r   r&   'GRICollectionMismatchException.__init__L  s2    	
($8	  !'3;N9J !' !L	r   r   r+   r-   s   @r   r@  r@  H  s     r   r@  c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidGRIPathSyntaxExceptioniW  zMException for when a part of the path of the GRI is syntactically invalid.
  c                 F   > [         [        U ]  SR                  XS95        g )NzPThe given GRI [{gri}] could not be parsed because the path is invalid: {message})r   rX   )r%   rF  r&   r'   )r(   r   rX   r)   s      r   r&   &InvalidGRIPathSyntaxException.__init__[  s$    	
'7	VV5r   r   r+   r-   s   @r   rF  rF  W  r>  r   rF  c                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )r   ib  z=Exception for when the path has the wrong number of segments.c           
         > [         [        U ]  SR                  USR	                  [        U5      5      U(       a  SU-   OS-   S95        g )NzxThe given GRI [{gri}] does not match the required structure for this resource type. It must match the format: [{format}]:::r   )r   r'   )r%   r   r&   r'   rD   r   )r(   r   rC   r   r)   s       r   r&   !GRIPathMismatchException.__init__e  sI    	
"D2	>	C(6*:!;7A$"3r"K 
Mr   r   rZ   r+   r-   s   @r   r   r   b  s    E r   r   c                       \ rS rSrSrSS jrS r\SS j5       r\SS j5       r	\S 5       r
\S	 5       r\S
 5       r\S 5       rSrg)r   in  ao  Encapsulates a parsed GRI string.

Attributes:
  path_fields: [str], The individual fields of the path portion of the GRI.
  collection: str, The collection portion of the GRI.
  is_fully_qualified: bool, True if the original GRI included the collection.
    This could be false if the collection is not defined, or if it was passed
    in explicitly during parsing.
Nc                 @    Xl         X l        U=(       a    USLU l        g)z$Use FromString() to construct a GRI.N)r   r   r   )r(   r   r   r   s       r   r&   GRI.__init__y  s    " O0KZt5KDr   c                     SR                  U R                   Vs/ s H  nU R                  U5      PM     sn5      R                  S5      nU R                  (       a  USU R
                  -   -  nU$ s  snf )NrK  rL  )rD   r   _EscapePathSegmentrstripr   r   )r(   sr   s      r   r   GRI.__str__  sn    
((!--/- ++A.-/ 006s 	TDOO##cJ	/s   A0c                     U R                  XS9u  pEU(       d  UnO.U(       a'  U R                  X5        U(       a  XR:w  a
  [        XUS9eU R                  U5      n[	        Xb[        U5      S9$ )a  Parses a GRI from a string.

Args:
  gri: str, The GRI to parse.
  collection: str, The collection this GRI is for. If provided and the GRI
    contains a collection, they must match. If not provided, the collection
    in the GRI will be used, or None if it is not specified.
  validate: bool, Validate syntax. Use validate=False to handle GRIs under
    construction.

Returns:
  A parsed GRI object.

Raises:
  GRICollectionMismatchException: If the given collection does not match the
    collection specified in the GRI.
)r   )rB  rC  )r   )_SplitCollection_ValidateCollectionr@  
_SplitPathr   bool)clsr   r   r   rb   rC  r   s          r   r   GRI.FromString  s{    & "2232JD %j		c.	0>,/1 	1 ..&KD9J4KM Mr   c                 f   U(       d  g[         R                  " SU5      n[        U5      S:  a  [        U5      e[        U5      S:X  a"  US   US   pTU(       a  U R	                  X5        OUS   SpTU(       a8  UR                  S5      (       d  UR                  S5      (       a  [        US5      eXE4$ )	a  Splits a GRI into its path and collection segments.

Args:
  gri: str, The GRI string to parse.
  validate: bool, Validate syntax. Use validate=False to handle GRIs under
    construction.

Returns:
  (str, str), The path and collection parts of the string. The
  collection may be None if not specified in the GRI.

Raises:
  InvalidGRIFormatException: If the GRI cannot be parsed.
  InvalidGRIPathSyntaxException: If the GRI path cannot be parsed.
)NNz6(?=(?<={)::+[^:}]|(?<=[^:{])::+}|(?<=[^:{])::+[^:}])::r   r      NrK  z%GRIs cannot have empty path segments.)r   r   r   r7  rX  
startswithendswithrF  )r[  r   r   partsrb   rC  s         r   rW  GRI._SplitCollection  s    "  HHNE
5zA~%c**	Uq %a%(	7 %a$ T__S))T]]3-?-?)
68 8 ""r   c                 R    [         R                  " SU5      (       d  [        X5      eg )Nz^\w+\.\w+(?:\.\w+)*$)r   r   r;  )r[  r   r   s      r   rX  GRI._ValidateCollection  s&     88+Z88/@@ 9r   c                     U(       d  / $ [         R                  " SU5      nU Vs/ s H  o0R                  U5      PM     sn$ s  snf )zSplits a GRI into its individual path segments.

Args:
  path: str, The path segment of the GRI (from _SplitCollection)

Returns:
  [str], A list of the path segments of the GRI.
z2(?=(?<={):+[^:}]|(?<=[^:{]):+}|(?<=[^:{]):+[^:}]):)r   r   _UnescapePathSegment)r[  rb   ra  parts       r   rY  GRI._SplitPath  sE     i HHJE 8==ut$$T*u===s   Ac                 2    [         R                  " SSU5      $ )Nz{(:+)}z\1r   subr[  segments     r   rf  GRI._UnescapePathSegment  s    66)UG,,r   c                 2    [         R                  " SSU5      $ )Nz(:+)z{\1}rj  rl  s     r   rR  GRI._EscapePathSegment  s    66'7G,,r   )r   r   r   r  )NT)T)r   r   r   r   r   r&   r   classmethodr   rW  rX  rY  rf  rR  r   r   r   r   r   r   n  s    L $M $ML *# *#X A A > >& - - - -r   r   c                      [         R                  R                  R                  U 5      R	                  5       n[        U5      $ ! [         R
                   a     gf = f)z5Check if a URL is the result of an endpoint override.F)r
   r,  api_endpoint_overridesPropertyr1  NoSuchPropertyErrorrZ  )r   endpoint_overrides     r   HasOverriddenEndpointrw    sX    "))@@II#% 
 
	   
	'	' s   7A AAc                       \ rS rSrSr  SS jrS rSS jrS rS r	SS	 jr
  SS
 jrSS jrSS jr  SS jrSS jr  SS jrS rSrg)Registryi	  a  Keep a list of all the resource collections and their parsing functions.

Attributes:
  parsers_by_collection: {str: {str: {str: _ResourceParser}}}, All the
      resource parsers indexed by their api name, api version
      and collection name.
  parsers_by_url: {str: {str: <Deeply-nested dict>}}, URL parsing tries
      indexed by api name and api version. Each key within a trie can be
      either a constant or a parameter name and represents a possible URL
      token after the API's base URL. At the end, a key of None indicates the
      value is a _ResourceParser.
  registered_apis: {str: str}, The most recently registered API version for
      each API. For instance, {'dns': 'v1', 'compute': 'alpha'}.
Nc                 d    U=(       d    0 U l         U=(       d    0 U l        U=(       d    0 U l        g rZ   r  parsers_by_urlregistered_apis)r(   r  r|  r}  s       r   r&   Registry.__init__  s)    !6!<"D(.BD*0bDr   c                 p    [        U R                  U R                  U R                  R	                  5       S9$ )zClones this registry.

Clones share the same underlying parser data and differ only in which API
versions were most recently registered.

Returns:
  Registry, The cloned registry.
r{  )ry  r  r|  r}  copyr   s    r   CloneRegistry.Clone  s5     "88**,,1135 5r   c                 :   U R                   R                  US5      nUc   U(       a  UnO[        R                  " U5      nX R                  R                  U0 5      ;  a.  [        R
                  " X5       H  nU R                  U5        M     X R                   U'   U$ )zRegister the given API if it has not been registered already.

Args:
  api_name: str, The API name.
  api_version: str, The API version, None for the default version.
Returns:
  api version which was registered.
N)r}  r   r   _GetDefaultVersionr  _GetApiCollections_RegisterCollection)r(   r   ru   registered_versionr   s        r   RegisterApiByNameRegistry.RegisterApiByName-  s     --11(DA	(#66x@ 44882FF%88O*  , P &1"r   c                 ,   UR                   nUR                  n[        X5      nU R                  R	                  U0 5      R	                  U0 5      nUR
                  nU(       d  SUR                  0n[        R                  " U5       H  u  pxUR                  U(       a  SU-   OS-   n	UR                  U	5      n
U
b,  [        U	UR                  U
R                  R                  /5      eXEU	'   UR                  (       d  Mw  U R                  X#XtU5        M     g)a#  Registers given collection with registry.

Args:
  collection_info: CollectionInfo, description of resource collection.
Raises:
  AmbiguousAPIException: If the API defines a collection that has already
      been added.
  AmbiguousResourcePath: If api uses same path for multiple resources.
r   r   N)r   ru   rx   r  
setdefault
flat_pathsrb   r   r   r   r   r/   r   r|   enable_uri_parsing_AddParserForUriPath)r(   r|   r   ru   r  collection_parserscollection_subpathssubnamerb   rh   existing_parsers              r   r  Registry._RegisterCollectionG  s	    ''H!--KT3F44??"M%:k26 )44!5!56':;'11"#-,o*..?o		$#O%4%=%=%4%D%D%M%M%OP 	P -3)		+	+	+!!($O <r   c                 (   X/UR                  S5      -   nU R                  nU(       a;  UR                  S5      nUS   S:X  a  US   S:X  a  SnX;  a  0 Xx'   Xx   nU(       a  M;  SU;   a#  [        US   UR                  R
                  5      eX44US'   g)z Registers parser for given path.r   r   {r   }{}N)r   r|  popr7   r|   name)	r(   r   ru   r   r  rb   tokens	cur_leveltokens	            r   r  Registry._AddParserForUriPathh  s     $tzz#6F ##I
jjme	qSU2Y#-			"i & y!)D/63I3I3N3NOO#+IdOr   c                     [        U5      nU R                  X2S9nU R                  R                  U0 5      R                  U0 5      R                  US5      nUc  [	        X5      eU$ )a  Returns a parser object for collection.

Args:
  collection: str, The resource collection name.
  api_version: str, The API version, None for the default version.

Raises:
  InvalidCollectionException: If there is no parser.

Returns:
  The parser object for collection.
ru   N)r3  r  r  r   rq   )r(   r   ru   r   r  s        r   GetParserForCollectionRegistry.GetParserForCollection  sf     &j1H(((KK((s8R ["!5cc*d6K ~&z??Mr   c           	         [        5       (       a  [        R                  X!US9R                  nU(       d  [	        U5      eU R                  XS9n[        UR                  R                  UR                  R                  5      nUR                  R                  n	Sn
[        U	5      [        U5      :w  a  U[        U	5      S-   S n
UR                  X#XUUS9$ )a\  Parse a resource id string into a Resource.

Args:
  collection: str, the name/id for the resource from commandline argument.
  resource_id: str, Some resource identifier.
      Can be None to indicate all params should be taken from kwargs.
  kwargs: {str:(str or func()->str)}, flags (available from context) or
      resolvers that can help parse this resource. If the fields in
      collection-path do not provide all the necessary information,
      kwargs will be searched for what remains.
  validate: bool, Validate syntax. Use validate=False to handle IDs under
    construction. An ID can be:
      fully qualified - All parameters are specified and have valid syntax.
      partially qualified - Some parameters are specified, all have valid
        syntax.
      under construction - Some parameters may be missing or too short and
        not meet the syntax constraints. With additional characters they
        would have valid syntax. Used by completers that build IDs from
        strings character by character. Completers need to do the
        string => parameters => string round trip with validate=False to
        handle the "add character TAB" cycle.
  api_version: str, The API version, None for the default version.
  default_resolver: func(str) => str, a default param resolver function
    called if kwargs doesn't resolve a param.

Returns:
  protorpc.messages.Message, The object containing info about this resource.

Raises:
  InvalidCollectionException: If the provided collection-path is malformed.
  UnknownCollectionException: If the collection of the resource could not be
      determined.

r   r  r   r^  N)r   r   )r   r   r   r   rk   r  GetApiBaseUrlr|   r   ru   r   r   r   )r(   r   r   r   r   ru   r   r  r   parser_collectionr   s              r   r   Registry.ParseResourceId  s    H 
 >>
x " AAK  &{33(((MFV33<<#33??AH ..88M
Z0 %6!7!9!:;m!!+x+33C " E Er   c                     [        U5      nU R                  X2S9nU R                  R                  U0 5      R                  U0 5      R                  US 5      nUc  [	        X5      eUR
                  $ )Nr  )r3  r  r  r   rq   r|   )r(   rh   ru   r   r  s        r   r   Registry.GetCollectionInfo  sn    %o6H(((KK((s8R ["!5s?D)  ~&DD!!!r   c                    [         R                  U5      nU(       d
  [        USS9e[        R                  " U5      u  pEnU=(       d    Un [
        R                  " U5      nX';  a@  [        U5      (       a0  U R                  R                  U[
        R                  " U5      5      nX';  a  [        USR                  U5      5      eXB/UR                  S5      -   nUS[        U5      *  n	 U R!                  XBS9  / n
U R$                  n['        U5       H  u  pX;   a  X   nM  S0 p[(        R*                  " U5       H  u  pUS	:X  d  M    O   [        US
R                  U5      S9e[        U5      S:X  aK  SU;   aE  SR-                  XS 5      nU
R/                  [0        R2                  R5                  U5      5        Un  O4U
R/                  [0        R2                  R5                  U5      5        UnM     SU;  a  [        US5      eUS   u  nn[7        [9        UR:                  R=                  U5      U
5      5      n
UR?                  SXUS9$ ! [        R                   a    [        USR                  U5      5      ef = f! [        R                   a    [        USR                  U5      5      e[        R"                   a    [        USR                  U5      5      ef = f)a  Parse a URL into a Resource.

Searches self.parsers_by_url to find a _ResourceParser. The parsers_by_url
attribute is a deeply nested dictionary, indexed by API name, API version,
then a series of keys corresponding to URL segments (split on '/') after the
API's base URL. Each of these keys can be either a literal segment (e.g.
"projects" in
"https://compute.googleapis.com/compute/v1/projects/{projectsId}/..."), in
which case it must match exactly, or a wildcard parameter ("{}"), in which
case it can match any token. For the URL provided, the API name (and if
unspecified, the API version) is extracted from the base URL, then a path
down the tree is followed, branching at each remaining token in the URL. If
there are no URL tokens left, and one of the keys at the current level is
None, the None points to a _ResourceParser that can turn the collected
params into a Resource.

Args:
  url: str, The URL of the resource.
  api_version: str, The API client version to use for parsing. For
    channel-based versioned clients, this argument is not needed as it
    can always be inferred from the URL. For interface-based versioned
    clients (as of 2024), this argument can be used to explicitly specify a
    client version (since multiple clients can share the same URL API
    version). If not provided, defaults to the API version in the URL.

Returns:
  Resource, The resource indicated by the provided URL.

Raises:
  InvalidResourceException: If the provided URL could not be turned into
      a cloud resource.
zunknown API host)rW   zunknown api {}zunknown api version {}r   Nr  r   r  zCould not parse at [{}]r^  zUrl too short.r   ) _URL_REr   rR   resource_utilSplitEndpointUrlr   _GetVersionsr   UnknownAPIErrorr'   rw  r}  r   r  r   r   r  UnknownVersionErrorr|  r   r   r   rD   appendr   r   r   r   r   r|   r   r   )r(   urlru   r   r   url_api_versionresource_pathversionsr  endpointrC   r  ir  r$   
next_levelr   r  s                     r   ParseURLRegistry.ParseURL  s   B MM#E$S1CDD 	&&s+ -H}0KM++H5h "	x	(	(**..m66x@B "$
'..{;= = $}':':3'??F'S''(H=
X? F##If%		$	 bZ"}}Y7
%D=
  8 '188?A 	A 
ZA	$*"4$fll**512	 mmFLL((/0 i5 &: 9$S*:;;%dOM6#f,,66}EvNOF!!f# " % %{ $$ M$S*:*A*A(*KLLM( $$ M$S*:*A*A(*KLL(( =$
'..{;= ==s   I ,J 0I>AKc                     U R                  X$S9n[        UR                  R                  UR                  R                  5      nUR                  R                  U5      nUR                  XXs5      $ )z:Parser relative names. See Resource.RelativeName() method.r  )r  r  r|   r   ru   GetSubcollectionr   )r(   r   r   r   ru   r  r   r   s           r   r   Registry.ParseRelativeNameH  sm     (((MFV33<<#33??AH**;;JGM##> >r   c                    [         R                  U5      nU(       d  [        US5      eUR                  S5      (       aL  U(       a  US:w  a  [	        SUU5      eU R                  SSUR                  S5      UR                  S5      S.S9$ U(       a  US:w  a  [	        SX!5      eU R                  SSS	UR                  S5      0S9$ )
z;Parse gs://bucket/object_path into storage.v1 api resource.zNot a storage urlr   storage.objectsNr^  bucketobjectr   r   r   storage.bucketsr  )_GCS_URL_REr   rR   groupr\   r   )r(   r  r   r   s       r   ParseStorageURLRegistry.ParseStorageURLS  s    c"E$S*=>>{{1~~	
&77./@*/24 	4!!&!KKNekk!nE " G G
 j$55,->
PP$%++a.)   + +r   c           	         U(       a  UR                  S5      (       d  UR                  S5      (       a]   U R                  X5      nU(       aB  U(       a;  UR                  5       U:w  a'  [        UUR                  5       UR                  5       S9eU$ UR                  S5      (       a  U R                  XS9$ U(       a  Ub  U(       d  [        U5      eU R                  X1U=(       d    0 UUUS9$ ! [         Gav  n	Sn
[        R                  " [
        5      n[        R                  " [        5      n[        R                  " [        5      nUR                  U5      (       a=   U[        U5      S R                  SS5      u  pnnO! [         a    U	ef = fX4S:w  a  e OUR                  U5      (       a    U[        U5      S R                  SS5      u  pnnO! [         a    U	ef = fX4S:w  a  e O]! [         aP  n	U[        U5      S nSU;   a  UR                  SS5      u  n
n Sn	A	O%U R                  SSS	U0S
9s Sn	A	s Sn	A	$ Sn	A	ff = fU
b  U R                  SSU
WS.S
9s Sn	A	$ e Sn	A	ff = f)a  Parse a Cloud resource from a command line.

Args:
  line: str, The argument provided on the command line.
  params: {str:(str or func()->str)}, flags (available from context) or
    resolvers that can help parse this resource. If the fields in
    collection-path do not provide all the necessary information, params
    will be searched for what remains.
  collection: str, The resource's collection, or None if it should be
    inferred from the line.
  enforce_collection: bool, fail unless parsed resource is of this
    specified collection, this is applicable only if line is URL.
  validate: bool, Validate syntax. Use validate=False to handle IDs under
    construction.
  default_resolver: func(str) => str, a default param resolver function
    called if params doesn't resolve a param.
  api_version: str, The API version, None for the default version.

Returns:
  A resource object.

Raises:
  InvalidResourceException: If the line is invalid.
  RequiredFieldOmittedException: If resource is underspecified.
  UnknownCollectionException: If no collection is provided or can be
      inferred.
  WrongResourceCollectionException: If the provided URL points into a
      collection other than the one specified.
zhttps://zhttp://Nr      )bor^  r  r  r  r  r  r_   zgs://r   )ru   r   r   )r_  r  rR   r   r   _GCS_URL_GCS_ALT_URL_GCS_ALT_URL_SHORTr   r   r   r   r   r\   r	  r  )r(   rV   rC   r   enforce_collectionr   r   ru   r   er  gcs_urlgcs_alt_urlgcs_alt_url_shortbucket_prefixobject_prefix
objectpaths                    r   r  Registry.Parseh  s   > 		$	$	(B(B(	d0#T :NN
*0!.."<<># # 
??7####D#@@D$T$T**
&,B,7)11A   C Cm ( &	&!33H='%77E++== "
__W%%s7|}%++C3 ?m]J g-; <011-[)*+11#q9 A}j /:= >+ -#/012d%)ZZQ%7"
++0 $$d+ , - - -- '', "(J? ( A A M&	s   C. .I/9A&I* "FI*F"I*4"GG0G$$G0/I*0
I
:)I#I*(I:I
;I*?I/I

I*#I/)I**I/c                 "    U R                  SXS9$ )zCreate a Resource from known collection and params.

Args:
  collection: str, The name of the collection the resource belongs to.
  **params: {str:str}, The values for each of the resource params.

Returns:
  Resource, The constructed resource.
NrB   )r  )r(   r   rC   s      r   CreateRegistry.Create  s     ::dz:AAr   r{  )NNNrZ   )TNN)FN)NNTTNN)r   r   r   r   r   r&   r  r  r  r  r  r   r   r  r   r  r  r  r   r   r   r   ry  ry  	  sz     AE#154PB,.. GK9=9Ev"k%Z GL$(	>+* JN>B\C|
Br   ry  c                     [        [        R                  R                  U S5      nSnUb  [	        UR                  5       X5      nU$ )a'  Determine base url to use for resources of given version from API endpoint override.

If no override is set by the user, return None.

Args:
  api_name: str, The API name.
  api_version: str, The API version.

Returns:
  Base URL of the API namespace, with API version, None if no override set.
N)r   r
   r,  rs  _GetApiBaseUrlr1  )r   ru   endpoint_override_propertyr   s       r   r  r    sM      '..$ @(+"&&((H 
/r   c                 V    [        X5      nUc  [        SR                  U 5      5      eU$ )aZ  Determine base url to use for resources of given version using current override endpoint for this resource name.

If no override is found, raise an error.

Args:
  api_name: str, The API name.
  api_version: str, The API version.

Returns:
  Base URL of the API namespace, with API version.

Raises:
  UserError: If override endpoint is not set.
zLgcloud config property {} needs to be set in api_endpoint_overrides section.)r  rO   r'   )r   ru   api_base_urls      r   GetApiBaseUrlOrThrowr    s8     x5,
	6(#% % 
r   c                 :    [        X5      nUc  [        X U5      $ U$ )av  Determine base url to use for resources of given version using current override endpoint for this resource name.

If no override is found, returns the default base url, with API version.

Args:
  api_name: str, The API name.
  api_version: str, The API version.
  default_base_url: str, The default API endpoint.

Returns:
  Base URL of the API namespace, with API version.
)r  r  )r   ru   default_base_urlr  s       r   GetApiBaseUrlOrDefaultr    s(     x5,*kBB	r   c                     U nUbO  [         R                  " X5      n[        R                  " U5      u  pVnUc  X2S-   -  n[         R                  " U5      nU$ )zXDetermine base url to use for resources of given API version from the supplied base url.r   )r   _GetBaseUrlFromApir  r  r   )r   r   ru   r  client_base_url_url_versions          r   r  r    s]    , $66xMO%66GAAC''l 22<@L	r   )?r   
__future__r   r   r   r   r   googlecloudsdk.api_lib.utilr   r   r   r  googlecloudsdk.corer	   r
   r   	six.movesr   r   r   r   _COLLECTION_SUB_REcompiler  r'   _METHOD_ID_REr  r  r  r  	Exceptionr   r   r!   r/   r7   r>   rG   rO   rR   r\   re   rk   rq   r  rx   r   r   r3  r5  r7  r;  r@  rF  r   r   rw  ry  REGISTRYr  r  r  r  r   r   r   <module>r     s   '  '  	 5 1 A * * 
    6  **9
:

?FF! G # $jj343;6 $I $45 4:5 :#E #EE E>% >5 52
  % 2<y <	y 	AI A= => >lBf lB^@v @FK	"9 
 , \ L 	| 	M-& M-`!GBv GBT :..&r   