+
    nDjn                     :   ^ RI t ^ RIHt ^ RIt ^ RIHt ^ RIHu H	t
 ^ RIHtHtHtHtHt RtRtRtRtRt] P.                  P0                  ] P.                  P                  .t] P4                  ! R	R
7      R 4       t] P4                  ! R	R
7      R 4       t] P4                  ! R	R
7      R 4       tR tR tR t R t!R t"R0R lt#R t$R t%R t&R t'R t(R t)R t*R t+R t,R t-R t.R  t/R! t0] P.                  Pc                  R"R#7      R$ 4       t2R% t3] P.                  Pi                  R1] Pj                  ! RRR&R'7      ] Pj                  ! R(RR)R'7      ] Pj                  ! RR(R*R'7      ] Pj                  ! R(R(R+R'7      .4      R, 4       t6R- t7R. t8R/ t9R#   ] d	    RtRt
 ELli ; i)2    N)	timedelta)InMemoryKmsClientMockVersioningKmsClientverify_file_encryptedread_external_keys_to_dictparse_wrapped_keyzencrypted_table.in_mem.parquets   0123456789112345
footer_keys   1234567890123450col_keymodule)scopec                      \         P                  P                  R \         P                  ! . RO4      R\         P                  ! . RO4      R\         P                  ! . RO4      /4      p V # )abc)         )r   r   r   )xyz)paTablefrom_pydictarray)
data_tables    _/data/cameron/venvs/s3viz/lib/python3.14/site-packages/pyarrow/tests/parquet/test_encryption.pyr   r   2   sM    %%RXXi RXXo&RXXo&' J
     c                  N    \         P                  ! \        \        R R./R7      p V # )r   r   )r	   column_keyspeEncryptionConfigurationFOOTER_KEY_NAMECOL_KEY_NAME)basic_encryption_configs    r   r%   r%   <   s,     88"3*

 #"r   c                  P    \         P                  ! \        \        R R./RR7      p V # )r   r   F)r	   r   internal_key_materialr    )external_encryption_configs    r   r(   r(   F   s1    !#!;!;"3*
 $"% &%r   c                h    \         P                  ! V R7      pR p\         P                  ! V4      pW3# )zy
Sets up and returns the KMS connection configuration and crypto factory
based on provided KMS configuration parameters.
custom_kms_confc                     \        V 4      # Nr   kms_connection_configurations   &r   kms_factory1setup_encryption_environment.<locals>.kms_factoryX        !=>>r   )r!   KmsConnectionConfigCryptoFactory)r+   kms_connection_configr1   crypto_factorys   &   r   setup_encryption_environmentr8   Q   s5    
 22?S? %%k2N 00r   c                    W$P                  R4      W5P                  R4      /p\        V4      w  r\        WVW4       W3# )zD
Writes an encrypted parquet file based on the provided parameters.
UTF-8)decoder8   write_encrypted_parquet)
pathr   footer_key_namecol_key_namer	   r
   encryption_configr+   r6   r7   s
   &&&&&&&   r   write_encrypted_filerA   a   sW     	**73nnW-O -I-) D.?1C !00r   c           	        V \         ,          p\        P                  ! \        \        RR./R\        RR7      RR7      pVP                  RJ g   Q h\        W!\        \        \        \        V4      w  rE\        V4       \        P                  ! \        RR7      R	7      p\        W&WE4      pVP                  V4      '       g   Q hR
# )DWrite an encrypted parquet, verify it's encrypted, and then read it.r   r   
AES_GCM_V1      @minutes   r	   r   encryption_algorithmcache_lifetimedata_key_length_bitsFrK   N)PARQUET_NAMEr!   r"   r#   r$   r   uniform_encryptionrA   
FOOTER_KEYCOL_KEYr   DecryptionConfigurationread_encrypted_parquetequalstempdirr   r=   r@   r6   r7   decryption_configresult_tables   &&      r   !test_encrypted_parquet_write_readrY   w   s    \!D
 22"3*
 * - " //5888,@/<W-) $ 22 -/)!6HL\****r   c           	     t   V \         ,          p\        P                  ! \        RR\	        RR7      RR7      pVP
                  RJ g   Q h\        W!\        \        \        RV4      w  rE\        V4       \        P                  ! \	        RR7      R7      p\        W&WE4      pVP                  V4      '       g   Q hR	# )
rC   TrD   rE   rF   rH   )r	   rO   rJ   rK   rL   r   rM   N)rN   r!   r"   r#   r   rO   rA   r$   rP   r   rR   rS   rT   rU   s   &&      r   )test_uniform_encrypted_parquet_write_readr[      s    \!D 22") - " //4777,@/<S-) $ 22 -/)!6HL\****r   c                 .   VP                   '       d   VP                  W24      pMVP                  W2V 4      pVf   Q h\        P                  ! WP                  VR7      ;_uu_ 4       pVP                  V4       R R R 4       R #   + '       g   i     R # ; i)N)encryption_properties)r'   file_encryption_propertiespqParquetWriterschemawrite_table)r=   tabler@   r6   r7   r^   writers   &&&&&  r   r<   r<      s    ...%3%N%N!&6" &4%N%N!d&<"%111			,,"<
> 
>AG5!
> 
> 
> 
>s   'BB	Tc                 r   V'       d   VP                  W!4      pMVP                  W!V 4      pVf   Q h\        P                  ! WR7      pVP                  ^8X  g   Q h\        P                  ! WR7      p\        VP                  4      ^8X  g   Q h\        P                  ! WR7      pVP                  RR7      # )Ndecryption_propertiesTuse_threads)	file_decryption_propertiesr_   read_metadatanum_columnsread_schemalennamesParquetFileread)	r=   rW   r6   r7   r'   rj   metara   results	   &&&&&    r   rS   rS      s     %3%N%N!&6" &4%N%N!d&<" &111@Dq   ^^@Fv||!!!^^@F;;4;((r   c           	     4   V \         ,          p\        P                  ! \        \        RR./R\        RR7      RR7      p\        W!\        \        \        \        V4       \        V4       \        \        \        P                  R4      \        \        P                  R4      /4      w  rE\        P                  ! \        RR7      R	7      p\        P                  ! \        R
R7      ;_uu_ 4        \!        W&VV4       RRR4       R#   + '       g   i     R# ; i)zUWrite an encrypted parquet, verify it's encrypted,
and then read it using wrong keys.r   r   rD   rE   rF   rH   rI   r:   rM   zIncorrect master key usedmatchN)rN   r!   r"   r#   r$   r   rA   rP   rQ   r   r8   r;   rR   pytestraises
ValueErrorrS   )rV   r   r=   r@   wrong_kms_connection_configwrong_crypto_factoryrW   s   &&     r   +test_encrypted_parquet_write_read_wrong_keyr|      s     \!D
 22"3*
 * - " ?L#W.?A $8T0j''0V 95
 22 -/	z)E	F	F%@ 	" 
G	F	F	Fs   .DD	c                    \        W4       \        P                  ! \        RR7      ;_uu_ 4        \        P
                  ! V \        ,          4      P                  4        RRR4       R#   + '       g   i     R# ; i)ziWrite an encrypted parquet, verify it's encrypted,
but then try to read it without decryption properties.no decryptionru   N)rY   rw   rx   IOErrorr_   rp   rN   rq   rV   r   s   &&r   0test_encrypted_parquet_read_no_decryption_configr      sG     &g:	w&6	7	7
w-.335 
8	7	7	7s   0A**A;	c                    \        W4       \        P                  ! \        RR7      ;_uu_ 4        \        P
                  ! V \        ,          4       RRR4       R#   + '       g   i     R# ; i)zsWrite an encrypted parquet, verify it's encrypted,
but then try to read its metadata without decryption properties.r~   ru   N)rY   rw   rx   r   r_   rk   rN   r   s   &&r   9test_encrypted_parquet_read_metadata_no_decryption_configr     s@     &g:	w&6	7	7
</0 
8	7	7	7   "AA-	c                    \        W4       \        P                  ! \        RR7      ;_uu_ 4        \        P
                  ! V \        ,          4       RRR4       R#   + '       g   i     R# ; i)zqWrite an encrypted parquet, verify it's encrypted,
but then try to read its schema without decryption properties.r~   ru   N)rY   rw   rx   r   r_   rm   rN   r   s   &&r   7test_encrypted_parquet_read_schema_no_decryption_configr     s>     &g:	w&6	7	7
w-. 
8	7	7	7r   c                   V R,          p\         P                  ! \        R7      p\        P                  ! \
        RR7      ;_uu_ 4        \        W!\        \        \        RV4       RRR4       R#   + '       g   i     R# ; i)IWrite an encrypted parquet, but give only footer key,
without column key.z)encrypted_table_no_col_key.in_mem.parquetr	   z4Either column_keys or uniform_encryption must be setru   r   N)	r!   r"   r#   rw   rx   OSErrorrA   r$   rP   rV   r   r=   r@   s   &&  r   'test_encrypted_parquet_write_no_col_keyr     sm     @@D 22"$ 
w%
& 
& 	T'.?	A	
& 
& 
& 
&s   	A00B	c                   V R,          p\         P                  ! \        \        RR./RR7      p\        P
                  ! \        RR7      ;_uu_ 4        \        W!\        \        \        RV4       R	R	R	4       R	#   + '       g   i     R	# ; i)
r   z=encrypted_table_col_key_and_uniform_encryption.in_mem.parquetr   r   T)r	   r   rO   z2Cannot set both column_keys and uniform_encryptionru   r   N)	r!   r"   r#   r$   rw   rx   r   rA   rP   r   s   &&  r   ;test_encrypted_parquet_write_col_key_and_uniform_encryptionr   '  s     TTD 22"3*
  ! 
wR
T 
T 	T'.?	A
T 
T 
T 
Ts   A::B	c           	        V R,          pTp\         P                  ! 4       pR p\         P                  ! V4      p\        P                  ! \
        RR7      ;_uu_ 4        \        W1VWW4       RRR4       R#   + '       g   i     R# ; i)<Write an encrypted parquet, but raise KeyError in KmsClient.(encrypted_table_kms_error.in_mem.parquetc                     \        V 4      # r-   r.   r/   s   &r   r1   ;test_encrypted_parquet_write_kms_error.<locals>.kms_factoryD  s     !!=>>r   r	   ru   N)r!   r4   r5   rw   rx   KeyErrorr<   rV   r   r%   r=   r@   r6   r1   r7   s   &&&     r   &test_encrypted_parquet_write_kms_errorr   ;  sn     ??D/ 224?
 %%k2N	x|	4	42C 5	G 
5	4	4	4   A66B	c           	     N  a V R,          pTp\         P                  ! 4       p ! R R\         P                  4      oV3R lp\         P                  ! V4      p\        P
                  ! \        RR7      ;_uu_ 4        \        W1VWW4       RRR4       R#   + '       g   i     R# ; i)r   r   c                   6   a  ] tR tRt o RtR tR tR tRtV t	R# )Jtest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClientiY  zFA KmsClient implementation that throws exception in
wrap/unwrap calls
c                P    \         P                  P                  V 4       Wn        R# )z%Create an InMemoryKmsClient instance.N)r!   	KmsClient__init__configselfr   s   &&r   r   Stest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClient.__init__^  s    LL!!$' Kr   c                    \        R 4      h)Cannot Wrap Keyry   r   	key_bytesmaster_key_identifiers   &&&r   wrap_keyStest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClient.wrap_keyc  s    .//r   c                    \        R 4      h)zCannot Unwrap Keyr   r   wrapped_keyr   s   &&&r   
unwrap_keyUtest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClient.unwrap_keyf  s    011r   )r   N
__name__
__module____qualname____firstlineno____doc__r   r   r   __static_attributes____classdictcell____classdict__s   @r   ThrowingKmsClientr   Y  s     		!
	0	2 	2r   r   c                    < S! V 4      # r-    )r0   r   s   &r   r1   Dtest_encrypted_parquet_write_kms_specific_error.<locals>.kms_factoryi  s     !=>>r   r   ru   N)r!   r4   r   r5   rw   rx   ry   r<   )	rV   r   r%   r=   r@   r6   r1   r7   r   s	   &&&     @r   /test_encrypted_parquet_write_kms_specific_errorr   P  s     ??D/ 2242BLL 2 ? %%k2N	z):	;	;2C 5	G 
<	;	;	;s   ;BB$	c           	        V R,          pTp\         P                  ! 4       pR p\         P                  ! V4      p\        P                  ! \
        RR7      ;_uu_ 4        \        W1VWW4       RRR4       R#   + '       g   i     R# ; i)z@Write an encrypted parquet, but raise ValueError in kms_factory.0encrypted_table_kms_factory_error.in_mem.parquetc                     \        R 4      h)Cannot create KmsClientr   r/   s   &r   r1   Ctest_encrypted_parquet_write_kms_factory_error.<locals>.kms_factory}  s    233r   r   ru   N)r!   r4   r5   rw   rx   ry   r<   r   s   &&&     r   .test_encrypted_parquet_write_kms_factory_errorr   t  s{     GGD/ 2244 %%k2N	z6
8 
8 	 2C 5	G
8 
8 
8 
8r   c           	     ,  a V R,          pTp\         P                  ! 4       p ! R R4      oV3R lp\         P                  ! V4      p\        P                  ! \
        4      ;_uu_ 4        \        W1VWW4       RRR4       R#   + '       g   i     R# ; i)z[Write an encrypted parquet, but use wrong KMS client type
that doesn't implement KmsClient.r   c                   6   a  ] tR tRt o RtR tR tR tRtV t	R# )Otest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClienti  z4This is not an implementation of KmsClient.
        c                (    VP                   V n        R # r-   )r+   master_keys_mapr   s   &&r   r   Xtest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClient.__init__  s    #)#9#9D r   c                    R # r-   r   r   s   &&&r   r   Xtest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClient.wrap_key      r   c                    R # r-   r   r   s   &&&r   r   Ztest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClient.unwrap_key  r   r   )r   Nr   r   s   @r   WrongTypeKmsClientr     s     		:		 	r   r   c                    < S! V 4      # r-   r   )r0   r   s   &r   r1   Htest_encrypted_parquet_write_kms_factory_type_error.<locals>.kms_factory  s    !">??r   N)r!   r4   r5   rw   rx   	TypeErrorr<   )	rV   r   r%   r=   r@   r6   r1   r7   r   s	   &&&     @r   3test_encrypted_parquet_write_kms_factory_type_errorr     sx     GGD/ 224 @ %%k2N	y	!	!2C 5	G 
"	!	!	!s   *BB	c                  P   R  p \         P                  ! \        \        RR./RRR\	        RR7      R^R7      pV ! V4       \         P                  ! \        R	7      p\        RR./Vn        RVn        RVn        RVn        \	        RR7      Vn	        RVn
        ^Vn        V ! V4       R
# )c                 r   \         V P                  8X  g   Q hR R.V P                  \        ,          8X  g   Q hRV P                  8X  g   Q hV P
                  '       g   Q hV P                  '       d   Q h\        RR7      V P                  8X  g   Q hV P                  '       d   Q h^V P                  8X  g   Q hR# )r   r   AES_GCM_CTR_V1      $@rF   N)r#   r	   r   r$   rJ   plaintext_footerdouble_wrappingr   rK   r'   rL   )r@   s   &r   !validate_encryption_configurationZtest_encrypted_parquet_encryption_configuration.<locals>.validate_encryption_configuration  s    "3">">>>>Sz.::<HHHH#4#I#IIII 11111$44444&*;*J*JJJJ$:::::'<<<<<r   r   r   r   TFr   rF   )r	   r   rJ   r   r   rK   r'   rL   r   N)r!   r"   r#   r$   r   r   rJ   r   r   rK   r'   rL   )r   r@   encryption_config_1s      r   /test_encrypted_parquet_encryption_configurationr     s    = 22"!C:0- .# 	 &&7844"$'3c3Z&B#/?,+/(*/')24)@&05-/2,%&9:r   c                     \         P                  ! \        R R7      R7      p \        R R7      V P                  8X  g   Q h\         P                  ! 4       p\        R R7      Vn        \        R R7      VP                  8X  g   Q hR# )r   rF   rM   N)r!   rR   r   rK   )rW   decryption_config_1s     r   /test_encrypted_parquet_decryption_configurationr     sl    22 .0T"&7&F&FFFF446)24)@&T"&9&H&HHHHr   c            	          R  p \         P                  ! RRRRRRR/R7      pV ! V4       \         P                  ! 4       pRVn        RVn        RVn        RRRR/Vn        V ! V4       R	# )
c                     R V P                   8X  g   Q hRV P                  8X  g   Q hRV P                  8X  g   Q hRRRR/V P                  8X  g   Q hR# )	Instance1URL1MyTokenkey1key_material_1key2key_material_2Nkms_instance_idkms_instance_urlkey_access_tokenr+   )r6   s   &r   validate_kms_connection_configPtest_encrypted_parquet_kms_configuration.<locals>.validate_kms_connection_config  sg    3CCCCC.?????1BBBBB)63CD%556 	7 6r   r   r   r   r   r   r   r   r   N)r!   r4   r   r   r   r+   )r   r6   kms_connection_config_1s      r   (test_encrypted_parquet_kms_configurationr     s    7 22#"$$
	 ##89 446.9+/5,/8,  /+ ##:;r   zNPlaintext footer - reading plaintext column subset reads encrypted columns too)reasonc                J   V \         ,          p\        P                  ! \        \        RR./RRR7      p\        P
                  ! \        \        P                  R4      \        \        P                  R4      /R7      pR p\        P                  ! V4      p\        W!VWF4       R	# )
zWrite an encrypted parquet, with plaintext footer
and with single wrapping,
verify it's encrypted, and then read plaintext columns.r   r   TF)r	   r   r   r   r:   r*   c                     \        V 4      # r-   r.   r/   s   &r   r1   Stest_encrypted_parquet_write_read_plain_footer_single_wrapping.<locals>.kms_factory  r3   r   N)rN   r!   r"   r#   r$   r4   rP   r;   rQ   r5   r<   )rV   r   r=   r@   r6   r1   r7   s   &&     r   >test_encrypted_parquet_write_read_plain_footer_single_wrappingr     s     \!D
 22"3*
  22Z..w7'..1
? %%k2ND.?1Cr   c           	     B   V \         ,          p\        W1\        \        \        \
        V4      w  rE\        V4       \        P                  ! 4       p\        W6WERR7      p\        P                  P                  P                  V4      p\        VP                  4       ;p	4      \        VP                   \        ,          4      ^,           8X  g   Q h\#        V	 U
u. uF  qP%                  V
4      RJNK  	  up
4      '       g   Q hVP'                  V4      '       g   Q hR# u up
i )zWrite an encrypted parquet file with external key material, verify
it's encrypted, then read both the table and external store.
Fr'   N)rN   rA   r#   r$   rP   rQ   r   r!   rR   rS   r   _parquet_encryptionFileSystemKeyMaterialStorefor_filern   get_key_id_setr   allget_key_materialrT   )rV   r   r(   r=   r6   r7   rW   rX   storekey_idsks   &&&        r   *test_encrypted_parquet_write_read_externalr    s    
 \!D,@/<W"-$) $224)!6#%L ""==FFtLE%..00w1&22<@AAEG G GwGw!&&q)5wGHHHH\**** Hs   Dzdouble wrapping)idFzsingle to double wrappedzdouble to singe wrappedzsingle wrappingc                  aaaa V \         ,          p\        P                  ! \        \        RR./RSR7      p\        P
                  ! RR7      pR p\        P                  ! V4      p\        VVVVV4       \        V4      oVP                  R4       VP                  VVSR	7       \        V4      o\        V4       \        V\        P                  ! 4       VVRR
7      p	\        S9   g   Q h\        S9   g   Q h\        S9   g   Q h\        S9   g   Q hR VVVV3R llp
V
! \        4       V
! \        4       VP                  V	4      '       g   Q hR# )a  Tests CryptoFactory.rotate_master_keys

Note: The CryptoFactory.rotate_master_keys() double_wrapping keword arg
may be either True (the default) or False regardless of whether
EncryptionConfig.double_wrapping was set to true (also the default) when
the external key material store was written. This means double wrapping may
be set one way initially and then applied or removed during rotation.
r   r   F)r	   r   r'   r   1)r   c                     \        V 4      # r-   )r   r/   s   &r   r1   8test_external_key_material_rotation.<locals>.kms_factoryR  s    &'CDDr   2)r   r   c                (    V ^8  d   QhR\         RR/# )r   master_key_idreturnN)str)formats   "r   __annotate__9test_external_key_material_rotation.<locals>.__annotate__r  s     & &3 &4 &r   c                    < S	V ,          pS
'       d   VP                   pMVP                  p\        V4      w  r4pSV ,          pS'       d   VP                   pMVP                  p\        V4      w  r7pWG8  g   Q hR # r-   )wrapped_kekwrapped_dekr   )r
  before_key_matbefore_key_wrapped_
before_verafter_key_matafter_key_wrapped	after_ver
after_keysbefore_keysdouble_wrap_initialdouble_wrap_rotateds   &       r   check_rotated_external_keysHtest_external_key_material_rotation.<locals>.check_rotated_external_keysr  sz    $]3!/!;!;!/!;!;,-?@q"=1 - 9 9 - 9 9+,=>a %%%r   N)rN   r!   r"   r#   r$   r4   r5   r<   r   refresh_key_access_tokenrotate_master_keysr   rS   rR   rT   )reusable_tempdirr   r  r  r=   r@   r6   r1   r7   table_read_after_rotationr  r  r  s   &&ff       @@r   #test_external_key_material_rotationr$  5  sR   & l*D22"!C:.#+	- 22CHE%%k2N -T2K 2237%%+ & -
 ,D1J$ 6
""$#!% k)));&&&j(((:%%%& &"  0-67777r   c           	        V \         ,          p\        W1\        \        \        \
        V4      w  rE\        V4       \        P                  ! \        RR7      R7      p\        ^24       F\  pVP                  WF4      pVf   Q h\        P                  ! W8R7      p	V	P                  RR7      p
VP                  V
4      '       d   K\  Q h	  R# )z\Write an encrypted parquet, verify it's encrypted,
and then read it multithreaded in a loop.rE   rF   rM   Nrf   Trh   )rN   rA   r#   r$   rP   rQ   r   r!   rR   r   rangerj   r_   rp   rq   rT   )rV   r   r%   r=   r6   r7   rW   irj   rs   rX   s   &&&        r   test_encrypted_parquet_loopr(    s     \!D
 -A/<W-!) $22 -/ 2Y%3%N%N!&6")555D{{t{4  .... r   c           	     d   V \         ,          p\        W1\        \        \        \
        V4      w  rE\        V4       \        P                  ! \        RR7      R7      pVP                  WF4      p?\        P                  ! W7R7      pVP                  RR7      p	VP                  V	4      '       g   Q hR# )zV
Test that decryption properties can be used if the crypto factory is no longer alive
rE   rF   rM   rf   Trh   N)rN   rA   r#   r$   rP   rQ   r   r!   rR   r   rj   r_   rp   rq   rT   )
rV   r   r%   r=   r6   r7   rW   rj   rs   rX   s
   &&&       r   %test_read_with_deleted_crypto_factoryr*    s     \!D,@/<W-!) $ 22 -/!/!J!J"2^^@F;;4;0L\****r   c           	        V \         ,          p\        W1\        \        \        \
        V4      w  rE\        P                  ! \        RR7      R7      pVP                  WF4      p\        P                  ! W7R7      pVP                  V4      '       g   Q h\        P                  ! WR7      pVP                  V4      '       g   Q hR# )z>Write an encrypted parquet then read it back using read_table.rE   rF   rM   rf   N)rN   rA   r#   r$   rP   rQ   r!   rR   r   rj   r_   
read_tablerT   )	rV   r   r%   r=   r6   r7   rW   rj   rX   s	   &&&      r   !test_encrypted_parquet_read_tabler-    s    \!D -A/<W-!) 22 -/!/!J!J"2 ==XL \**** ==CL\****r   )T)r  r  ):rw   datetimer   pyarrowr   pyarrow.parquetparquetr_   pyarrow.parquet.encryption
encryptionr!    pyarrow.tests.parquet.encryptionr   r   r   r   r   ImportErrorrN   rP   r#   rQ   r$   markparquet_encryption
pytestmarkfixturer   r%   r(   r8   rA   rY   r[   r<   rS   r|   r   r   r   r   r   r   r   r   r   r   r   r   xfailr   r  parametrizeparamr$  r(  r*  r-  r   r   r   <module>r=     s  "   E ++
E E 0 

 KK""
KK
 h   h#  # h&  &1 1,+>+6"). "F61/A"A(G*!GHG(GB ;FI<:  2 3C3CN+2 2T4$56UD%?@T5%>?UE&78	5:;J8;J8Z/:+0+M  	B	Bs   F FF