
    *]                     R   S 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	r	SSK
Js  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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Jr  SSKJr  SSKJr  Sr Sr! " S S\RD                  5      r# " S S\RH                  5      r%g)!Integration tests for mb command.    )absolute_import)print_function)division)unicode_literalsN)randint)PopulateProjectId)	SkipForS3)
SkipForXML)SkipForJSON)ObjectToURI)SECONDS_IN_DAY)SECONDS_IN_MONTH)SECONDS_IN_YEAR)SetBotoConfigForTest)SetEnvironmentForTest)Retry)	shim_utilz>gsutil does not support bucket lock operations for S3 buckets.z/gsutil KMS operations only run on GCS JSON API.c                   t   \ rS rSrSrS-S jr\" S5      S 5       rS r\" \	5      S 5       r
\" \	5      S 5       r\" \	5      S	 5       r\" \	5      S
 5       r\" \	5      S 5       rS r\" S5      S 5       r\" S5      S 5       r\" S5      S 5       r\" S5      S 5       r\" S5      S 5       r\" S5      S 5       r\" S5      S 5       r\" \5      \" \5      S 5       5       r\" \5      \" \5      S 5       5       r\" \5      \" \5      \" \SSS9S 5       5       5       r\" S5      \" S5      S 5       5       r\" S5      \" S5      S 5       5       r\" S 5      S! 5       r \" S 5      S" 5       r!\" S 5      S# 5       r"\#" S$5      S% 5       r$\#" S$5      S& 5       r%\" S'5      S( 5       r&\" S'5      S) 5       r'S* r(S+r)g,).TestMb-   r   c                 >   U R                   R                  [        S 5      [        R                  R
                  [        R                  R                  S9n[        R                  R                  nU(       a>  [        R                  R                  [        SS5      [        SS5      [        SS5      4-  nU R                   R                  X#5      nU R                   R                  U5      nUR                  (       a"  / Ul        U R                   R                  XE5        U$ )N)locationr   	   )kms_apiCreateKeyRingr	   testcaseKmsTestingResourcesKEYRING_NAMEKEYRING_LOCATION"CONSTANT_KEY_NAME_DO_NOT_AUTHORIZEMUTABLE_KEY_NAME_TEMPLATEr   CreateCryptoKeyGetKeyIamPolicybindingsSetKeyIamPolicy)selfmutablekeyring_fqnkey_namekey_fqn
key_policys         &platform/gsutil/gslib/tests/test_mb.pyGetKeyTestMb.GetKey0   s     ,,,,$$$11-->> - @K ++NNH--GG
!Q-A1K7 7h ll**;AG --g6Jj
ll""77N    z.S3 returns success when bucket already exists.c                     U R                  5       nU R                  S[        U5      /SSS9nU R                  (       a  U R	                  SU5        g U R	                  SU5        g )Nmb   Texpected_statusreturn_stderrz:HTTPError 409: The requested bucket name is not available.zalready exists)CreateBucket	RunGsUtilsuri_use_gcloud_storageassertIn)r'   
bucket_uristderrs      r-   test_mb_bucket_existsTestMb.test_mb_bucket_existsG   sc    ""$J^^T4
#34,-*.  0F 
mm
FP mm$f-r0   c                     U R                  / SQSSS9nU R                  (       a  U R                  SU5        g U R                  SU5        g )N)r2   -p   ãzgs://fobarbazr3   Tr4   z6The project property must be set to a valid project IDzInvalid non-ASCII)r8   r:   r;   )r'   r=   s     r-   test_non_ascii_project_fails#TestMb.test_non_ascii_project_failsS   sL    ^^?,-*.  0F 
mmL mm'0r0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R                  USS	9  g )
Nbucketgs://%sFsuppress_consec_slashesr2   --retention60s<   $expected_retention_period_in_seconds)MakeTempNamebotostorage_urilowerr8   r9   VerifyRetentionPolicyr'   bucket_namer<   s      r-   "test_create_with_retention_seconds)TestMb.test_create_with_retention_seconds]   si    ##H-K!!){/@/@/B"C:?AJNND-Z0@ABzDF  Hr0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R                  U[        S9  g )	NrF   rG   FrH   r2   rJ   1drM   )rO   rP   rQ   rR   r8   r9   rS   r   rT   s      r-   test_create_with_retention_days&TestMb.test_create_with_retention_daysf   si    ##H-K!!){/@/@/B"C:?AJNND-tJ/?@A  Ir0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R                  U[        S9  g )	NrF   rG   FrH   r2   rJ   1mrM   )rO   rP   rQ   rR   r8   r9   rS   r   rT   s      r-   !test_create_with_retention_months(TestMb.test_create_with_retention_monthso   sj    ##H-K!!){/@/@/B"C:?AJNND-tJ/?@A9I  Kr0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R                  U[        S9  g )	NrF   rG   FrH   r2   rJ   1yrM   )rO   rP   rQ   rR   r8   r9   rS   r   rT   s      r-    test_create_with_retention_years'TestMb.test_create_with_retention_yearsx   si    ##H-K!!){/@/@/B"C:?AJNND-tJ/?@A  Jr0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /SS	S
9nU R                  US5        g )NrF   rG   FrH   r2   rJ   1secondr3   Tr4   z$Incorrect retention period specifiedrO   rP   rQ   rR   r8   r9   assertRegexr'   rU   r<   r=   s       r-   &test_create_with_retention_invalid_arg-TestMb.test_create_with_retention_invalid_arg   su    ##H-K!!){/@/@/B"C:?AJ^^T=)!*-/,-*.  0F 	VDEr0   c                    U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /SS	S
9nU R                  (       a  U R                  SU5        g U R                  US5        g )NrF   zs3://%sFrH   r2   rJ   ra   r3   Tr4   z4Features disallowed for S3: Setting Retention Periodz7Retention policy can only be specified for GCS buckets.	rO   rP   rQ   rR   r8   r9   r:   r;   rg   rh   s       r-   +test_create_with_retention_on_s3_urls_fails2TestMb.test_create_with_retention_on_s3_urls_fails   s    ##H-K!!){/@/@/B"C:?AJ^^	}dD$45  F 
mmJ 
LNr0   z3Public access prevention only runs on GCS JSON API.c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R                  US5        g )NrF   rG   FrH   r2   --papenforced)rO   rP   rQ   rR   r8   r9   !VerifyPublicAccessPreventionValuerT   s      r-   test_create_with_pap_enforced$TestMb.test_create_with_pap_enforced   s`    ##H-K!!){/@/@/B"C:?AJNND':tJ/?@A**:zBr0   c                 "   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R	                  SS	[        U5      /S
S9nU R                  US[        U5      -  5        g )NrF   rG   FrH   r2   rp   	inheritedpublicaccesspreventiongetTreturn_stdoutz%s:\s+inheritedrf   r'   rU   r<   stdouts       r-   test_create_with_pap_inherited%TestMb.test_create_with_pap_inherited   s    ##H-K!!){/@/@/B"C:?AJNND';Z0@AB^^5u!*-/*.  0F 	V/$z2BBCr0   c                    U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /SS	S
9nU R                  (       a  U R                  SU5        g U R                  US5        g )NrF   rG   FrH   r2   rp   invalid_argr3   Tr4   z:Flag value not in translation map for "--pap": invalid_argz invalid_arg is not a valid valuerl   rh   s       r-    test_create_with_pap_invalid_arg'TestMb.test_create_with_pap_invalid_arg   s    ##H-K!!){/@/@/B"C:?AJ^^T7M!*-/,-*.  0F 
mm
FP vBCr0   z%RPO flag only works for GCS JSON API.c           
          U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSSSS	[        U5      /5        U R                  US
S	5        g )NrF   rG   FrH   r2   -lnam4--rpoASYNC_TURBOrpo)rO   rP   rQ   rR   r8   r9   VerifyCommandGetrT   s      r-    test_create_with_rpo_async_turbo'TestMb.test_create_with_rpo_async_turbo   sn    ##H-K!!){/@/@/B"C:?AJNN	tVWm	j		 	*e];r0   c                    U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5         U R                  USS	5        g ! [         a    U R                  USS
5         g f = f)NrF   rG   FrH   r2   r   r   r   DEFAULTNone)rO   rP   rQ   rR   r8   r9   r   AssertionErrorrT   s      r-   test_create_sets_rpo_to_default&TestMb.test_create_sets_rpo_to_default   s    ##H-K!!){/@/@/B"C:?AJNND$Z(89:7
Jy9 7 Jv67s   A+ +B
Bc           
          U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSSSS	[        U5      /S
SS9nU R                  SU5        g)z0Turbo replication is only meant for dual-region.rF   rG   FrH   r2   r   zus-central1r   r   Tr3   r6   r5   z.ASYNC_TURBO cannot be enabled on REGION bucketNrO   rP   rQ   rR   r8   r9   r;   rh   s       r-   :test_create_with_rpo_async_turbo_fails_for_regional_bucketATestMb.test_create_with_rpo_async_turbo_fails_for_regional_bucket   sz     ##H-K!!){/@/@/B"C:?AJ^^	t]G]	j			  F
 	MMBFKr0   c           
      H   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R                  (       a  SOSnU R                  SSS	S
S[        U5      /SUS9nU R                  (       a  U R                  SU5        g U R                  SU5        g )NrF   rG   FrH      r3   r2   r   r   r   incorrect_valueTr   z=--recovery-point-objective: Invalid choice: 'incorrect_value'zYInvalid value for --rpo. Must be one of: (ASYNC_TURBO|DEFAULT), provided: incorrect_valuerO   rP   rQ   rR   r:   r8   r9   r;   r'   rU   r<   r5   r=   s        r-   1test_create_with_rpo_incorrect_value_raises_error8TestMb.test_create_with_rpo_incorrect_value_raises_error   s    ##H-K!!){/@/@/B"C:?AJ33aO^^	tVW&7	j		'	  )F 
mm
K
 mm'(.0r0   c           
         U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  5       nU R                  SS[        R                  R                  SU[        U5      /SS	S
9nU R                  (       a  U R                  SU5        g U R                  SU5        U R                  SU-  U5        g )NrF   rG   FrH   r2   r   -kTr3   r   2HTTPError 403: Permission denied on Cloud KMS key.To authorize, run:z-k %s)rO   rP   rQ   rR   r.   r8   r   r   r    r9   r:   r;   r'   rU   r<   keyr=   s        r-   &test_create_with_k_flag_not_authorized-TestMb.test_create_with_k_flag_not_authorized   s     ##H-K!!){/@/@/B"C:?AJ
++-C^^dH00AA4Z +/,-  /F 
mmH mm(&1
mmGcM6*r0   c                    U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  5       nU R                  SS[        R                  R                  SUS[        5       [        U5      /S	S
S9nU R                  (       a  U R                  SU5        g U R                  SU5        U R                  S[        5       -  U5        g )NrF   rG   FrH   r2   r   r   rA   Tr3   r   r   r   z-p %s)rO   rP   rQ   rR   r.   r8   r   r   r    r	   r9   r:   r;   r   s        r-   -test_create_with_k_flag_p_flag_not_authorized4TestMb.test_create_with_k_flag_p_flag_not_authorized  s     ##H-K!!){/@/@/B"C:?AJ
++-C^^dH00AA4Z	 +/,-  /F 
mmH mm(&1
mmG/116:r0      r3   )triestimeout_secsc           
      (   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SS9nU R                  SSS	U/5        U R                  S
S[        R                  R                  S	U[        U5      /SS9  g )NrF   rG   FrH   T)r(   kms	authorizer   r2   r   r   )r5   )
rO   rP   rQ   rR   r.   r8   r   r   r    r9   )r'   rU   r<   r   s       r-   "test_create_with_k_flag_authorized)TestMb.test_create_with_k_flag_authorized#  s     ##H-K!!){/@/@/B"C:?AJ
++d+
#CNNE;c23NNdH00AA4Z $%	  &r0   z4Custom Dual Region is not supported for the XML API.z3Custom Dual Region is not supported for S3 buckets.c                 
   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R	                  SS	[        U5      /S
S9nU R                  US5        g )NrF   rG   FrH   r2   r   zus-east1+us-east4ls-LbTry   z(ocations:\s*\[\s*.US-EAST1.,\s*.US-EAST4rf   r{   s       r-   /test_create_with_custom_dual_regions_via_l_flag6TestMb.test_create_with_custom_dual_regions_via_l_flag2  s     ##H-K!!){/@/@/B"C:?AJNND$ 3T*5EFG^^T5$z*:;4^PFVHIr0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /SS	S
9nU R                  SU5        g )NrF   rG   FrH   r2   r   zinvalid_reg1+invalid_reg2Tr3   r   z.The specified location constraint is not validr   rh   s       r-   =test_create_with_invalid_dual_regions_via_l_flag_raises_errorDTestMb.test_create_with_invalid_dual_regions_via_l_flag_raises_error<  sw     ##H-K!!){/@/@/B"C:?AJ^^	t0	j			  F
 	MMBFKr0   z1The --placement flag only works for GCS JSON API.c                 
   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R	                  SS	[        U5      /S
S9nU R                  US5        g )NrF   rG   FrH   r2   --placementzus-central1,us-west1r   r   Try   z+ocations:\s*\[\s*.US-CENTRAL1.,\s*.US-WEST1rf   r{   s       r-   test_create_with_placement_flag&TestMb.test_create_with_placement_flagI  s    ##H-K!!){/@/@/B"C:?AJNN	}4	j		 ^^T5$z*:;4^PFVKLr0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /SS	S
9nU R                  US5        g )NrF   rG   FrH   r2   r   zinvalid_reg1,invalid_reg2Tr3   r   z.*400.*(Invalid custom placement config|One or more unrecognized regions in dual-region, received: INVALID_REG1, INVALID_REG2).*rf   rh   s       r-   4test_create_with_invalid_placement_flag_raises_error;TestMb.test_create_with_invalid_placement_flag_raises_errorT  s|    ##H-K!!){/@/@/B"C:?AJ^^	}9	j			  F
 	 *+r0   c                 D   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R                  (       a  SOSnU R                  SSS	[        U5      /S
US9nU R                  (       a  U R                  SU5        g U R                  SU5        g )NrF   rG   FrH   r   r3   r2   r   zval1,val2,val3Tr   z--placement: too many argszhCommandException: Please specify two regions separated by comma without space. Specified: val1,val2,val3r   r   s        r-   Btest_create_with_incorrect_number_of_placement_values_raises_errorITestMb.test_create_with_incorrect_number_of_placement_values_raises_errorc  s    ##H-K!!){/@/@/B"C:?AJ  33aO^^	}.	j		'	  )F
 
mm0&9
mm67=?r0   zTesting XML only behavior.c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /SS	S
9nU R                  SU5        g )NrF   rG   FrH   r2   r   r   Tr3   r   zXCommandException: The --rpo option(s) can only be used for GCS Buckets with the JSON APIr   rh   s       r-   4test_single_json_only_flag_raises_error_with_xml_api;TestMb.test_single_json_only_flag_raises_error_with_xml_apiv  sx    ##H-K!!){/@/@/B"C:?AJ^^T7M!*-/*.,-  /F 	MM	-.46r0   c                     U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSSSS	S
SSSS[        U5      /SSS9nU R                  SU5        g )NrF   rG   FrH   r2   --autoclassrp   enabledr   zuscentral-1,us-asia1r   r   z-bonTr3   r   z}CommandException: The --autoclass, --pap, --placement, --rpo, -b option(s) can only be used for GCS Buckets with the JSON APIr   rh   s       r-   6test_multiple_json_only_flags_raise_error_with_xml_api=TestMb.test_multiple_json_only_flags_raise_error_with_xml_api  s    ##H-K!!){/@/@/B"C:?AJ^^mWidZ
 +/,-  /F 	MM	Kr0   1The --autoclass flag only works for GCS JSON API.c                    U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SS[        U5      /5        U R	                  SS[        U5      /S	S
9nU R                  US5        g )NrF   rG   FrH   r2   r   r   r   Try   zAutoclass:.*Enabled on *.rf   r{   s       r-   test_create_with_autoclass_flag&TestMb.test_create_with_autoclass_flag  s}    ##H-K!!){/@/@/B"C:?AJNND-j)9:;^^T5$z*:;4^PFV9:r0   c           	         U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSSS[        U5      /S	S
S9nU R                  (       a  U R                  SU5        g U R                  SU5        g )NrF   rG   FrH   r2   r   z-carchiveTr3   r   z/HTTPError 400: Cannot set default storage classz9BadRequestException: 400 Cannot set default storage class)rO   rP   rQ   rR   r8   r9   r:   r;   rh   s       r-   :test_create_with_invalid_storage_class_with_autoclass_flagATestMb.test_create_with_invalid_storage_class_with_autoclass_flag  s    ##H-K!!){/@/@/B"C:?AJ^^T=$	4
CSTdhz{^|F
mmEvN
mmOQWXr0   c                 
   U R                  S5      n[        R                  " SUR                  5       -  SS9nU R	                  SSS[        U5      /5        U R	                  SS	[        U5      /S
S9nU R                  US5        g )NrF   rG   FrH   r2   -snearliner   r   Try   zStorage\sclass:\s*NEARLINErf   r{   s       r-   test_create_with_storage_class%TestMb.test_create_with_storage_class  s    ##H-K!!){/@/@/B"C:?AJNND$
D,<=>^^T5$z*:;4^PFV:;r0    N)F)*__name__
__module____qualname____firstlineno____doc__r.   r
   r>   rC   BUCKET_LOCK_SKIP_MSGrV   rZ   r^   rb   ri   rm   r   rs   r}   r   r   r   r   r   KMS_SKIP_MSGr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __static_attributes__r   r0   r-   r   r   -   s   ). =>	. ?	.1 !"H #H !"I #I !"K #K !"J #J !"F #FN CDC EC CDD ED CDD ED 56< 7< 56
7 7
7 56
L 7
L 560 70* l\+  +& l\;  ;* l\qq1
& 2  
& DEBCJ D FJ DEBC	L D F	L ABM CM AB+ C+ AB? C?$ +,
6 -
6 +, -  AB; C; ABY CY<r0   r   c                   \    \ rS rSrSrS r\" S5      S 5       r\" S5      S 5       rS r	S	r
g
)TestMbUnitTestsWithShimi  z#Unit tests for gsutil mb with shim.c           	      n   [        SS/5         [        SSS.5         U R                  S/ SQSS	9nS
R                  UR                  S   5      nU R                  SR                  [        R                  " S5      5      U5        S S S 5        S S S 5        g ! , (       d  f       N= f! , (       d  f       g = f)NGSUtiluse_gcloud_storageTruer   hidden_shim_modedry_runr   fake_dir(CLOUDSDK_CORE_PASS_CREDENTIALS_TO_GSUTILCLOUDSDK_ROOT_DIRr2   )rJ   ra   zgs://fake-bucketTargsreturn_log_handler
infoz_Gcloud Storage Command: {} storage buckets create --retention-period 31557600s gs://fake-bucket	r   r   
RunCommandjoinmessagesr;   formatr   _get_gcloud_binary_pathr'   mock_log_handler
info_liness      r-   ,test_shim_translates_retention_seconds_flagsDTestMbUnitTestsWithShim.test_shim_translates_retention_seconds_flags  s    	GHJ 
K 6<)" 	  ??41-
 ?C + D YY/88@A
 HIO$<<ZHJJ 	"	
K 
K	 	
K 
K#   B&A'BB&
B#	B&&
B4z+The --rpo flag only works for GCS JSON API.c           	      r   Sn[        SS/5         [        SUS.5         U R                  S/ SQSS	9nS
R                  UR                  S   5      nU R                  SR                  [        R                  " S5      5      U5        S S S 5        S S S 5        g ! , (       d  f       N= f! , (       d  f       g = f)Nr   r   r   r   r   r2   )r   r   zgs://fake-bucket-1Tr   r   r   zTGcloud Storage Command: {} storage buckets create --recovery-point-objective DEFAULTr   )r'   fake_cloudsdk_dirr   r   s       r-   2test_shim_translates_recovery_point_objective_flagJTestMbUnitTestsWithShim.test_shim_translates_recovery_point_objective_flag  s    "	GHJ 
K 6<0" 	  ??;# + %
 YY/88@A
BCI622:>D@AK	M	
K 
K	 	
K 
Ks#   B(A'BB(
B%	!B((
B6r   c           	      n   [        SS/5         [        SSS.5         U R                  SSS/S	S
9nSR                  UR                  S   5      nU R                  SR                  [        R                  " S5      5      U5        S S S 5        S S S 5        g ! , (       d  f       N= f! , (       d  f       g = f)Nr   r   r   r   r   r2   r   zgs://fake-bucket-2Tr   r   r   zWGcloud Storage Command: {} storage buckets create --enable-autoclass gs://fake-bucket-2r   r   s      r-   #test_shim_translates_autoclass_flag;TestMbUnitTestsWithShim.test_shim_translates_autoclass_flag  s    	GHJ 
K 6<)" 	  ??4/</C1- ?C + D YY/88@A
 @AG$<<ZHBJ 	"	
K 
K	 	
K 
Kr   c           	      n   [        SS/5         [        SSS.5         U R                  S/ SQSS	9nS
R                  UR                  S   5      nU R                  SR                  [        R                  " S5      5      U5        S S S 5        S S S 5        g ! , (       d  f       N= f! , (       d  f       g = f)Nr   r   r   r   r   r2   )r   r   zgs://fake-bucket-3Tr   r   r   zeGcloud Storage Command: {} storage buckets create --default-storage-class nearline gs://fake-bucket-3r   r   s      r-   test_shim_translates_class_flag7TestMbUnitTestsWithShim.test_shim_translates_class_flag  s    	GHJ 
K 6<)" 	  ??41-
 ?C + D YY/88@A
 NOUv$<<ZHPJ 	"	
K 
K	 	
K 
Kr   r   N)r   r   r   r   r   r   r   r  r  r	  r   r   r0   r-   r   r     sF    +"( ;<M =M& AB" C"&"r0   r   )&r   
__future__r   r   r   r   osrandomr   rP   gslib.tests.testcasetestsr   gslib.project_idr	   )gslib.tests.testcase.integration_testcaser
   r   r   gslib.tests.utilr   r9   gslib.utils.retention_utilr   r   r   r   r   gslib.utils.retry_utilr   gslib.utilsr   r   r   GsUtilIntegrationTestCaser   ShimUnitTestBaser   r   r0   r-   <module>r     s    ( & %  ' 	   ' ' . ? @ A 0 5 7 6 1 2 ( !& @A<X// A<HQ"h77 Q"r0   