o
    i                      @   st  d dl Z d dlZd dlZd dlmZ d dlmZmZmZm	Z	m
Z
mZmZmZ d dlZd dlZzd dlmZmZmZmZ d dlmZ W n ey]   d dlmZmZmZmZ d dlmZ Y nw d dlmZmZ d dlmZmZm Z  d d	l!m"Z"m#Z# d
Z$dZ%G dd deZ&G dd deZ'G dd deZ(ddddZ)ddddZ*ddddZ+ddddZ,dd Z-dd Z.dd Z/dd Z0dd Z1d d! Z2d"d# Z3d$d% Z4d&d' Z5d(d) Z6d*d+ Z7d,d- Z8d.d/ Z9d0d1 Z:d2d3 Z;d4d5 Z<d6d7 Z=d8d9 Z>d:d; Z?d<d= Z@d>d? ZAd@dA ZBdBdC ZCdDdE ZDdFdG ZEdHdI ZFdJdK ZGdLdM ZHdNdO ZIdPdQ ZJdRdS ZKdTdU ZLdVdW ZMdXdY ZNdZd[ ZOd\d] ZPd^d_ ZQd`da ZRdbdc ZSddde ZTdfdg ZUejVWdhdidjgdkdl ZXejVWdmdndogdpdq ZYdrds ZZdtdu Z[ejVWdvg dwdxdy Z\dzd{ Z]d|d} Z^d~d Z_ejVj`ea dkdddd Zbdd Zcdd Zddd ZeejVWdddgdd Zfdd ZgejVWdddgdd Zhdd Zidd ZjejVWdddgdd Zkdd Zldd Zmdd Zndd Zodd ZpejVWdg dg dfg ddg dfdgdg dfgdd Zqdd Zrdd Zsdd Ztdd Zudd Zvdd Zwdd ZxejVWdddeygddezgddezggdd Z{ejVWdg dâg dĢg dŢg dƢg dǢg dȢg dɢg dʢg dˢg d̢g d͢ej|dddejVj}dэg dҢg dӢg dԢej|dddejVj}dэg d֢g dעg dآej|dddejVj}dэg dڢg dۢg dܢej|dddejVj}dэgdd߄ Z~dd Zdd ZdS )    N)GeneratorType)AnyCallableDictIterableListOptionalTupleUnion)	BaseModelPositiveIntStrictFloatconstr)
StrictBool)r   r   r   r   )ConfigConfigValidationError)Catmake_tempdirmy_registry)	Generatorpartiala  
[optimizer]
@optimizers = "Adam.v1"
beta1 = 0.9
beta2 = 0.999
use_averages = true

[optimizer.learn_rate]
@schedules = "warmup_linear.v1"
initial_rate = 0.1
warmup_steps = 10000
total_steps = 100000

[pipeline]

[pipeline.classifier]
name = "classifier"
factory = "classifier"

[pipeline.classifier.model]
@layers = "ClassifierModel.v1"
hidden_depth = 1
hidden_width = 64
token_vector_width = 128

[pipeline.classifier.model.embedding]
@layers = "Embedding.v1"
width = ${pipeline.classifier.model:token_vector_width}

z
[optimizer]
@optimizers = "Adam.v1"
beta1 = 0.9
beta2 = 0.999
use_averages = true

[optimizer.learn_rate]
@schedules = "warmup_linear.v1"
initial_rate = 0.1
warmup_steps = 10000
total_steps = 100000
c                   @   s,   e Zd ZU eed< eed< G dd dZdS )HelloIntsSchemahelloworldc                   @      e Zd ZdZdS )zHelloIntsSchema.ConfigforbidN__name__
__module____qualname__extra r!   r!   P/home/ubuntu/.local/lib/python3.10/site-packages/confection/tests/test_config.pyr   G       r   N)r   r   r   int__annotations__r   r!   r!   r!   r"   r   C      
 r   c                   @   s0   e Zd ZU eed< dZeed< G dd dZdS )DefaultsSchemarequireddefault valueoptionalc                   @   r   )zDefaultsSchema.Configr   Nr   r!   r!   r!   r"   r   O   r#   r   N)r   r   r   r$   r%   r*   strr   r!   r!   r!   r"   r'   K   s   
 r'   c                   @   s<   e Zd ZU eed< dZeed< eed< eddZ	eed< dS )	ComplexSchema	outer_reqr)   	outer_opt
level2_req   )r(   
level2_optN)
r   r   r   r$   r%   r.   r+   r   r'   r1   r!   r!   r!   r"   r,   S   s
   
 r,   	catsie.v1FT@catsevilcutec                  C   s8   ddd} t | t\}}}|| ksJ || ksJ d S )Nr0      r   r   )r   _fillr   )simple_configf_vr!   r!   r"   test_validate_simple_configa   s   
r>   c                  C   sj   ddd} t t}t| t W d    n1 sw   Y  |j}t|jdks,J d|j	v s3J d S )Nr0   hi!r8   type_error.integer)
pytestraisesr   r   r9   r   valuelenerrorserror_types)invalid_configexc_infoerrorr!   r!   r"   test_invalidate_simple_configh   s   
rJ   c                  C   sH   dddd} t t t| t W d    d S 1 sw   Y  d S )Nr0   r7      )r   r   r    )rA   rB   r   r   r9   r   )rG   r!   r!   r"   test_invalidate_extra_argsq   s   "rL   c                  C   s~   ddi} t | t\}}}|d dksJ |d dksJ ddi}tt t |t W d    d S 1 s8w   Y  d S )Nr(   r0   r*   r)   z
some value)r   r9   r'   rA   rB   r   )valid_configfilledr<   r=   rG   r!   r!   r"    test_fill_defaults_simple_configw   s   "rO   c                  C   s   ddddd} t | t\}}}|d dksJ |d dks!J |d	 d
 dks+J |d	 d dks5J |d d dks?J |d d dksIJ d S )Nr0         r8   )r-   r/   r-   r.   r)   r/   r   r   r1   r(   r*   )r   r9   r,   )rM   rN   r<   
validationr!   r!   r"   test_fill_recursive_config   s   rS   c                  C   sL   t tsJ t ddirJ t drJ dddd} t | s$J d S )Nr   r   r0   
complex.v1      ?r2   @complexrater4   )r   
is_promisegood_catsie)invalidr!   r!   r"   test_is_promise   s
   r\   c                   C   s   t tdks	J d S )N)catsr2   )r   get_constructorrZ   r!   r!   r!   r"   test_get_constructor   s   r_   c                  C   s0   t t\} }| g ksJ |dddksJ d S )NT)r5   r6   )r   
parse_args
bad_catsie)argskwargsr!   r!   r"   test_parse_args   s   rd   c                  C   s*   t t} d| jv sJ d| jv sJ d S )Nr5   r6   )r   make_promise_schemarZ   
__fields__schemar!   r!   r"   test_make_promise_schema   s   
ri   c                  C   s>   dt d} t| t\}}}|| ksJ |dddksJ d S )Nr0   r(   r*   meow)rZ   r   r9   r'   configrN   r<   	validatedr!   r!   r"   test_validate_promise   s   
ro   c                  C   s:   ddddd} t | t\}}}|d d du sJ d S )	Nr0   r2   Fr4   r5   rj   r*   r6   T)r   r9   r'   rl   r!   r!   r"   test_fill_validate_promise   s   rq   c                  C   s   ddddd} t t t| t W d    n1 sw   Y  d| d d< t t t| t W d    d S 1 s@w   Y  d S )	Nr0   r2   Frp   rj   Tr*   whiskers)rA   rB   r   r   r9   r   r'   )rm   r!   r!   r"   test_fill_invalidate_promise   s   "rs   c                   C   sf   t jtjdddt_ttdsJ ttj dksJ tjjddd d ttj d	ks1J d S )
NdogsFentry_pointsr   zgood_boy.v1c                 S      | S Nr!   xr!   r!   r"   <lambda>   s    z&test_create_registry.<locals>.<lambda>)funcr0   )		cataloguecreater   	namespacert   hasattrrD   get_allregisterr!   r!   r!   r"   test_create_registry   s   r   c                   C   s   t t tdd W d    n1 sw   Y  tjdd  t t tdd W d    d S 1 s:w   Y  d S )N	dfkoofkdsr2   zcatsie.v123r]   )rA   rB   
ValueErrorr   getr]   r   r!   r!   r!   r"   test_registry_methods   s   "r   c                  C   s   dddddid} t d| id }|d dksJ |d	 dd
iks%J tt d	ddddii} t |  W d    d S 1 sDw   Y  d S )Nr0   threer2   Trp   onetwocfgr   r   scratch!truer   resolverA   rB   r   rm   resultr!   r!   r"   test_resolve_no_schema   s   "r   c                     s  G dd dt G fdddt  G  fdddt } ddd	d
did}tjd|i| d ddd	d
did}tt tjd|i| d W d    n1 sRw   Y  ddd	d
did}tt tjd|i| d W d    d S 1 s{w   Y  d S )Nc                   @      e Zd ZU eed< dS )z.test_resolve_schema.<locals>.TestBaseSubSchemar   N)r   r   r   r+   r%   r!   r!   r!   r"   TestBaseSubSchema      
 r   c                       s,   e Zd ZU eed<  ed< G dd dZdS )z+test_resolve_schema.<locals>.TestBaseSchemar   r   c                   @   r   )z2test_resolve_schema.<locals>.TestBaseSchema.Configr   Nr   r!   r!   r!   r"   r      r#   r   N)r   r   r   r   r%   r   r!   )r   r!   r"   TestBaseSchema   r&   r   c                          e Zd ZU  ed< dS )z'test_resolve_schema.<locals>.TestSchemar   Nr   r   r   r%   r!   r   r!   r"   
TestSchema   r   r   r0   r   r2   Trp   r   r   rg   four)r   r   r   rA   rB   r   )r   rm   r!   )r   r   r"   test_resolve_schema   s   "r   c                     s   G dd dt  G  fdddt } dddd}tjd	|i| d
}tjd	|i| d
}|d	 ddddks6J |d	 |ks>J d S )Nc                   @   s&   e Zd ZU eed< eed< eed< dS )z3test_resolve_schema_coerced.<locals>.TestBaseSchematest1test2test3N)r   r   r   r+   r%   boolfloatr!   r!   r!   r"   r      s   
 r   c                       r   )z/test_resolve_schema_coerced.<locals>.TestSchemar   Nr   r!   r   r!   r"   r      r   r   {   r0      )r   r   r   r   rg   123Tg      @)r   r   fillr   )r   rm   rN   r   r!   r   r"   test_resolve_schema_coerced   s   r   c                  C   s~   t d} t | }|d d dksJ |d d d dks!J |d d	 d
 d	ks-J |d d	 d d d dks=J d S )Nutf8	optimizerbeta1?
learn_rateinitial_rate皙?pipeline
classifierfactorymodel	embeddingwidth   )EXAMPLE_CONFIGencoder   
from_bytes)byte_stringr   r!   r!   r"   test_read_config  s   
$r   c                  C   s0   t  t} tj| ddd }|jdksJ d S )NTvalidater   r   )r   from_strOPTIMIZER_CFGr   r   r   )r   r   r!   r!   r"   test_optimizer_config  s   r   c                  C   sV   t  t} |   t ksJ t dddiit} |   t ks)J d S )Nr   foobar)r   r   r   to_strstripr   r!   r!   r"   test_config_to_str  s   r   c                  C   s0   t ddddiii} |   d ksJ d S )Nr   r   r   r0   z*
[optimizer]

[optimizer.foo]
bar = 1
    )r   r   r   r   r!   r!   r"   .test_config_to_str_creates_intermediate_blocks  s
   
r   c                  C   sn   d} ddddi}t  | }||ksJ t |}||ksJ | }d|v s)J t  |}||ks5J d S )NzK
        [section]
        node1 = "^a$$"
        node2 = "$$b$$c"
        sectionz^a$z$b$c)node1node2z^a$$r   r   r   )section_strsection_dictr   cfg_strnew_cfgr!   r!   r"   test_config_to_str_escapes%  s   r   c                  C   s<   t  t} |  }t  |}|  t ksJ d S rx   )r   r   r   to_bytesr   r   r   )r   	cfg_bytesr   r!   r!   r"   test_config_roundtrip_bytes<  s   r   c                  C   sl   t  t} t }|d }| | t  |}W d    n1 s#w   Y  |  t ks4J d S Nz
config.cfg)r   r   r   r   to_disk	from_diskr   r   )r   pathcfg_pathr   r!   r!   r"   test_config_roundtrip_diskC  s   
r   c                 C   sF   t  t}| d }|| t  |}|  t ks!J d S r   )r   r   r   r   r   r   r   )pathy_fixturer   r   r   r!   r!   r"   3test_config_roundtrip_disk_respects_path_subclassesL  s
   
r   c                  C   s   ddddd} t t t|   W d   n1 sw   Y  d}t t t | W d   dS 1 s<w   Y  dS )zTest that an error is raised if a config contains top-level keys without
    a section that would otherwise be interpreted as [DEFAULT] (which causes
    the values to be included in *all* other sections).
    r0   r2   r   rp   r   Nz[DEFAULT]
one = 1)rA   rB   r   r   r   r   )r   
config_strr!   r!   r"   #test_config_to_str_invalid_defaultsT  s   "r   c               	   C   s  		ddt dtdtddfdd	} tjtjd
ddt_td|  ddddd}td|i ddddd}t	
t td|i W d    n1 sNw   Y  ddddd}t	
t td|i W d    n1 sqw   Y  ddddd}t	
t t| W d    n1 sw   Y  t	
t t| W d    n1 sw   Y  dddd}t	
t td|i W d    d S 1 sw   Y  d S )N
   ERRORrX   steps	log_levelz(DEBUG|INFO|WARNING|ERROR))regexc                 S      d S rx   r!   )rX   r   r   r!   r!   r"   complex_argsb  s   z2test_validation_custom_types.<locals>.complex_argscomplexFru   rT   rU      INFO)rW   rX   r   r   rm   r   noner2   rV   )r   r   )r   r   r   r}   r~   r   r   r   r   rA   rB   r   r   )r   r   r!   r!   r"   test_validation_custom_typesa  sD   
"r   c                  C   s   dddddid} t jd| idd	}t jd| idd	}|d d
 dks&J |d d ddiks2J |d d d d dks@J |d d d d du sNJ d S )Nr0   r   r2   falserp   r   r   Fr   r   r   r   r5   r6   T)r   r   r   )rm   r   rN   r!   r!   r"   test_validation_no_validate  s    r   c                  C   s   ddddddi} t j| dd}t|d d	 d
ksJ tt t |  W d    n1 s2w   Y  ddddddi} t | }t|d d	 dksRJ |d d	 d du s^J |d d	 d du sjJ |d d	 d dksvJ d S )Nr   r0   r2   r   rp   r   Fr   r   rK   z	catsie.v2rP   r5   r6   T
cute_level)r   r   rD   rA   rB   r   r   r!   r!   r"   test_validation_fill_defaults  s   
r   c                  C   sX   t ddddtt dtfdd} dd	g}d
dd|di}t |d
 dks*J d S )Nzcatsie.v567r   r   rb   r   c                 W   s4   |d dksJ |d dksJ | dksJ |d S )Nr   ^_^r0   ^(*.*)^bazr!   r   rb   r!   r!   r"   
catsie_567  s   z4test_make_config_positional_args.<locals>.catsie_567r   r   rm   r   )r4   r   *)r   r]   r   r+   r   )r   rb   r   r!   r!   r"    test_make_config_positional_args  s
   r   c                  C   s   t ddddtdtfdd} t dd	tfd
d}dddddiidi}t j|dd}|d d dks9J |d d dddiiksGJ d S )Nzcatsie.v568r   r   rb   r   c                 W   s$   |d dksJ | dksJ |d S )Nr   r   r   r!   r   r!   r!   r"   
catsie_568  s   z>test_fill_config_positional_args_w_promise.<locals>.catsie_568zcat_promise.v568returnc                   S   s   dS )Nr   r!   r!   r!   r!   r"   cat_promise     z?test_fill_config_positional_args_w_promise.<locals>.cat_promiserm   promiser4   r4   r   Tr   r   )r   r]   r+   r   )r   r   r   rN   r!   r!   r"   *test_fill_config_positional_args_w_promise  s   
 r   c                  C   s   t ddttttf  fdd} ddg ddi}t |d dks&J dddd	gdi}tt	 t | W d    d S 1 sEw   Y  d S )
Nzcatsie.v890rb   c                  W   s   | d dksJ | d S )Nr   r   r!   )rb   r!   r!   r"   
catsie_890  s   z<test_make_config_positional_args_complex.<locals>.catsie_890rm   )r   Tr0   Fr   r   True)
r   r]   r   r
   r   r   r   rA   rB   r   )r   r   r!   r!   r"   (test_make_config_positional_args_complex  s   "r   c                  C   sT  d} t  |  | ksJ d} t  |  | ksJ tddddd}d} tt  |  }|d	ks;J tt  | }|d
diksLJ d} tt  |  }|dks_J tt  | }|d
ddifikssJ tdddtfdd}d} tt  |  }d}||ksJ d} tt  | }|d
diksJ d S )Nz[a]
b = 1
* = ["foo","bar"]z1[a]
b = 1

[a.*.bar]
test = 2

[a.*.foo]
test = 1zcatsie.v666F)rk   c                 W   s   |S rx   r!   )rk   rb   r!   r!   r"   
catsie_666  r   z7test_positional_args_to_from_string.<locals>.catsie_666z+[a]
@cats = "catsie.v666"
* = ["foo","bar"]z8[a]
@cats = "catsie.v666"
* = ["foo","bar"]
meow = falsea)r   r   z*[a]
@cats = "catsie.v666"

[a.*.foo]
x = 1z7[a]
@cats = "catsie.v666"
meow = false

[a.*.foo]
x = 1rz   r0   zcatsie.v777yc                 S   s   d|  S )Nrk   r!   )r  r!   r!   r"   
catsie_777     z7test_positional_args_to_from_string.<locals>.catsie_777z:[a]
@cats = "catsie.v666"

[a.*.foo]
@cats = "catsie.v777"zM[a]
@cats = "catsie.v666"
meow = false

[a.*.foo]
@cats = "catsie.v777"
y = 1z@[a]
@cats = "catsie.v666"

[a.*.foo]
@cats = "catsie.v777"
y = 3)meowmeowmeowr0   )r   r   r   r   r]   r   r   r$   )r   r   rN   resolvedr  expectedr   r!   r!   r"   #test_positional_args_to_from_string  s2   r	  c                  C   sZ   t ddtdd fdd} t dddtdtt fd	d
}ddddi}t | d S )Nztest_optimizer.v1rX   r   c                 S   r   rx   r!   rX   r!   r!   r"   test_optimizer_v1  r   z>test_validation_generators_iterable.<locals>.test_optimizer_v1ztest_schedule.v1rU   
some_valuec                 s   s    	 | V  qrx   r!   )r  r!   r!   r"   test_schedule_v1     z=test_validation_generators_iterable.<locals>.test_schedule_v1r   r   @optimizersrX   )rU   )r   
optimizersr   	schedulesr   r   )r  r  rm   r!   r!   r"   #test_validation_generators_iterable  s   r  c                  C   s<   t dddtddfdd} ddd	d
di}t | dS )zFTest that unset type hints are handled correctly (and treated as Any).test_optimizer.v2r   r   r   Nc                 S   r   rx   r!   )rX   r   r!   r!   r"   test_optimizer_v2  r   z;test_validation_unset_type_hints.<locals>.test_optimizer_v2testr   r   )r  rX   r   r   )r   r  r$   r   )r  rm   r!   r!   r"    test_validation_unset_type_hints  s   r  c                  C   s   t dddd} t dddd}dd	dii}tt t | W d    n1 s/w   Y  ddd
di}tt t | W d    d S 1 sQw   Y  d S )Nzbad.v1r   c                   S   s   t d)Nz This is an error in the function)r   r!   r!   r!   r"   bad  r  z)test_validation_bad_function.<locals>.badzgood.v1c                   S   r   rx   r!   r!   r!   r!   r"   good  r   z*test_validation_bad_function.<locals>.goodr  r  r0   )r  invalid_arg)r   N)r   r  rA   rB   r   r   r   )r  r  rm   r!   r!   r"   test_validation_bad_function
  s   "r  c                  C   sL   ddddddddi} t | d }|jdksJ |jdgd ks$J d S )	Nr   zmy_cool_optimizer.v1g?zmy_cool_repetitive_schedule.v1gMbP?rP   )
@schedules	base_raterepeat)r  r   r   )r   r   r   r   )rm   r   r!   r!   r"   test_objects_from_config  s   r   c                     s  t d ddddttdf dtdtd	tt f fd
dtdddddtdtd	ttt gtt f ffdd} d}d|ddi}t	|d }t
|dsTJ tt|jdks`J t|jd jdksmJ  |djdksyJ d|dgdi}t t t	| W d   n1 sw   Y  d|dddi}t t t	| W d   dS 1 sw   Y  dS )zgTest that functions registered with partial applications are handled
    correctly (e.g. initializers).numpygr   lohishape.r#  r$  r   c                   s    j |||  S rx   )randomuniformtolist)r%  r#  r$  )r!  r!   r"   uniform_init5  s   z/test_partials_from_config.<locals>.uniform_initzuniform_init.v1c                    s   t  | |dS )Nr"  r   r"  )r)  r!   r"   configure_uniform_init:  s   z9test_partials_from_config.<locals>.configure_uniform_initr  gɿ)@initializersr#  __call__rK   )r7   rK   g      ?Nr   )r,  r#  other)rA   importorskipr	   r$   r   r   r   initializersr   r   r   rD   inspect	signature
parametersdefaultasarrayr%  rB   r   )r+  namer   r|   bad_cfgr!   )r!  r)  r"   test_partials_from_config0  sF   

"r8  c               
      s   ddt dt dt fdd tdddt dtt gt f f fdd	} td
ddtt gt f dt dtt gt f fdd}d
ddddd}td|id }|ddksWJ |ddks_J dS )zTest that partial functions are passed correctly to other registered
    functions that consume them (e.g. initializers -> layers).r0   r  br   c                 S   s   | | S rx   r!   r  r9  r!   r!   r"   test_initializerW  s   z:test_partials_from_config_nested.<locals>.test_initializerztest_initializer.v1c                    s   t  | dS )Nr9  r*  r<  r;  r!   r"   configure_test_initializerZ  s   zDtest_partials_from_config_nested.<locals>.configure_test_initializerztest_layer.v1initcc                    s    fddS )Nc                    s   |   S rx   r!   ry   r@  r?  r!   r"   r{   `  s    zFtest_partials_from_config_nested.<locals>.test_layer.<locals>.<lambda>r!   )r?  r@  r!   rA  r"   
test_layer^  s   z4test_partials_from_config_nested.<locals>.test_layerr   r   )r,  r9  )z@layersr@  r?  r  3   d      Nr  )r$   r   r0  r   layersr   )r>  rB  r   r|   r!   r=  r"    test_partials_from_config_nestedS  s   $.rG  c                  C   s   t ddd } ddi}t d|id }t|tsJ t ddtdtfd	d
}dddid}t d|id }t|tsBJ t ddtttf dtfdd}ddddiid}t d|id }t|tsmJ t ddtdtfdd}dS )ziTest that generator replacement for validation in config doesn't
    actually replace the returned value.ztest_schedule.v2c                   s   s    	 dV  q)NTr   r!   r!   r!   r!   r"   test_schedulep  r  z.test_validate_generator.<locals>.test_scheduler  r  r  rX   r   c                 S   rw   rx   r!   r
  r!   r!   r"   test_optimizer2y  r   z0test_validate_generator.<locals>.test_optimizer2r  ztest_optimizer.v3r  c                 S      | d S )NrX   r!   r  r!   r!   r"   test_optimizer3  r  z0test_validate_generator.<locals>.test_optimizer3)r  r  ztest_optimizer.v4c                  W   rJ  )Nr   r!   rK  r!   r!   r"   test_optimizer4  r  z0test_validate_generator.<locals>.test_optimizer4N)	r   r  r   
isinstancer   r  r   r   r+   )rH  r   r   rI  rL  rM  r!   r!   r"   test_validate_generatorl  s*   

rO  c                  C   s^   ddddd} t d| id }t|tsJ |jdksJ |jdu s&J |jdks-J dS )	zlTest that validation can handle checks against arbitrary generic
    types in function argument annotations.zgeneric_cat.v1z
int_cat.v1rK   )r4   value_in)r4   catr  Ngeneric_cat)r   r   rN  r   rP  	value_outr6  )r   rQ  r!   r!   r"   test_handle_generic_type  s   rT  r   z[a]
b = 1
c = 2

[a.c]
d = 3z%[a]
b = 1

[a.c]
d = 2

[a.c.d]
e = 3c                 C   s<   t t t |  W d   dS 1 sw   Y  dS )zThis would cause very cryptic error when interpreting config.
    (TypeError: 'X' object does not support item assignment)
    NrA   rB   r   r   r   r   r!   r!   r"    test_handle_error_duplicate_keys  s   "rV  zcfg,is_valid)z[a]
b = 1

[a.c]
d = 3T)z[a]
b = 1

[A.c]
d = 2Fc                 C   sP   |r
t  |  dS tt t  |  W d   dS 1 s!w   Y  dS )zTest that you can't expand a block that hasn't been created yet. This
    comes up when you typo a name, and if we allow expansion of undefined blocks,
    it's very hard to create good errors for those typos.
    Nr   r   rA   rB   r   )r   is_validr!   r!   r"    test_cant_expand_undefined_block  s
   	"rY  c                  C   s  dddddddidi} d	di}t j| |dd
}|d d d d du s'J ddi}t j| |dd
}|d d d dks?J ddddd di}t j| |d}|d d d u sZJ |d d d dksfJ |d d d du srJ |d d d du s~J tt d	di}t j| |dd
 W d    n1 sw   Y  tt dddid di}t j| |d W d    n1 sw   Y  tt ddd}t j| |dd
 W d    n1 sw   Y  tt ddi}t j| |dd
 W d    d S 1 sw   Y  d S )Nr   r0   r   r2   TFr3   r   cfg.two.three.evil	overridesr   r   r5   cfg.two.threerK   rp   r\  r   r4   r6   r   )rZ  ztwo.fourcfg.five)r   r   rA   rB   r   rm   r\  r   r!   r!   r"   test_fill_config_overrides  sB   
$ra  c                  C   s  dddddddidi} d	di}t j| |dd
}|d d d dks%J ddi}t j| |dd
}|d d d dks=J ddddd di}t j| |d}|d d dksXJ |d d d u sbJ tt d	di}t j| |dd
 W d    n1 s~w   Y  tt dddid di}t j| |d W d    n1 sw   Y  tt ddd}t j| |dd
 W d    n1 sw   Y  tt ddi}t j| |dd
 W d    d S 1 sw   Y  d S )Nr   r0   r   r2   TFr3   r   rZ  r[  r   rk   r]  rK   rp   r^  r   r   r4   )rZ  zcfg.two.fourr_  r   r`  r!   r!   r"   test_resolve_overrides  s>   
"rb  zprop,expected))za.b.cT)a.bT)r  T)za.eT)za.b.c.dFc                 C   s0   ddddddgdi}t | ||u sJ d S )Nr  r      r@  dr0   r7   r9  e)r   _is_in_config)propr  rm   r!   r!   r"   test_is_in_config
  s   rk  c                  C   s|   G dd dt } tddd| dtfdd}d	d|  d
di}tj|dd}|d	 }t|d | s4J |d d
ks<J d S )Nc                   @   s   e Zd Zdd ZdS )z/test_resolve_prefilled_values.<locals>.Languagec                 S   r   rx   r!   )selfr!   r!   r"   __init__  s   z8test_resolve_prefilled_values.<locals>.Language.__init__N)r   r   r   rm  r!   r!   r!   r"   Language  s    rn  zprefilled.v1r   nlprC   c                 S   s   | |fS rx   r!   )ro  rC   r!   r!   r"   	prefilled  r  z0test_resolve_prefilled_values.<locals>.prefilledr  2   )r  ro  rC   Tr   r   r0   r  )objectr   r  r$   r   rN  )rn  rp  rm   r  r   r!   r!   r"   test_resolve_prefilled_values  s   rs  c                  C   s   t jddtdtttf fdd} ddddd	}t jd
|iddd
 d }|d du s0J d|vs6J t jd
|iddd
 d }|d du sKJ dS )zFTest that a registered function returning a dict is handled correctly.zcatsie_with_dict.v1r5   r   c                 S   s
   d|  iS )Nnot_evilr!   )r5   r!   r!   r"   catsie_with_dict(  s   
z;test_fill_config_dict_return_type.<locals>.catsie_with_dictFrp   r   )r  r   r   Tr   r  rt  N)	r   r]   r   r   r   r+   r   r   r   )ru  rm   r   r!   r!   r"   !test_fill_config_dict_return_type%  s   
rv  c                  C   s8   t ddddd} |  }| |ksJ | |usJ d S )Nr0   r7   rK   re  r:  )r   copy)rm   copiedr!   r!   r"   test_deepcopy_config4  s   ry  PyPyzcopy does not fail for pypy)reasonc                  C   sP   t d} td| d}t t |  W d    d S 1 s!w   Y  d S )Nr!  r0   r:  )rA   r/  r   rB   r   rw  )r!  rm   r!   r!   r"   test_deepcopy_config_pickle<  s
   

"r|  c                  C   s<   d} t  | }|d d d dksJ | | ksJ dS )z`Test that references to function registries without arguments are
    serialized inline as dict.z,[section]
subsection = {"@registry":"value"}r   
subsectionz	@registryrC   Nr   r   rm   r!   r!   r"   "test_config_to_str_simple_promisesG  s   r  c                  C   sz   d} t t t |  W d    n1 sw   Y  d} t t t |  W d    d S 1 s6w   Y  d S )Nz[a]
b = null

[a.b]
c = 1z[a]
b = null

[a.b.c]
d = 1rU  r   r!   r!   r"   $test_config_from_str_invalid_sectionP  s   "r  c                  C   sD   ddddddddd	d
iid} d}t | } |  |ks J dS )z,Test that Config.to_str orders the sections.r0   r7   re  rK   rg  ghrP   r   )ij)r  r;   z=[a]
e = 3

[a.b]
c = 1
d = 2

[f]

[f.g]

[f.g.h]
i = 4
j = 5N)r   r   )rm   r  r!   r!   r"   test_config_to_str_orderZ  s
   $r  rf  .:c                 C   sT  d}t t t | W d   n1 sw   Y  d|  d}t |d d dks1J d|  d}t |d d d	ksEJ d
|  d}t |d d d	ksYJ d|  d}t |d d dksmJ d|  d}t |d d ddgksJ d|  d|  d}t |d d dksJ t |d d dksJ dS )a-  Test that config values are interpolated correctly. The parametrized
    value is the final divider (${a.b} vs. ${a:b}). Both should now work and be
    valid. The double {{ }} in the config strings are required to prevent the
    references from being interpreted as an actual f-string variable.
    z#[a]
foo = "hello"

[b]
bar = ${foo}Nz [a]
foo = "hello"

[b]
bar = ${afoo}r9  r   r   zfoo}!zhello!z![a]
foo = "hello"

[b]
bar = "${azfoo}!"z[a]
foo = 15

[b]
bar = ${az15!z#[a]
foo = ["x", "y"]

[b]
bar = ${arz   r  z[a]
foo = "x"
bar = ${azfoo}
baz = "${azfoo}y"r  r   xyrU  )rf  c_strr!   r!   r"   test_config_interpolationd  s"     r  c                  C   sZ  d} t  j| dd}|d d ddgksJ | }|d d ddgks&J d	} t  | }|d d g d
ks:J t  j| dd}d} t  | }|d d dddigksXJ d} tt t  |  W d    n1 spw   Y  d}t  |}|d d ddgddgksJ d}tt t  |  W d    d S 1 sw   Y  d S )Nz,[a]
b = 1

[c]
d = ["hello ${a.b}", "world"]Finterpolater@  rf  zhello ${a.b}r   hello 1z4[a]
b = 1

[c]
d = [${a.b}, "hello ${a.b}", "world"])r0   r  r   z"[a]
b = 1

[c]
d = ["hello", ${a}]r   r9  r0   z*[a]
b = 1

[c]
d = ["hello", "hello ${a}"]z=[a]
b = 1

[c]
d = ["hello", {"x": ["hello ${a.b}"], "y": 2}]r7   )rz   r  z5[a]
b = 1

[c]
d = ["hello", {"x": [${a.b}], "y": 2}])r   r   r  rA   rB   r   )r  rm   r   r!   r!   r"   test_config_interpolation_lists~  s.    "r  c                 C   sN  d}t  |}|d d |d ksJ d|  d}t  |}|d d d |d d ks0J d	|  d
|  d}t  |}|d d dksIJ d|  d}t  |}|d d dks_J d}t  |}|d d |d kssJ |d d |d ksJ d|  d}t  |}|d d |d d ksJ d}t  |}|d d |d ksJ d}t  |}|d d d |d ksJ d|  d}tt t  | W d   n1 sw   Y  d|  d}tt t  | W d   n	1 sw   Y  d}tt t  | W d   dS 1 s w   Y  dS )a/  Test that config sections are interpolated correctly. The parametrized
    value is the final divider (${a.b} vs. ${a:b}). Both should now work and be
    valid. The double {{ }} in the config strings are required to prevent the
    references from being interpreted as an actual f-string variable.
    z-[a]
foo = "hello"
bar = "world"

[b]
c = ${a}r9  r@  r  z [a]
foo = "hello"

[a.x]
y = ${azb}

[a.b]
c = 1
d = [10]rz   r  z%[a]
x = "string"
y = 10

[b]
z = "${azx}/${azy}"zz	string/10z0[a]
x = ["hello", "world"]

[b]
y = "result: ${azx}"zresult: ["hello", "world"]z-[a]
foo = "x"

[b]
bar = ${a}

[c]
baz = ${b}r   r   z,[a]
foo = "x"

[b]
bar = ${a}

[c]
baz = ${bzbar}z.[a]
foo = "x"

[a.b]
bar = 100

[c]
baz = ${a}z[a]
foo ="x"

[a.b]
bar = ${a}z0[a]
foo = "x"

[b]
bar = ${a}

[c]
baz = ${b.barr  Nz[a]
foo = ${bz/[a]

[a.b]
foo = "x: ${c}"

[c]
bar = 1
baz = 2rW  )rf  r  rm   r!   r!   r"   "test_config_interpolation_sections  sJ    $r  c                  C   s  d} ddd}t  j| |d}|d d dksJ |d d d	 dks%J |d d d
 dks1J t  j| ddid}|d d d	 dksGJ |d d d
 dksSJ |d d d dks_J tt t  j| ddid W d    n1 syw   Y  tt t  j| ddid W d    n1 sw   Y  d} t  j| ddid}|d d dksJ |d d d
 dksJ d} t  j| ddid}|d d d	 dksJ |d
 d d	diksJ d S )Nz0[a]
b = 1

[a.c]
d = 2
e = 3

[f]
g = {"x": "y"}r   r   )rc  a.c.dr^  r  r9  r@  rf  rh  rK   za.c.frD  r7   r;   zf.g.xr  z![a]
b = 1

[a.c]
d = 2
e = ${a:b}rc  z%[a]
b = 1

[a.c]
d = 2
[e]
f = ${a.c}r  rW  )r   r\  rm   r!   r!   r"   test_config_from_str_overrides  s0   
r  c                  C   s   t dddtfdd} ddd}t d|i}t d|i}|d du s(J |d |ks0J dd	d}tt t d|i W d
   d
S 1 sMw   Y  d
S )zTest that the auto-generated pydantic schemas auto-alias reserved
    attributes like "validate" that would otherwise cause NameError.zcatsie.with_aliasFr   c                 S   rw   rx   r!   r   r!   r!   r"   catsie_with_alias  r   z7test_config_reserved_aliases.<locals>.catsie_with_aliasT)r4   r   r  r   N)F)r   r]   r   r   r   rA   rB   r   )r  r   r  rN   r!   r!   r"   test_config_reserved_aliases  s   

"r  c                 C   s  t d}d|  d|  d}t j|dd}|jrJ |d d d	|  d
ks)J |d d d|  dks7J |d d dksAJ t j| dd}|jsPJ |d d dksZJ |d d dksdJ |d d ddikspJ | }|jsyJ |d d dksJ |d d dksJ |d d ddiksJ d|jddgddggddd|  ddi}t t	 t|  W d   dS 1 sw   Y  dS )a)  Test that interpolation is correctly preserved. The parametrized
    value is the final divider (${a.b} vs. ${a:b}). Both should now work and be
    valid. The double {{ }} in the config strings are required to prevent the
    references from being interpreted as an actual f-string variable.
    r!  z[a]
b = 1

[c]
d = ${azb}
e = "hello${azb}"
f = ${a}Fr  r@  rf  z${azb}rh  z	"hello${azb}"r;   z${a}Tr0   hello1r9  rz   r7   rP   r   dtypez${xzy})r  r  N)
rA   r/  r   r   is_interpolatedr   r  r5  rB   r   )rf  r!  r  rm   config2config3r   r!   r!   r"   test_config_no_interpolation  s*   



,"r  c                  C   s  d} t  j| dd}|jrJ |d d dksJ |d d d	ks#J t|}t|}|d d
ks5J |d d d
ks?J |d d dksIJ |d d du sSJ |d d d	ks]J | }|jsfJ |d d du spJ |d d |d ks|J t  j| dd}|jsJ t|}t|}|d d
ksJ |d d d
ksJ |d d du sJ |d d |d ksJ t  j| dd}|jrJ t|}|jrJ |d d d	ksJ t|}|d d d
ksJ d S )NzE[a]
bad = true
[b]
@cats = "catsie.v1"
evil = ${a:bad}

[c]
 d = ${b}Fr  r9  r5   z${a:bad}r@  rf  z${b}r   r6   T)r   r   r  r   r   r   r  )r   rm   rN   r  interpolatedr!   r!   r"   %test_config_no_interpolation_registry"  s>   










r  c                  C   s  dddid} ddddd}t || }t|d	ksJ |d
 dks&J |d dddks1J ddddd} dddd	ddd}t || }t|dksRJ |d
 dksZJ |d ddd	dksfJ |d dksnJ dddddd} dddd	dd}t || }t|dksJ |d
 dksJ |d dddksJ |d dksJ dddidd} dddd	dd}t || }t|dksJ |d
 dksJ |d ddd	dksJ |d dksJ dddidd} dddid}t || }t|dksJ |d
 dksJ |d ddiksJ |d dks"J dddidd} ddd}t || }t|dks?J |d
 dksHJ |d ddiksSJ |d dks\J d S )Nr   r@  rf  r:  r   rh  r  )r@  r;   r7   r  r9  rz   r0   )@testr   rD  )r  r   r   r  r9  r@  rK   r  r   z@fooz@bar)r   mergerD   )rm   defaultsmergedr!   r!   r"   test_config_deep_mergeE  sR   
r  c                  C   s   d} d}t  j| dd}t  |}||}|d dddd	ks#J |d
 dddks.J | d
 dddks;J t  d}t  jddd}||}|d d dksXJ d S )Nz[a]
b= 1
c = 2

[d]
e = ${a:b}z[a]
x = 100

[d]
y = 500Fr  r  r0   r7   rD  )r9  r@  rz   rf  z${a:b}i  )rh  r  z[a]
b= 1
c = 2z[a]
b = 100
c = ${a:b}r@  )r   r   r  r  )r   defaults_strrm   r  r  r!   r!   r"    test_config_deep_merge_variabless  s   

r  c                  C   s  t d} dddii}t| }|dksJ t |}t||ks%J dddii}t| }|dks7J t |}t||ksEJ dd| jg d	g d
gddii}t|}t t |  W d    n1 snw   Y  d}t j|dd}| |ksJ d S )Nr!  r   r   Fz[cfg]
foo = falser   z[cfg]
foo = "false"rz   )r0   r7   rK   rP   )rP   r   rK   rP   r;   r  z8[a]
b = 1

[c]
d = ${a:b}
e = "hello${a:b}"
f = "${a:b}"r  )	rA   r/  r   r   r   dictr5  rB   r   )r!  r   r   rm   r!   r!   r"   test_config_to_str_roundtrip  s&   
"
r  c                  C   s   d} t  j| dd}|jrJ |t dddii}|jrJ t |}|jr(J | }|js1J |t  j| dd}|jrAJ dS )zFTest that a config object correctly reports whether it's interpolated.z4[a]
b = 1

[c]
d = ${a:b}
e = "hello${a:b}"
f = ${a}Fr  rz   r  r  N)r   r   r  r  r  r~  r!   r!   r"   test_config_is_interpolated  s   



r  z(section_order,expected_str,expected_keysz?[a]
b = 1
c = 2

[a.d]
e = 3

[a.f]
g = 4

[h]
i = 5

[j]
k = 6)r  r  r  )r  r  r  z?[j]
k = 6

[h]
i = 5

[a]
b = 1
c = 2

[a.d]
e = 3

[a.f]
g = 4r  z?[h]
i = 5

[a]
b = 1
c = 2

[a.d]
e = 3

[a.f]
g = 4

[j]
k = 6)r  r  r  c                 C   s   ddidddidddid	d
did}t | }t || d |ks%J tt | d| }||ks7J tt || d }||ksGJ d S )Nkrd  r0   rh  rK   r7   r  rP   )r9  rf  r@  r;   r  r   )r  r  r  section_order)r   r   listr   keys)r  expected_strexpected_keysr   r   r  r!   r!   r"   !test_config_serialize_custom_sort  s   r  c            
      C   s   i i i d} g d}d}t | |d}| |ksJ | }| |ks&J |di i}| | dks8J t |}| |ksDJ d}g d}t |d|}t| |ks\J t|}	|	j	|kshJ d	S )
zpTest that sort order is preserved when merging and copying configs,
    or when configs are filled and resolved.)rz   r  r  )r  r  rz   z[y]

[z]

[x]r  r  z

[a]z9[a]
b = 1
[c]
@cats = "catsie.v1"
evil = true

[t]
 x = 2)r@  r  tN)
r   r   rw  r  r   r  r  r   r   r  )
r   r  r  rm   r  r  config4r   config5rN   r!   r!   r"    test_config_custom_sort_preserve  s"   
r  c                  C   sN   t ddig dd} t| }t|}|ddiksJ |jg dks%J d S )Nr   r   )r   r   r   r  )r   pickledumpsloadsr  )rm   data
config_newr!   r!   r"   test_config_pickle  s
   

r  c                     sR  G dd dt  G  fdddt } tddddd	i}tt tj|| d
 W d   n1 s3w   Y  tj|| ddd }|dddksKJ | }tj|| ddd }|dddksbJ tddddd	idd}tj|| ddd }|dddksJ G dd dt G fdddt }tj||ddd }|dddd	ksJ dS )z>Test that filling a config from a schema removes extra fields.c                   @   ,   e Zd ZU eed< eed< G dd dZdS )z8test_config_fill_extra_fields.<locals>.TestSchemaContentr  r9  c                   @   r   )z?test_config_fill_extra_fields.<locals>.TestSchemaContent.Configr   Nr   r!   r!   r!   r"   r     r#   r   Nr   r   r   r+   r%   r$   r   r!   r!   r!   r"   TestSchemaContent  r&   r  c                       r   )z1test_config_fill_extra_fields.<locals>.TestSchemar   Nr   r!   )r  r!   r"   r     r   r   r   1r7   Tr  rg   NF)rh   r   r:  )r  c                   @   r  )z9test_config_fill_extra_fields.<locals>.TestSchemaContent2r  r9  c                   @   r   )z@test_config_fill_extra_fields.<locals>.TestSchemaContent2.ConfigallowNr   r!   r!   r!   r"   r     r#   r   Nr  r!   r!   r!   r"   TestSchemaContent2  r&   r  c                       r   )z2test_config_fill_extra_fields.<locals>.TestSchema2r   Nr   r!   )r  r!   r"   TestSchema2  r   r  )r   r   rA   rB   r   r   r   r  )r   rm   rN   r  r  r  r!   )r  r  r"   test_config_fill_extra_fields  s$   r  c                  C   sj  G dd dt } ddd}tt}t||  W d    n1 s#w   Y  |j}|jdks2J |jd u s9J |j	r>J |j
du sEJ t|jdksNJ |jd d	 d
ksYJ |jd d dksdJ |jd d dksoJ |jtdgksyJ d}d}tj|||dd}|j|jksJ |j|jksJ |j|ksJ |j|ksJ |j
du sJ |j|jksJ d S )Nc                   @   s   e Zd ZU eed< eed< dS )z3test_config_validation_error_custom.<locals>.Schemar   r   Nr   r   r   r$   r%   r!   r!   r!   r"   Schema  s   
 r  r0   r?   r8   zConfig validation errorTr   loc)r   msgzvalue is not a valid integertyper@   zCustom errorzSome error description hereF)titledescshow_config)r   rA   rB   r   r   r9   rC   r  r  parentr  rD   rE   rF   set
from_errortext)r  rm   rH   e1r  r  e2r!   r!   r"   #test_config_validation_error_custom  s0   

r  c                  C   s@   d} t t t |  W d    d S 1 sw   Y  d S )Nz[a]
b crU  r  r!   r!   r"   test_config_parsing_error$  s   "r  c                  C   s  G dd dt } ddddi}t|}t|}|d dks!J |d d d	u s+J tt tj|| d
 W d    n1 sBw   Y  tj|| d
}|d d d	u sXJ t|}|d dkseJ G dd dt }ddddi}tj||d
}|d |d ksJ |d dksJ d S )Nc                   @   r   )z4test_config_fill_without_resolve.<locals>.BaseSchemacatsieNr  r!   r!   r!   r"   
BaseSchema+  r   r  r  r2   Frp   rk   r6   Trg   c                   @   s"   e Zd ZU eed< dZeed< dS )z5test_config_fill_without_resolve.<locals>.BaseSchema2r     r.  N)r   r   r   r   r%   r.  r$   r!   r!   r!   r"   BaseSchema2;  s   
 r  dogr.  r  )r   r   r   r   rA   rB   r   )r  rm   rN   r  filled2r  filled3r!   r!   r"    test_config_fill_without_resolve*  s$   


r  c                  C   sl   t dddd} dd| di}t|d }t|t sJ |j| jks$J |j| jks,J |j| jks4J d S )Ntestcatr0   r7   )rP  rS  r   z	catsie.v3)r4   arg)r   r   r   rN  r6  rP  rS  )rQ  rm   r   r!   r!   r"   test_config_dataclassesE  s   r  zgreeting,value,expectedV  	${vars.a}342everyonec                 C   s@   d| d}d| i}t  j||d}t|d d |ksJ d S )Nz
    [project]
    my_par = z%

    [vars]
    a = "something"
    vars.ar^  projectmy_par)r   r   r  greetingrC   r  str_cfgr\  r   r!   r!   r"   test_config_interpolatesO  s   
r  )	hello 342r  r  )hello everyoner  r  )hello tout le monder  r  )hello 42r  r  )r  [1, ${vars.a}, 3]r  )r  r  r  )r  r  r  )r  r  r  )r  hello ${vars.a}r  )r  r  r  )tout le monder  r  42r  r  )marks)r  [1, hello ${vars.a}, 3]r  )r  r  r  )r  r  r  r  )r  [1, 'hello ${vars.a}', '3']r  )r  r  r  )r  r  r  r  )r  +[{'name':'x','script':['hello ${vars.a}']}]r  )r  r  r  )r  r  r  r  c                 C   sD   d| d}d| i}d|v sJ t  j||d}|t|v s J d S )Nz
    [project]
    commands = z!

    [vars]
    a = "world"
    r  r  r^  )r   r   r+   r  r!   r!   r"   test_config_overridese  s   &r  c                  C   sR   d} t jtdd t |  W d    n1 sw   Y  d} t |  d S )Nz-
    [project]
    commands = 'do stuff'
    zsingle-quoted)matchz-
    [project]
    commands = some'thing
    )rA   warnsUserWarningr   r   )r  r!   r!   r"   test_warn_single_quotes  s   r  c                  C   s<   t  d} | d d g dksJ | d d dksJ dS )	zWTest whether strings interpretable as integers are parsed correctly (i. e. as strings).z4[a]
foo = [${b.bar}, "00${b.bar}", "y"]

[b]
bar = 3r  r   )rK   003r  r9  r   rK   N)r   r   r   r!   r!   r"   (test_parse_strings_interpretable_as_ints  s
   r  )r1  r  platformtypesr   typingr   r   r   r   r   r   r	   r
   r}   rA   pydantic.v1r   r   r   r   pydantic.v1.typesr   ImportErrorpydanticpydantic.types
confectionr   r   confection.tests.utilr   r   r   confection.utilr   r   r   r   r   r'   r,   rZ   	ok_catsiera   worst_catsier>   rJ   rL   rO   rS   r\   r_   rd   ri   ro   rq   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r	  r  r  r  r   r8  rG  rO  rT  markparametrizerV  rY  ra  rb  rk  rs  rv  ry  skipifpython_implementationr|  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r$   r+   r  paramxfailr  r  r  r!   r!   r!   r"   <module>   sH   (	
	


	#
"#(

'$

	



5 
#.

'

	
%