
    cQ                        S 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	Jr  SS
KJr  SSKr\R                   R#                  5        V s/ s H  n \R%                  U 5      PM     sn 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 " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S \5      r " S! S"\R@                  " \RB                  5      5      r" " S# S$\#5      r$ " S% S&\#5      r% " S' S(\%5      r&gs  sn f ))z4Utility for retrieving and parsing the Resource Map.    )absolute_import)division)unicode_literalsN)base)
exceptions)yaml)yaml_validator)filesc                       \ rS rSrSrSrg)ResourceMapError#   zGeneral Purpose Exception. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       8lib/googlecloudsdk/command_lib/util/resource_map/base.pyr   r   #   s    "r   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ResourceMapInitializationError'   zGException for when an error occurs while initializing the resource map.c                 J   > [         [        U ]  SR                  U5      5        g )Nz+Error while initializing resource map: [{}])superr   __init__format)self
init_error	__class__s     r   r   'ResourceMapInitializationError.__init__*   s&    	
(
;;A6*;MOr   r   r   r   r   r   r   r   r   __classcell__r    s   @r   r   r   '   s    OO Or   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )PrivateAttributeNotFoundError0   zFException for when a private attribute that doesn't exist is accessed.c                 J   > [         [        U ]  SR                  X5      5        g )Nz*[{}] does not have private attribute [{}].)r   r&   r   r   )r   data_wrapperattribute_namer    s      r   r   &PrivateAttributeNotFoundError.__init__3   s'    	
'
ELL, -r   r   r"   r$   s   @r   r&   r&   0   s    N- -r   r&   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ApiNotFoundError9   z<Exception for when an API does not exist in the ResourceMap.c                 J   > [         [        U ]  SR                  U5      5        g )Nz"[{}] API not found in ResourceMap.)r   r-   r   r   r   api_namer    s     r   r   ApiNotFoundError.__init__<   s"    	

=DDXNOr   r   r"   r$   s   @r   r-   r-   9   s    DP Pr   r-   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ApiAlreadyExistsErrorA   zHException for when an API being added already exists in the ResourceMap.c                 J   > [         [        U ]  SR                  U5      5        g Nz'[{}] API already exists in ResourceMap.)r   r4   r   r   r0   s     r   r   ApiAlreadyExistsError.__init__D   s"    	
/188BDr   r   r"   r$   s   @r   r4   r4   A   s    PD Dr   r4   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ResourceNotFoundErrorI   z8Exception for when a Resource does not exist in the API.c                 J   > [         [        U ]  SR                  U5      5        g )Nz'[{}] resource not found in ResourceMap.)r   r:   r   r   )r   resource_namer    s     r   r   ResourceNotFoundError.__init__L   s"    	
/188GIr   r   r"   r$   s   @r   r:   r:   I   s    @I Ir   r:   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ResourceAlreadyExistsErrorQ   zLException for when a Resource being added already exists in the ResourceMap.c                 J   > [         [        U ]  SR                  U5      5        g r7   )r   r@   r   r   r0   s     r   r   #ResourceAlreadyExistsError.__init__T   s"    	
$d4188BDr   r   r"   r$   s   @r   r@   r@   Q   s    TD Dr   r@   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )MetadataNotFoundErrorY   CException for when a metadata field does not exist in the Resource.c                 J   > [         [        U ]  SR                  X!5      5        g )Nz/[{}] metadata field not found in [{}] Resource.)r   rE   r   r   r   r=   metadata_fieldr    s      r   r   MetadataNotFoundError.__init__\   s$    	
/9@@	+,r   r   r"   r$   s   @r   rE   rE   Y       K, ,r   rE   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )#TrackLevelResourceReleaseTrackErrorb   zGException for when an attempt to access a releast track of a RT occurs.c                 J   > [         [        U ]  SR                  X5      5        g )Nz?Attempted accessing of [{}] track of TrackLevelResourceData[{}])r   rN   r   r   )r   attempted_rtaccessed_rtr    s      r   r   ,TrackLevelResourceReleaseTrackError.__init__e   s&    	
-
#VL>@r   r   r"   r$   s   @r   rN   rN   b   s    O@ @r   rN   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )MetadataAlreadyExistsErrorl   rG   c                 J   > [         [        U ]  SR                  X!5      5        g )Nz.[{}] metadata already exists in [{}] Resource.)r   rU   r   r   rI   s      r   r   #MetadataAlreadyExistsError.__init__o   s$    	
$d48??	+,r   r   r"   r$   s   @r   rU   rU   l   rL   r   rU   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )UnwrappedDataExceptionu   z6Exception for when unwrapped data is added to the map.c                 J   > [         [        U ]  SR                  X5      5        g )NzhThe following data must be wrapped in a(n) {}Data wrapper prior to being added to the resource map: [{}])r   rZ   r   r   )r   
field_typedatar    s      r   r   UnwrappedDataException.__init__x   s"    	
 $0	0	
	!#r   r   r"   r$   s   @r   rZ   rZ   u   s    ># #r   rZ   c                       \ rS rSrSrS rS rS rS rS r	\
R                  S 5       rS	 rSS jrS rS rS rS rS rS rS rSS jrSrg
)ResourceMapBase   a  Base data wrapper class for Resource Map metadata yaml files.

This object loads the relevant resource map file upon instantiation and sets
the parsed dictionary as the internal attribute _resource_map_data. Underlying
dictionary data is never interacted with directly, and is instead is
set/retrieved/interacted with via an ApiData wrapper object.

Attributes:
  _resource_map_data: Dict containing metadata for each resource in each api.
c                 n    S U l         S U l        U R                  5         0 U l        U R	                  5         g N)_map_file_path_schema_file_path_register_paths_resource_map_data_load_resource_mapr   s    r   r   ResourceMapBase.__init__   s2    D!D Dr   c                 h    UR                  S5      (       a  [        SU5      eU R                  U5      $ )z5Returns underlying API data when accessing attribute._ResourceMap)
startswithr&   get_apir   r1   s     r   __getattr__ResourceMapBase.__getattr__   s/    3)-BB<<!!r   c                     XR                   ;   $ )z;Returns True if api_name exists in self._resource_map_data.rh   rq   s     r   __contains__ResourceMapBase.__contains__   s    ....r   c              #   x   #    [         R                  " U R                  5       H  u  p[        X5      v   M     g7f)zBYields ApiData wrapper objects for each API in _resource_map_data.N)six	iteritemsrh   ApiDatar   r1   api_datas      r   __iter__ResourceMapBase.__iter__   s-     !mmD,C,CDH'' Es   8:c                 D    U R                  5       UR                  5       :H  $ rd   to_dictr   others     r   __eq__ResourceMapBase.__eq__       <<>U]]_,,r   c                     g)zMust be overridden by child classes to register map and schema paths.

Must explicitly set self._map_file_path and self._schema_file_path to
appropriate filepaths in the overridden method of the child class.
Nr   rj   s    r   rg   ResourceMapBase._register_paths   s     	r   c                 0    [         R                  " U R                  5       n[        R                  " U5      U l        SSS5        U R
                  (       d  0 U l        gg! , (       d  f       N(= f! [         R                   a  n[        U5      eSnAff = f)z@Loads the ~/resource_map.yaml file into self._resource_map_data.N)r
   
FileReaderre   r   loadrh   MissingFileErrorr   )r   ferrs      r   ri   "ResourceMapBase._load_resource_map   ss    0D//0A"&))A, 1$$"$ % 10 !! 0*3//0s-    A1 A  A1  
A.*A1 1BBBNc                 t    U(       a  U R                  5         U(       a  U R                  5         [        R                  " U=(       d    U R                  5       n[
        R                  " U R                  US9  SSS5        g! , (       d  f       g= f! [        R                   a  n[        U5      eSnAff = f)zBPrunes and exports self._resource_map_data to ~/resource_map.yaml.)streamN)
prune_validate_resource_mapr
   
FileWriterre   r   dumprh   r   r   )r   	file_pathr   validater   r   s         r   _export_resource_map$ResourceMapBase._export_resource_map   s}    0	

	##%I<)<)<=		$))!4 >==!! 0*3//0s6   AB  B9B 
BB B B7'B22B7c                 v    [         R                  " U R                  5      R                  U R                  5        g)z:Validates resource map against ~/resource_map_schema.yaml.N)r	   	Validatorrf   Validaterh   rj   s    r   r   &ResourceMapBase._validate_resource_map   s*    T334==!r   c                     U R                   $ rd   ru   rj   s    r   r   ResourceMapBase.to_dict   s    """r   c                 H    [        U 5       H  nUR                  5         M     g)a  Prunes the resource map, removing redundant metadata values in the map.

Calls prune() on each ApiData wrapper object, which in turn calls prune()
on each underlying resource. Pruning each resource will remove any instances
of a track-specific metadata field being set to the same value as the parent
resource metadata field, eliminating any redundancies and keeping the map
as clean as possible.
Niterr   r   r}   s     r   r   ResourceMapBase.prune   s     Jnn r   c                 f    XR                   ;  a  [        U5      e[        XR                   U   5      $ )z2Returns the api data wrapped in an ApiData object.)rh   r-   r{   rq   s     r   rp   ResourceMapBase.get_api   s/    ...X&&844X>??r   c                    [        U[        5      (       d  [        SU5      eUR                  5       U R                  ;   a  [        UR                  5       5      eU R                  R                  UR                  5       5        g)a,  Adds an api to the resource map.

Args:
  api_data: Data for api being added. Must be wrapped in an ApiData object.

Raises:
  ApiAlreadyExistsError: API already exists in resource map.
  UnwrappedDataException: API data attempting to be added without being
    wrapped in an ApiData wrapper object.
ApiN)
isinstancer{   rZ   get_api_namerh   r4   updater   r   s     r   add_apiResourceMapBase.add_api   sf     h(("5(33				 D$;$;	;!("7"7"9::
$$X%5%5%78r   c                    [        U[        5      (       d  [        SU5      eUR                  5       U R                  ;  a  [        UR                  5       5      eU R                  R                  UR                  5       5        g)a@  Updates an API's data with the provided api data.

Args:
  api_data: API Data to update the api with. Must be provided as an ApiData
  object.

Raises:
  ApiNotFoundError: Api to be updated does not exist.
  UnwrappedDataException: API data attempting to be added without being
    wrapped in an ApiData wrapper object.
r   N)r   r{   rZ   r   rh   r-   r   r   r   s     r   
update_apiResourceMapBase.update_api   sf     h(("5(33d&=&==X22455
$$X%5%5%78r   c                 R    XR                   ;  a  [        U5      eU R                   U	 g)z%Removes an API from the resource map.N)rh   r-   rq   s     r   
remove_apiResourceMapBase.remove_api  s'    ...X&&)r   c                 &    U R                  U5        g)z-Public method to export resource map to file.N)r   )r   r   s     r   exportResourceMapBase.export	  s    i(r   )re   rh   rf   )NFTrd   )r   r   r   r   r   r   rr   rv   r~   r   abcabstractmethodrg   ri   r   r   r   r   rp   r   r   r   r   r   r   r   r   ra   ra      sm    	"/(
- 	 	0
0!
#@9$9&*)r   ra   c                   p    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rSS jrS rSrg)r{   i  zData wrapper for an API object in the Resource Map metadata file.

Attributes:
  _api_name: Name of the API.
  _api_data: Dict of resources and associated metadata constituting the api.
c                     Xl         X l        g rd   )	_api_name	_api_datar|   s      r   r   ApiData.__init__  s    NNr   c                     UR                  S5      (       a  [        SU5      e[        XR                  U R                  U   5      $ )zGReturns the specified resource's data wrapped in a ResourceData object.rm   r{   )ro   r&   ResourceDatar   r   r   r=   s     r   rr   ApiData.__getattr__  s?    $$))]CC~~}57 7r   c                     XR                   ;   $ rd   )r   r   s     r   rv   ApiData.__contains__!  s    NN**r   c              #      #    U R                   R                  5        H  u  p[        XR                  U5      v   M     g7f)zGYields ResourceData wrapper objects for each API in _resource_map_data.N)r   itemsr   r   )r   r=   resource_datas      r   r~   ApiData.__iter__$  s0     (,(<(<(>$FF )?s   =?c                 ,    [        U R                  5      $ rd   )reprr   rj   s    r   __repr__ApiData.__repr__)  s    r   c                 D    U R                  5       UR                  5       :H  $ rd   r   r   s     r   r   ApiData.__eq__,  r   r   c                 J    [         R                  " U R                  5       5      $ rd   )ry   	text_typer   rj   s    r   to_strApiData.to_str/  s    ==((r   c                 :    U R                  5       U R                  0$ rd   )r   r   rj   s    r   r   ApiData.to_dict2  s    00r   c                 B    [         R                  " U R                  5      $ rd   )ry   r   r   rj   s    r   r   ApiData.get_api_name5  s    ==((r   c                 |    XR                   ;  a  [        U5      e[        XR                  U R                   U   5      $ )zEReturns the data for the specified resource in a ResourceData object.)r   r:   r   r   r   s     r   get_resourceApiData.get_resource8  s6    NN*!-00~~}57 7r   c                    [        U[        5      (       d  [        SU5      eUR                  5       U R                  ;   a  [        UR                  5       5      eU R                  R                  UR                  5       5        g NResource)r   r   rZ   get_resource_namer   r@   r   r   r   r   s     r   add_resourceApiData.add_resource?  s`    m\22":}==		(	(	*dnn	<&}'F'F'HII
nnM1134r   c                    [        U[        5      (       d  [        SU5      eUR                  5       U R                  ;  a  [        UR                  5       5      eU R                  R                  UR                  5       5        g r   )r   r   rZ   r   r   r:   r   r   r   s     r   update_resourceApiData.update_resourceG  s`    m\22":}==		(	(	*$..	@!-"A"A"CDD
nnM1134r   c                 `    U(       a  XR                   ;  a  [        U5      eU R                   U	 g rd   )r   r:   )r   r=   
must_exists      r   remove_resourceApiData.remove_resourceO  s%    m>>9!-00}%r   c                 H    [        U 5       H  nUR                  5         M     g rd   r   r   s     r   r   ApiData.pruneT  s    d $r   )r   r   N)T)r   r   r   r   r   r   rr   rv   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r{   r{     sN    7+G
 -)1)755&
r   r{   c                      ^  \ rS rSrSrS rS rU 4S jrS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rSrU =r$ )r   iY  zData wrapper for a Resource object in the ResourceMap metadata file.

Attributes:
  _resource_name: Name of the resource.
  _api_name: Name of the parent api.
  _resource_data: Metadata for the resource.
c                 (    Xl         X l        X0l        g rd   )_resource_namer   _resource_data)r   r=   r1   r   s       r   r   ResourceData.__init__b  s    'N'r   c                     U[         ;   a  U R                  U5      $ UR                  S5      (       a  [        SU5      eU R	                  U5      $ )a  Returns metadata value or TrackLevelResourceData object.

Attribute being accessed will be either a metadata field for the resource,
or the release track (GA, BETA, or ALPHA). If the attribute is a metadata
field the appropriate value will be returned from self._resource_data. If
the atatribute is a release track, a TrackLevelResourceData object will be
returned. This enables both of the following usecases:

  `value = map.api.resource.metadata_field` OR
  'value = map.api.resource.ALPHA.metadata_field`

Args:
  metadata_field: Field or release track being accessed

Returns:
  Metadata field value OR TrackLevelResourceData object.

Raises:
  MetadataNotFoundError: Metadata field does not exist.
  PrivateAttributeNotFoundError: Private attribute doesn't exist in object.

rm   r   )_RELEASE_TRACKSget_release_track_dataro   r&   get_metadatar   rJ   s     r   rr   ResourceData.__getattr__g  sL    . (((88		"	"3	'	')..II~..r   c                    > UR                  S5      (       a  [        [        U ]  X5        gXR                  ;  a  U R                  X5        gU R                  X5        g)a  Sets the specified metadata field to the provided value.

If the object is not yet instantiated, then standard __setattr__ behavior
is observed, allowing for proper object instantiation. After initialization,
the specified metadata field within self._resource_data is set to the
provided value

Args:
  metadata_field: Metadata field to set the value for.
  value: Value to set the specified metadata field to.

Returns:
  True
rm   N)ro   r   r   __setattr__r   add_metadataupdate_metadatar   rJ   valuer    s      r   r   ResourceData.__setattr__  sM        %%L$+NB	22	2
.
>1r   c                 D    U R                  5       UR                  5       :H  $ rd   r   r   s     r   r   ResourceData.__eq__  r   r   c                 $    U R                  U5      $ rd   )has_metadata_fieldr   s     r   rv   ResourceData.__contains__  s    "">22r   c                    [          H  nXR                  ;   d  M  U R                  U   n[        UR                  5       5       H-  nX0R                  ;   d  M  U R                  U   X#   :X  d  M+  X#	 M/     U(       a  Mv  U R                  U	 M     g)zDRemoves any redundant metadata specifications between track and top.N)r   r   listkeys)r   tracktrack_resource_datakeys       r   r   ResourceData.prune  s     	%%	%"11%8+0023C'''D,?,?-).-/#( 4
 #"!!%( !r   c                 :    U R                  5       U R                  0$ rd   )r   r   rj   s    r   r   ResourceData.to_dict  s    ""$d&9&9::r   c                     XR                   ;   $ rd   )r   r   s     r   r   ResourceData.has_metadata_field  s    0000r   c                     U R                   $ rd   )r   rj   s    r   r   ResourceData.get_resource_name  s    r   c                     U R                   $ rd   )r   rj   s    r   r   ResourceData.get_api_name  s    >>r   c                 ^    SR                  U R                  5       U R                  5       5      $ )Nz{}.{})r   r   r   rj   s    r   get_full_collection_name%ResourceData.get_full_collection_name  s%    >>$++-t/E/E/GHHr   c                 j    XR                   ;  a  [        U R                  U5      eU R                   U   $ rd   r   rE   r   r   s     r   r   ResourceData.get_metadata  s2    000!$"5"5~FF~..r   c                 V    [        U R                  U R                  U R                  US9$ )Nr  )TrackLevelResourceDatar   r   r   r   release_tracks     r   r   #ResourceData.get_release_track_data  s+    !	 r   c                 j    XR                   ;   a  [        U R                  U5      eX R                   U'   g rd   )r   rU   r   r   rJ   r   s      r   r   ResourceData.add_metadata  s/    ,,,&t':':NKK,1.)r   c                 j    XR                   ;  a  [        U R                  U5      eX R                   U'   g rd   r  r  s      r   r   ResourceData.update_metadata  s/    000!$"5"5~FF,1.)r   c                 h    XR                   ;  a  [        U R                  U5      eU R                   U	 g rd   r  r   s     r   remove_metadataResourceData.remove_metadata  s/    000!$"5"5~FF


n
-r   )r   r   r   )r   r   r   r   r   r   rr   r   r   rv   r   r   r   r   r   r  r   r   r   r   r"  r   r#   r$   s   @r   r   r   Y  s^    (
/<2.-3);1I/
22. .r   r   c                   h   ^  \ rS rSrSrU 4S jrS rU 4S jrS rS r	S r
S	 rS
 rS rS rSrU =r$ )r  i  a  Data wrapper for track-specific resource metadata.

This data wrapper represents the metadata for a specific release track of a
resource. Retrieval of metadata will first check for a track level
specification of the metadata, and if not found will then retrieve the
top level metadata value.

Attributes:
  _resource_name: Name of the resource.
  _api_name: Name of the parent api.
  _resource_data: Metadata for the resource.
  _track: Release track for the resource.
  _track_resource_data: Track specific metadata for the resource.
c                 |   > X@l         UR                  U R                   0 5      U l        [        [        U ]  XU5        g rd   )_trackget_track_resource_datar   r  r   )r   r=   r1   r   r  r    s        r   r   TrackLevelResourceData.__init__  s7    K - 1 1$++r BD	
 $01>@r   c                 h    UR                  S5      (       a  [        SU5      eU R                  U5      $ )a"  Retrieves the track-specific metadata value for the resource.

If the specified release track does not have a specified value, the parent
metadata field value for the resource will be returned.

Args:
  metadata_field: Metadata field value to retrieve

Returns:
  Metadata field value for the specified release track-specific or the
  parent metadata field.

Raises:
  MetadataNotFoundError: Metadata field value wasn't found for the specific
  track or for the parent.
  PrivateAttributeNotFoundError: Private attribute doesn't exist in object.
rm   r  )ro   r&   r   r   s     r   rr   "TrackLevelResourceData.__getattr__  s;    $   %%)*B*8: : ~..r   c                    > UR                  S5      (       a  [        [        U ]  X5        gXR                  ;   a  U R                  X5      $ U R                  X5      $ )a  Sets the specified metadata field to the provided value.

If the object is not yet instantiated, then standard __setattr__ behavior
is observed, allowing for proper object intitialization. After
initialization, the specified metadata field for the release track is set
to the provided value.

Args:
  metadata_field: Metadata field to set the value for.
  value: Value to set the specified metadata field to.

Returns:
  True
rm   N)ro   r   r  r   r(  r   r   r   s      r   r   "TrackLevelResourceData.__setattr__  sT        %%"D5nL	44	4##N::  77r   c                 2    U R                   U R                  0$ rd   )r   r   rj   s    r   r   TrackLevelResourceData.to_dict$  s    !4!455r   c                     XR                   ;   a  U R                   U   $ XR                  ;   a  U R                  U   $ [        U R                  U5      erd   )r(  r   rE   r   r   s     r   r   #TrackLevelResourceData.get_metadata'  sO    222&&~66	..	.  00!$"5"5~FFr   c                 j    XR                   ;   a  [        U R                  U5      eX R                   U'   g rd   )r(  rU   r   r  s      r   r   #TrackLevelResourceData.add_metadata/  s/    222&t':':NKK27/r   c                 j    XR                   ;  a  [        U R                  U5      eX R                   U'   g rd   r(  rE   r   r  s      r   r   &TrackLevelResourceData.update_metadata5  s/    666!$"5"5~FF27/r   c                 h    XR                   ;  a  [        U R                  U5      eU R                   U	 g rd   r5  r   s     r   r"  &TrackLevelResourceData.remove_metadata;  s/    666!$"5"5~FF

#
#N
3r   c                     U R                   $ rd   )r&  rj   s    r   get_release_track(TrackLevelResourceData.get_release_trackA  s    ;;r   c                 ,    [        XR                  5      erd   )rN   r&  r  s     r   r   -TrackLevelResourceData.get_release_track_dataD  s    
-m[[
IIr   )r&  r(  )r   r   r   r   r   r   rr   r   r   r   r   r   r"  r:  r   r   r#   r$   s   @r   r  r    sC    @/0806G884J Jr   r  )'r   
__future__r   r   r   r   googlecloudsdk.callioper   calliope_basegooglecloudsdk.corer   r   r	   googlecloudsdk.core.utilr
   ry   ReleaseTrack	AllValuesr   r   Errorr   r   r&   r-   r4   r:   r@   rE   rN   rU   rZ   with_metaclassABCMetara   objectr{   r   r  r  s   0r   <module>rI     sN   ; &  ' 
 9 * $ . * 
 '4&@&@&J&J&L&LUCMM%&L
#z'' #O%5 O-$4 -P' PD, DI, ID!1 D,, ,@*: @,!1 ,#- #L)c((5 L)^Hf HVB.6 B.JgJ\ gJAs   D?