
                         |   d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddlm	Z	 ddlm
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ ddlm
Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddl Z dZ! ejD                         Z#d Z$ddZ%d Z& G d de	jN                        Z(y)z.Implementation of CloudApi for s3 using boto3.    )absolute_import)division)unicode_literalsN)	cloud_api)errors)headers_util)request_config_factory)xml_metadata_field_converters)xml_metadata_util)storage_url)resource_reference)resource_util)s3_resource_reference)download_util)
exceptions)log)
properties)retry)scaled_integerl        c                     | j                   j                  di       j                  d      dk(  r$t        j                  dj	                  |            y )NResponseMetadataHTTPStatusCodei  z{} not found: 404.)responsegetr   NotFoundErrorformat)errorresource_names     3lib/googlecloudsdk/api_lib/storage/s3_xml/client.py_raise_if_not_found_errorr    4   sM    
^^*B/334DEL 

3::=I
JJ M    c                     t        j                  t        j                  j                  dt         j
                  fg|       S )a  Decorator that catches botocore ClientErrors and raises XmlApiErrors.

  Args:
    format_str (str): A googlecloudsdk.api_lib.storage.errors.S3ErrorPayload
      format string. Note that any properties that are accessed here are on the
      S3ErrorPayload object, not the object returned from botocore.

  Returns:
    A decorator that catches botocore.exceptions.ClientError and returns an
      XmlApiError with a formatted error message.
  N
format_str)r   !catch_error_raise_cloud_api_errorbotocorer   ClientErrorXmlApiErrorr#   s    r   &_catch_client_error_raise_s3_api_errorr)   ;   s9     
	1	1''v/A/ABC
 r!   c                     t        | j                  xrF | j                  j                  xs. | j                  j                  xs | j                  j                        S )zBChecks if RequestConfig has ACL setting aside from predefined ACL.)boolresource_argsacl_grants_to_addacl_grants_to_removeacl_file_path)request_configs    r   _modifies_full_acl_policyr1   N   sT    	"" 

&
&
8
8 8))>>8))77
 r!   c                      e Zd ZdZej
                  j                  hZdZdZ	e
j                  j                  Zd Zd ZddZ e       dd       Z e       d        Zdej(                  j*                  dfd	Zej(                  j*                  fd
Zd Zej(                  j*                  fdZ e       	 	 	 	 dd       Z e       d        Zd Zd Z e       ddej<                  j>                  dddfd       Z  e       	 	 	 	 dd       Z!ddddddejD                  jF                  dfdZ$ e       	 	 	 dd       Z%d Z&d Z' e       ddddejP                  jR                  fd       Z*y)S3XmlClientzS3 XML Client.Nc                     t         j                  j                  j                  j	                         | _        | j                         | _        y N)r   VALUESstorages3_endpoint_urlGetendpoint_urlcreate_clientclient)selfs    r   __init__zS3XmlClient.__init__f   s5    "))11AAEEGD$$&DKr!   c                     ~t        j                         }|j                         D ]!  \  }}|j                  j	                  ||       # y r5   )r   get_additional_header_dictitemsheaders
add_header)r=   requestkwargsrB   keyvalues         r   "_add_additional_headers_to_requestz.S3XmlClient._add_additional_headers_to_requestj   s;    557Gmmo
Uoo  e, &r!   c           	         t         j                  j                  j                  j	                         }|rd}nd}t
        5  t        j                  t        j                  j                  j                  | j                  | j                  || j                  |      }|j                  j                   j#                  d| j$                         |cddd       S # 1 sw Y   yxY w)zCreates the Boto3 client.

    Args:
      resource_location: (string) The name of the region associated with the
        client.

    Returns:
      A boto3 client.
    FN)aws_access_key_idaws_secret_access_keyregion_namer:   verifyzbefore-sign.s3.*)r   r6   authdisable_ssl_validationGetBoolBOTO3_CLIENT_LOCKboto3r<   r   ProviderPrefixS3rG   access_key_idaccess_key_secretr:   metaeventsregister_firstrH   )r=   resource_locationrO   
verify_sslr<   s        r   r;   zS3XmlClient.create_clientp   s     	55==? j j	||

$
$
'
'
-
- .. $ 6 6'((f kk''
dEE  
		s    BCC c                    ~|j                   }|j                  r(| j                  |j                        }|j                  }n4| j                  }t        j
                  j                         j                  }|r*|j                  |j                  j                  d|i      }n&|j                  |j                  j                        }|j                  s`|j                  sT|j                  sH|j                  s<|j                  s0|j                   s$|j"                  s|j$                  s|j&                  r| j)                  ||      S |j+                  d      }t-        j.                  |j                  ||      S )See super class.LocationConstraint)BucketCreateBucketConfigurationr_   Location)locationmetadata)r,   rc   r;   r<   rR   sessionSessionrL   create_bucketr   bucket_namecors_file_pathlabels_file_pathlifecycle_file_path
log_bucketlog_object_prefixrequester_pays
versioningweb_error_pageweb_main_page_suffixpatch_bucketr   r   S3BucketResource)	r=   bucket_resourcer0   fields_scoper,   r<   location_constraintrd   backend_locations	            r   rg   zS3XmlClient.create_bucket   sI    	"00M!!-"8"89f)22{{f!MM113??%% ,,88%9;N$O & Qh %% ,,88 & :h 	$$(F(F))]-E-E''=+G+G  M$@$@**??||J/ 11##! r!   c                 <    ~| j                   j                  |      S )r]   ra   )r<   delete_bucket)r=   rh   r0   s      r   ry   zS3XmlClient.delete_bucket   s     	;;$$K$88r!   Fc           	         d|i}	 |j                  | j                  j                  |             |t        j                  j                  u r!t        j                  | j                  ||      S d| j                  j                  dfd| j                  j                   dfd| j                  j"                  d	fd
| j                  j$                  dfd| j                  j&                  dfd| j                  j(                  d	fd| j                  j*                  d	ffD ](  \  }}}		  ||      }
|	r|
j-                  |      n|
||<   * |t        j                  j.                  u r 	 | j                  j1                  |      |d<   t        j                  | j                  ||      S # t        j                  j
                  $ r/}t        ||       t        j                  |      |d<   Y d}~d}~ww xY w# t        j                  j
                  $ r#}t        j                  |      ||<   Y d}~d}~ww xY w# t        j                  j
                  $ r"}t        j                  |      |d<   Y d}~d}~ww xY w)r]   Namera   r^   N	CORSRulesT!ServerSideEncryptionConfigurationLifecycleConfigurationFLoggingEnabledPayer
VersioningWebsiteACL)updater<   get_bucket_locationr&   r   r'   r    r   r(   r   FieldsScopeSHORTr   %get_bucket_resource_from_xml_responseschemeget_bucket_corsget_bucket_encryption"get_bucket_lifecycle_configurationget_bucket_loggingget_bucket_request_paymentget_bucket_versioningget_bucket_websiter   FULLget_bucket_acl)r=   rh   
generationru   soft_deletedrd   r   rF   api_callresult_has_key
api_results              r   
get_bucketzS3XmlClient.get_bucket   s3    $HAoodkk55 6   y,,222DD
++x  
dkk1148	,dkk.O.O			!		7	7	@	4;;994@	$++88$?	t{{88%@	DKK22E:
*%X~2[1
/=
s+:
*& y,,1114++44K4H BBX{ I ** A{3'-'9'9%'@h#$A4   ,, 2**512   ,, 4 ,,U34sG   +F   !G/ H2  G,=$G''G,/H/H**H/2I1I,,I1c              #   .  K   	 | j                   j                         }|d   D ]  }|t        j                  j                  k(  r| j                  |d   |       8t        j                  t        j                  t        j                  j                  |d         t        j                  |d         ||d   d        y# t        j                  j                   $ r2}t#        j$                  t'        j(                  |             Y d}~yd}~ww xY ww)r]   Bucketsr{   CreationDateOwner)r_   r   )creation_timerd   N)r<   list_bucketsr   r   r   r   r   rs   r   CloudUrlrS   rT   r   convert_datetime_object_to_utcr&   r   r'   core_exceptionsreraiser   r(   )r=   ru   r   bucketr   s        r   r   zS3XmlClient.list_buckets   s     9))+hY'&900555v=
=%66"";#=#=#@#@#)&>3)HH(* ##G, 	 ( ** 9f007889s/   DB>C DD (DDDDc                 ,   |j                   j                  |d<   	  |di | y # t        j                  j                  $ rR}t        ||j                   j                         t        j                  t        j                  |             Y d }~y d }~ww xY w)Nr_    )
r   rh   r&   r   r'   r    r   r   r   r(   )r=   rt   patch_functionpatch_kwargsr   s        r   _make_patch_requestzS3XmlClient._make_patch_request  st    ,88DDL+$|$** +'B'B'N'NO	ii""5)**+s   $ BABBc           	         |j                   }t        |      s|j                  ri }t        |      ryt        |dd      r#t	        j
                  |j                        |d<   nI| j                  j                  |j                  j                        }t        j                  ||      |d<   |j                  r|j                  |d<   | j                  || j                  j                  |       |j                  rF| j                  || j                  j                   dt	        j"                  |j                        i       |j$                  rF| j                  || j                  j&                  dt	        j(                  |j$                        i       |j*                  rF| j                  || j                  j,                  dt	        j.                  |j*                        i       |j0                  s|j2                  rQ| j                  || j                  j4                  d	t	        j6                  |j0                  |j2                        i       |j8                  rF| j                  || j                  j:                  d
t	        j<                  |j8                        i       |j>                  rF| j                  || j                  j@                  dt	        jB                  |j>                        i       |jD                  s|jF                  rQ| j                  || j                  jH                  dt	        jJ                  |jD                  |jF                        i       | jM                  |j                  j                  |      S )r]   r/   NAccessControlPolicyra   r   CORSConfigurationTaggingr~   BucketLoggingStatusRequestPaymentConfigurationVersioningConfigurationWebsiteConfiguration)ru   )'r,   r1   predefined_acl_stringgetattrr
   process_acl_filer/   r<   r   r   rh   r   ,get_acl_policy_with_added_and_removed_grantsr   put_bucket_aclri   put_bucket_corsprocess_corsrj   put_bucket_taggingprocess_labelsrk   "put_bucket_lifecycle_configurationprocess_lifecyclerl   rm   put_bucket_loggingprocess_loggingrn   put_bucket_request_paymentprocess_requester_paysro   put_bucket_versioningprocess_versioningrp   rq   put_bucket_websiteprocess_websiter   )r=   rt   r0   ru   r,   put_acl_kwargsexisting_acl_dicts          r   rr   zS3XmlClient.patch_bucket  s$   
 #00M 0,,n	">	2=/48+<<-- .
/ #kk88$00<< 9 >
  LL#^ .
/ 
	-	- . D Du
0J0J-/ ##


++
%
%!#@#M#M..$ %%


++
(
(6EE00 ((


++
8
8&/AA#77
 =#B#B


++
(
(#/??#..0O0O
 ##


++
0
0+/FF#22
 


++
+
+'/BB#..
 ##}'I'I


++
(
($/??#22#88 ??##//l  L Lr!   c                    t        |      rt        |j                  dd      }|rt        j                  |      }	n[| j
                  j                  |j                  j                  |j                  j                        }
t        j                  |
|      }	|j                  j                  |j                  j                  |	d} | j
                  j                  di | nd}	|j                  j                  |j                  j                  d}|j                  j                  r|j                  j                  |d<   |j                  j                  |j                  j                  |d}|rDd|d<   t        j                  t        j                  |j                  |j                        |       n=t        j                   |||	      r%d|d<   t        j"                  |j                  |       t        j$                  |||
        | j
                  j&                  di |}|r ||j(                         t        j*                  | j,                  ||d   |d   |	      S )r]   r/   Nr_   Key)r_   r   r   	VersionId)r_   r   
CopySourceREPLACEMetadataDirective)attributes_resourceknown_posix)posix_to_setr_   r   )acl_dictr   )r1   r   r,   r
   r   r<   get_object_aclr   rh   r   r   r   put_object_aclr   copy_object_metadatard   0is_user_metadata_field_present_in_request_configcopy_user_metadata_fields/update_object_metadata_dict_from_request_configcopy_objectsize%get_object_resource_from_xml_responser   )r=   source_resourcedestination_resourcer0   r   progress_callbackshould_deep_copy_metadatar   r/   r   r   r   source_kwargscopy_kwargscopy_responses                  r   r   zS3XmlClient.copy_object  s;    !0n::O"$m	0AA-P KK66'33??$00>> 7 @ JJ!> 	 )44@@%11??!)n
 !dkk  2>2h.::FF+77EEGM""--#2#>#>#I#ImK  '22>>#//==#K !)2k%&,,

0
0"++&&  
	K	K
1"

 ,5'(33$$k	
 EE^, ,DKK++:k:M,,-BBHE r!   c                     ~|j                   |j                  d}|j                  r|j                  |d<    | j                  j                  di |S )r]   r   r   r   )rh   r   r   r<   delete_object)r=   
object_urlr0   delete_object_kwargss       r   r   zS3XmlClient.delete_object  sZ     	 (('' *4*?*?;'$4;;$$<';<<r!   c                    |j                   |j                  d}|dj                  |      |d<   ndj                  ||      |d<   |j                  t	        |j                        |d<    | j
                  j                  di |}|}	|d   j                  t        j                  t        j                  j                  j                  j                                     D ]R  }
|j                  |
       |j!                         D ]  }|j#                  |
        |	t%        |
      z  }	|sK ||	       T |j'                  d      S )	Nr   z	bytes={}-Rangezbytes={}-{}r   BodyContentEncodingr   )r   namer   r   strr<   
get_objectiter_chunksr   ParseIntegerr   r6   r7   download_chunk_sizer9   writevaluesr   lenr   )r=   cloud_resourcedownload_stream	digestersr   
start_byteend_byteget_object_argsr   processed_byteschunkhash_objects               r   _download_objectzS3XmlClient._download_object  s7    !''""O !,!3!3J!?og!.!5!5j(!Kog  ,%()B)B%Cok"%t{{%%88H O&!--##%%99==?	AB E""))++5! , U#o	/*B <<)**r!   c                    
 ||d

 fd}
fd}t        j                  t        j                  j                  j
                  j                         t        j                  j                  j                  j                         dz  t        j                  j                  j                  j                               }	|	j                  |t        j                  j                  j                  j                         dz  |      S )N)r   r   c            	      <    j                   d   d         S )Nr   r   )r   )r   r   r   r   progress_stater=   s   r   _call_download_objectzES3XmlClient._download_object_resumable.<locals>._call_download_object  s3     ""
/96G

&z(BD Dr!   c                     t         j                  j                  D ]Z  }t        ||      sj	                         }|d   kD  r|d<   d|_        t        j                  dj                  || |              y y)Nr   r   z=Retrying download from byte {} after exception: {}. Trace: {}TF)	
s3transferutilsS3_RETRYABLE_DOWNLOAD_ERRORS
isinstancetellretrialr   debugr   )exc_type	exc_valueexc_tracebackstateretryable_error_typer   r   r   s         r    _should_retry_resumable_downloadzPS3XmlClient._download_object_resumable.<locals>._should_retry_resumable_download  sz    ","2"2"O"O
i!56&++-*.66+5N<(EM
)) !!'
Hm!LN #P r!   i  )max_retrialswait_ceiling_msexponential_sleep_multiplier)sleep_msshould_retry_if)r   Retryerr   r6   r7   max_retriesGetIntmax_retry_delayr  RetryOnExceptionbase_retry_delay)r=   r   r   r   r   r   r   r   r  retryerr   s   `````     @r   _download_object_resumablez&S3XmlClient._download_object_resumable  s     %/HEND D mm&&..::AAC"))11AAHHJ %%BBIIKNG ##""**;;BBDtK8 $ : :r!   r   c
                     ~~t        j                  ||      ry||}
ni }
|t        j                  j                  k(  r| j                  |||
|||	      }|S | j                  |||
|||	      }|S )r]   N)r   (return_and_report_if_nothing_to_downloadr   DownloadStrategy	RESUMABLEr  r   )r=   r   r   r0   r   do_not_decompressdownload_strategyr   r   r   digesters_dictcontent_encodings               r   download_objectzS3XmlClient.download_object(  s     	)==)  nnI66@@@88
/>;L
h  	 ..
/>;L
h  r!   c           
         ~~||d}|||d<   	  | j                   j                  di |}|t        j                  j                  u r4	  | j                   j                  di |}
|
j                  dd       |
|d<   |rN|t        j                  j$                  ur2	  | j                   j&                  di |}|j)                  dd      |d<   t1        j2                  | j4                  |||      S # t        j                  j                  $ rK}	t        |	t        j                  t        j                  j                  |||      j                         |	d}	~	ww xY w# t        j                  j                  $ r#}t!        j"                  |      |d<   Y d}~d}~ww xY w# t*        $ r }t-        j.                  d|       Y d}~d}~ww xY w)	r]   r   Nr   r   r   TagSetz$Failed to get object tags, error: %sr   )r<   head_objectr&   r   r'   r    r   r   rS   rT   
url_stringr   r   r   r   popr   r(   r   get_object_taggingr   	Exceptionr   warningr   r   r   )r=   rh   object_namer0   r   ru   r   rD   object_dicteacl_responser   tags_responses                r   get_object_metadatazS3XmlClient.get_object_metadataJ  s    	$[9G 'gk+DKK++6g6k y,,11171t{{11<G<+T2)E I,A,A,G,GG	666AA - 1 1(D AH BB[+{ 9 ** 



{99<<k*J88B
D g   ,, 7#//6E7  
 	:EBsH   C. 	3E 1F .EAEEF6FF	G%G  GTc
              #   v  K   ~~~~	|t         j                  j                  k(  rd}
d}nd}
d}	 | j                  j	                  |
      }|j                  |||nd||nd      }|D ]  }|j                  |g       D ]  }|t         j                  j                  u rj| j                  ||d   t        j                  t        j                  t        j                  j                  	            |j                  d
      |       t!        j"                  | j$                  ||        |j                  dg       D ]%  }t!        j&                  | j$                  ||       '  y# t(        j*                  j,                  $ r2}t/        j0                  t3        j4                  |             Y d}~yd}~ww xY ww)r]   list_object_versionsVersionslist_objects_v2ContentsN )r_   Prefix	Delimiterr   r   r   )rh   r,  r0   r   ru   CommonPrefixes)r   ObjectStateLIVE_AND_NONCURRENTr<   get_paginatorpaginater   r   r   r1  r	   get_request_configr   r   rS   rT   r   r   r   %get_prefix_resource_from_xml_responser&   r   r'   r   r   r   r(   )r=   rh   prefix	delimiterru   halt_on_empty_responseinclude_folders_as_prefixesnext_page_tokenobject_statelist_filterapi_method_nameobjects_key	paginatorpage_iteratorpager-  prefix_dictr   s                     r   list_objectszS3XmlClient.list_objects  s     	#y,,@@@.ok)ok9++++O<i((!-2!*!6IB ) @m  $88K4KY22777
 **''.5HH((0J0J0M0MN P&??;7) + + + $II[+  5"  88$4b9K!GGkk;  :%  , ** 9f007889s/   +F9D8E' &F9'F6(F1,F91F66F9c                 X    ~| j                  |||      }| j                  ||||d      S )r]   )r   T)r   r   r0   r   r   )r1  r   )	r=   rh   r,  object_resourcer0   ru   r   r   r   s	            r   patch_object_metadataz!S3XmlClient.patch_object_metadata  sJ     	..[Z / 9O',%!"&   r!   c           	         |j                   j                  }|j                   j                  }t        j                  t
        j                  j                  j                  j                               }t        j                  t
        j                  j                  j                  j                               }| j                  j                  |t        j                  j                  j!                  d||      |||       | j#                  ||t%        j&                  t        j(                  t         j*                  j,                                    S )a6  Uploads the data using boto3's managed transfer utility.

    Calls the upload_fileobj method which performs multi-threaded multipart
    upload automatically. Performs slightly better than put_object API method.
    However, upload_fileobj cannot perform data intergrity checks and we have
    to use put_object method in such cases.

    Args:
      source_stream (a file-like object): A file-like object to upload. At a
        minimum, it must implement the read method, and must return bytes.
      destination_resource (resource_reference.ObjectResource|UnknownResource):
        Represents the metadata for the destination object.
      extra_args (dict): Extra arguments that may be passed to the client
        operation.

    Returns:
      resource_reference.ObjectResource with uploaded object's metadata.
    F)use_threadsmultipart_chunksizemultipart_threshold)FileobjConfigr_   r   	ExtraArgsr:  )r   rh   r   r   r   r   r6   r7   rU  r9   rV  r<   upload_fileobjrR   s3transferTransferConfigr1  r	   r@  r   rS   rT   )r=   source_streamr   
extra_argsrh   r,  rU  rV  s           r   &_upload_using_managed_transfer_utilityz2S3XmlClient._upload_using_managed_transfer_utility  s   ( '22>>K&22@@K(55!!5599;=(55!!5599;=KK xx  // 3 3 0 5   
 ##[11  (B(B(E(EF	HI Ir!   c                 L   |j                   j                  |j                   j                  |d}|j                  |        | j                  j
                  di |}t        j                  | j                  ||j                   j                  |j                   j                        S )a  Uploads the source stream using the put_object API method.

    Args:
      source_stream (a seekable file-like object): The stream of bytes to be
        uploaded.
      destination_resource (resource_reference.ObjectResource|UnknownResource):
        Represents the metadata for the destination object.
      extra_args (dict): Extra arguments that may be passed to the client
        operation.

    Returns:
      resource_reference.ObjectResource with uploaded object's metadata.
    )r_   r   r   r   )	r   rh   r   r   r<   
put_objectr   r   r   )r=   r^  r   r_  rE   r   s         r   _upload_using_put_objectz$S3XmlClient._upload_using_put_object  s      '22>>#//==F
 MM*%t{{%%//HBB((44((66	 r!   c	                    ~~|t         j                  j                  k(  r.t        j                  dj                  |j                              i }	t        |t        j                        r|j                  r|j                  |	d<   t        j                  |	|||       t        |j                  dd      }
|
r|t         j                  j                  u rt!        j"                  d       n|t         j                  j$                  u r|j                  j&                  t(        kD  rFt!        j*                  d|
       t!        j"                  dt(        |j                  j&                         nB|j                  j&                  |j                  j&                  |	d	<   | j-                  |||	      S |	j/                  d
       | j1                  |||	      S )r]   zInvalid upload strategy: {}.Metadata)r   r   md5_hashNz9S3 does not support MD5 validation for streaming uploads.zThe MD5 hash %s will be ignoredzZS3 does not support MD5 validation for the entire object if size > %d bytes. File size: %dContentLength
ContentMD5)r   UploadStrategyr  command_errorsErrorr   rG   r  r   ObjectResourcecustom_fieldsr   r   r   r,   	STREAMINGr   r+  SIMPLEr   MAX_PUT_OBJECT_SIZEr  rc  r(  r`  )r=   r^  r   r0   r   serialization_datar   tracker_callbackupload_strategyr_  rf  s              r   upload_objectzS3XmlClient.upload_object  s    	,)22<<<  
(
/
/0E0E
FH H
 J/#5#D#DE		&	&!0!>!>
:EE+!	 ~33ZFH 
I44>>	>OP i66==='',,/BB
))5x
@
++01D**//1
 ))..:*8*F*F*K*KJ'..}/CZQ Q nn\"
 66+Z9 9r!   r5   )NNFN)NNNF)NNN)+__name__
__module____qualname____doc__r   
CapabilityCLIENT_SIDE_HASH_VALIDATIONcapabilitiesrU   rV   r   rS   rT   r   r>   rH   r;   r)   rg   ry   r   NO_ACLr   r   r   rr   r   r   r   r  r  ONE_SHOTr#  r1  r<  LIVErO  rR  r`  rc  ri  ro  rt  r   r!   r   r3   r3   [   s    66, -%%((&'- D *+ ,@ *+9 ,9 ((//5n '0&;&;&B&B 9(+ !* 5 5 < <zLx *+  %O ,Ob *+
= ,
=+8#:J *+
 !%(-(1(B(B(K(K(,!"# ,B *+
 2 ,2n !"&((--69p *+  ,,(IT: *+ ..55A9 ,A9r!   r3   r5   ))rx  
__future__r   r   r   	threadingrR   r&   googlecloudsdk.api_lib.storager   r   r   r	   r
   r   "googlecloudsdk.command_lib.storagerj  r   ,googlecloudsdk.command_lib.storage.resourcesr   r   r   +googlecloudsdk.command_lib.storage.tasks.cpr   googlecloudsdk.corer   r   r   r   googlecloudsdk.core.utilr   r   r  rp  LockrQ   r    r)   r1   CloudApir3   r   r!   r   <module>r     s    5 '  '    4 1 7 A H < G : K F N E = # * * 3  $ "INN$ K&	|9)$$ |9r!   