Ë
    ÛJêjÖx  ã                  ó²  — d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlZddlZddlmZ ddlZddlmZmZmZ ddlmZ ddlmZmZ ddlmZmZmZmZ dd	lm Z m!Z!m"Z" dd
l#m$Z$m%Z%m&Z& ddl'm(Z(m)Z) ddl*m+Z+m,Z,m-Z- ddl.m/Z/ dd„Z0d d!d„Z1d"d!d„Z2 G d„ d«      Z3 G d„ d«      Z4 G d„ d«      Z5 G d„ d«      Z6 G d„ d«      Z7 G d„ d«      Z8 G d„ d«      Z9y)#u  F4 tests â€” Model Intelligence, free-only routing and fail-closed egress.

Every test here exists to fail when the control it names stops working.  Tests
that pass regardless of the implementation were removed on purpose: a green
suite that cannot go red proves nothing.
é    )ÚannotationsN)ÚMock)ÚModelGatewayÚModelGatewayConfigÚModelNotAvailableError)ÚModelEgressGate)ÚKiloConfigBuilderÚNoFreeModelAvailable)ÚModelFreeStatusÚModelRecordÚModelRegistryÚModelStatus)ÚProviderRecordÚProviderRegistryÚProviderStatus)ÚModelRefÚNoAvailableModelÚRoleAssignmentStore)ÚModelRouterÚModelRouterError)Ú
EgressGateÚEgressPolicyÚEgressRequest)ÚSecurityErrorc                 ó  — t        «       }t        «       }| D ]d  }|j                  |«       |j                  |j                  «      �Œ0|j                  t        |j                  t        j                  d¬«      «       Œf |t        ||¬«      fS )z0Build a registry + router pair from ``records``.T)ÚproviderÚstatusÚapi_available©Úmodel_registryÚprovider_registry)	r   r   ÚregisterÚgetr   r   r   ÚACTIVEr   )ÚrecordsÚregistryÚ	providersÚrecords       úB/home/oem/CyberBrain26-unified/tests/test_f4_model_intelligence.pyÚ	_registryr*   6   s~   € ä‹€HÜ Ó"€IØò 	ˆØ×Ñ˜&Ô!Ø�=‰=˜Ÿ™Ó)Ñ1Ø×ÑÜØ#Ÿ_™_Ü)×0Ñ0Ø"&ôõð	ð ”[°ÈIÔVÐVÐVó    c                óX   — t        | |t        j                  t        j                  ¬«      S ©N©Úmodel_idr   r   Úfree_status)r   r   r$   r   ÚFREE©r/   r   s     r)   Ú_freer3   G   ó'   € ÜØØÜ×!Ñ!Ü#×(Ñ(ô	ð r+   c                óX   — t        | |t        j                  t        j                  ¬«      S r-   )r   r   r$   r   ÚPAIDr2   s     r)   Ú_paidr7   P   r4   r+   c                  óL   — e Zd Zd
d„Zd
d„Zd
d„Zd
d„Zd
d„Zd
d„Zd
d„Z	d
d„Z
y	)ÚTestRoleAssignmentc                ó^  — t        «       }|j                  dt        ddd¬«      «       |j                  dt        ddd¬«      «       |j                  } |«       }ddh}||k(  }|sÁt	        j
                  d|fd	||f«      d
t        j                  «       v st	        j                  |«      rt	        j                  |«      nd
t	        j                  |«      t	        j                  |«      t	        j                  |«      dœz  }dd|iz  }t        t	        j                  |«      «      ‚d x}x}x}}y )Núrole-xÚpzmodel-aT©Úis_freezrole-yzmodel-b©ú==)zN%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.distinct_models
}()
} == %(py7)sÚstore©Úpy0Úpy2Úpy4Úpy7úassert %(py9)sÚpy9)r   Úassignr   Údistinct_modelsÚ
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚAssertionErrorÚ_format_explanation)ÚselfrA   Ú@py_assert1Ú@py_assert3Ú@py_assert6Ú@py_assert5Ú@py_format8Ú@py_format10s           r)   Ú"test_two_roles_get_distinct_modelsz5TestRoleAssignment.test_two_roles_get_distinct_models_   sÇ   € Ü#Ó%ˆØ�‰�Xœx¨¨YÀÔEÔFØ�‰�Xœx¨¨YÀÔEÔFà×$Ñ$Ð@Ñ$Ó&Ð@¨9°iÐ*@Ð@Ð&Ð*@Ñ@×@×@Õ@Ð&Ð*@×@×@×@×@×@Ñ@ˆu×@×@Ó@ˆu×@×@Ô@Ð$×@×@Ò@Ð&×@×@Ò@Ð*@×@×@×@×@×@×@Ö@r+   c           	     óö  — t        «       }t        ddd¬«      }|j                  d|t        ddd¬«      g«       |j                  }d}d} |||¬«      }||u }|�st	        j
                  d|fd	||f«      d
t        j                  «       v st	        j                  |«      rt	        j                  |«      nd
t	        j                  |«      t	        j                  |«      t	        j                  |«      t	        j                  |«      dt        j                  «       v st	        j                  |«      rt	        j                  |«      nddœz  }dd|iz  }	t        t	        j                  |	«      «      ‚d x}x}x}x}}y )Nr<   ú
main-modelTr=   r;   Úbackup©Úmain_available©Úis©zn%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s.select_for_role
}(%(py4)s, main_available=%(py6)s)
} is %(py10)srA   Úmain©rC   rD   rE   Úpy6Úpy8Úpy10úassert %(py12)sÚpy12©r   r   rI   Úselect_for_rolerK   rL   rM   rN   rO   rP   rQ   rR   )
rS   rA   rc   rT   rU   rW   Ú@py_assert7Ú@py_assert9Ú@py_format11Ú@py_format13s
             r)   Ú-test_select_for_role_uses_main_when_availablez@TestRoleAssignment.test_select_for_role_uses_main_when_availablef   sñ   € Ü#Ó%ˆÜ˜˜\°4Ô8ˆØ�‰�X˜t¤h¨s°HÀdÔ&KÐ%LÔMà×$Ñ$ÐK XÐK¸dÐKÑ$ X¸dÔCÐKÐCÀtÐK×K×KÖKÐCÀt×K×K×K×K×KÑKˆu×K×KÓKˆu×K×KÔKÐ$×K×KÒK X×K×KÒK¸d×K×KÒKÐC×K×K×K×K×KÐKÀt×K×KÓKÀt×K×K×K×K×K×K×KÒKr+   c           	     óø  — t        «       }t        dddd¬«      }|j                  dt        ddd¬«      |g«       |j                  }d}d} |||¬	«      }||u }|�st	        j
                  d
|fd||f«      dt        j                  «       v st	        j                  |«      rt	        j                  |«      ndt	        j                  |«      t	        j                  |«      t	        j                  |«      t	        j                  |«      dt        j                  «       v st	        j                  |«      rt	        j                  |«      nddœz  }dd|iz  }	t        t	        j                  |	«      «      ‚d x}x}x}x}}y )Nr<   zfree-backupT©Úverifiedr>   r;   r\   r=   Fr^   r`   rb   rA   r]   rd   rh   ri   rj   )
rS   rA   r]   rT   rU   rW   rl   rm   rn   ro   s
             r)   Ú.test_select_for_role_falls_back_to_free_backupzATestRoleAssignment.test_select_for_role_falls_back_to_free_backupm   sò   € Ü#Ó%ˆÜ˜#˜}°tÀTÔJˆØ�‰�Xœx¨¨\À4ÔHÈ6È(ÔSà×$Ñ$ÐN XÐN¸eÐNÑ$ X¸eÔDÐNÐDÈÐN×N×NÖNÐDÈ×N×N×N×N×NÑNˆu×N×NÓNˆu×N×NÔNÐ$×N×NÒN X×N×NÒN¸e×N×NÒNÐD×N×N×N×N×NÐNÈ×N×NÓNÈ×N×N×N×N×N×N×NÒNr+   c           
     óô   — t        «       }|j                  dt        ddd¬«      t        dddd¬«      g«       t        j                  t
        «      5  |j                  dd¬	«       d d d «       y # 1 sw Y   y xY w)
Nr;   r<   r\   Tr=   zpaid-backupFrr   r^   ©r   rI   r   ÚpytestÚraisesr   rk   ©rS   rA   s     r)   Ú(test_select_for_role_refuses_paid_backupz;TestRoleAssignment.test_select_for_role_refuses_paid_backupt   sq   € Ü#Ó%ˆØ�‰ØÜ�S˜,°Ô5Ü�c˜=°4ÀÔGÐHô	
ô �]‰]Ô+Ó,ñ 	BØ×!Ñ! (¸5Ð!ÔA÷	B÷ 	Bñ 	Búó   ÁA.Á.A7c           
     óô   — t        «       }|j                  dt        ddd¬«      t        dddd¬«      g«       t        j                  t
        «      5  |j                  dd¬	«       d d d «       y # 1 sw Y   y xY w)
Nr;   r<   r\   Tr=   Ú
unverifiedFrr   r^   rv   ry   s     r)   Ú.test_select_for_role_refuses_unverified_backupzATestRoleAssignment.test_select_for_role_refuses_unverified_backup   sq   € Ü#Ó%ˆØ�‰ØÜ�S˜,°Ô5Ü�c˜<°%ÀÔFÐGô	
ô �]‰]Ô+Ó,ñ 	BØ×!Ñ! (¸5Ð!ÔA÷	B÷ 	Bñ 	Búr{   c                ó’   — t        j                  t        «      5  t        «       j	                  d«       d d d «       y # 1 sw Y   y xY w)NÚnope)rw   rx   r   r   rk   )rS   s    r)   Ú(test_select_for_role_unknown_role_raisesz;TestRoleAssignment.test_select_for_role_unknown_role_raisesŠ   s5   € Ü�]‰]Ô+Ó,ñ 	:ÜÓ!×1Ñ1°&Ô9÷	:÷ 	:ñ 	:ús	   š=½Ac                ó‚  — t        «       }|j                  dt        ddd¬«      «       |j                  dddd«       |j	                  d«      }d }||u}|s™t        j                  d|fd||f«      d	t        j                  «       v st        j                  |«      rt        j                  |«      nd	t        j                  |«      d
œz  }dd|iz  }t        t        j                  |«      «      ‚d x}}|j                  }ddddœg}||k(  }|s­t        j                  d|fd||f«      d	t        j                  «       v st        j                  |«      rt        j                  |«      nd	t        j                  |«      t        j                  |«      dœz  }dd|iz  }	t        t        j                  |	«      «      ‚d x}x}}y )Nr;   r<   r\   Tr=   Úchat©úis not©z%(py0)s is not %(py3)sÚ
assignment©rC   Úpy3úassert %(py5)sÚpy5)Ú	task_kindr/   Úsuccessr?   )z/%(py2)s
{%(py2)s = %(py0)s.results
} == %(py5)s©rC   rD   r‹   úassert %(py7)srF   )r   rI   r   Úrecord_resultr#   rK   rL   rM   rN   rO   rP   rQ   rR   Úresults)
rS   rA   r‡   Ú@py_assert2rT   Ú@py_format4Ú@py_format6Ú@py_assert4rU   rX   s
             r)   Útest_record_result_appendsz-TestRoleAssignment.test_record_result_appendsŽ   sf  € Ü#Ó%ˆØ�‰�Xœx¨¨\À4ÔHÔIØ×Ñ˜H f¨l¸DÔAà—Y‘Y˜xÓ(ˆ
Ø!%Ð%ˆz Ð%×%×%Õ%ˆz ×%×%×%×%×%Ñ%ˆz×%×%Ó%ˆz×%×%Ô% ×%×%×%×%×%×%Ñ%Ø×!Ñ!ð 	
Ø ¨lÀtÑLð&
ð 	
Ð!ð &
ñ 
÷ 	
ïé ó	
Ð!ð &
÷ 	
ò 	
ç	�6÷	
ò 	
ïé ð ÷ 	
ñ 	
ç 	�	ð ÷ 	
ò 	
ç 	�	ð "÷ 	
ð 	
ç 	�	ð&
÷ 	
÷ 	
÷ 	
ñ 	
ïé ÷	
÷ 	
ð 	
r+   c           	     óö   — t        «       }t        ddd¬«      }|j                  d|t        ddd¬«      g«       t        j                  t
        «      5  |j                  dd¬«       d	d	d	«       y	# 1 sw Y   y	xY w)
zCA rejected backup must raise, never silently return the main model.r<   r\   Tr=   r;   ÚpaidFr^   N)r   r   rI   rw   rx   r   rk   )rS   rA   rc   s      r)   Ú,test_refusal_does_not_return_the_paid_backupz?TestRoleAssignment.test_refusal_does_not_return_the_paid_backup™   sm   € ä#Ó%ˆÜ˜˜\°4Ô8ˆØ�‰�X˜t¤h¨s°FÀEÔ&JÐ%KÔLä�]‰]Ô+Ó,ñ 	BØ×!Ñ! (¸5Ð!ÔA÷	B÷ 	Bñ 	Bús   ÁA/Á/A8N©ÚreturnÚNone)Ú__name__Ú
__module__Ú__qualname__rZ   rp   rt   rz   r~   r�   r–   r™   © r+   r)   r9   r9   ^   s0   „ óAóLóOó	Bó	Bó:ó	
ôBr+   r9   c                  ól   — e Zd Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Z	dd„Z
dd	„Zdd
„Zdd„Zdd„Zy)ÚTestRouterFreeOnlyc           	     ó„  — t        t        «       t        «       «      \  }}|j                  }d} ||¬«      }|j                  }d}||k(  }|sét        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }	dd	|	iz  }
t        t        j                  |
«      «      ‚d x}x}x}x}x}}y )
NT©Ú	free_onlyúfree-ar?   )zt%(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.route
}(free_only=%(py4)s)
}.model_id
} == %(py11)sÚrouter©rC   rD   rE   re   rf   Úpy11úassert %(py13)sÚpy13©r*   r3   r7   Úrouter/   rK   rL   rM   rN   rO   rP   rQ   rR   )rS   Ú_r§   rT   rU   rW   rl   Ú@py_assert10rm   Ú@py_format12Ú@py_format14s              r)   Ú'test_route_free_only_returns_free_modelz:TestRouterFreeOnly.test_route_free_only_returns_free_model©   sÆ   € Üœe›g¤u£wÓ/‰	ˆˆ6à�|‰|Ð@ dÐ@‰| dÔ+Ð@Ð+×4Ñ4Ð@¸Ð@Ð4¸Ñ@×@×@Õ@Ð4¸×@×@×@×@×@Ñ@ˆv×@×@Ó@ˆv×@×@Ô@ˆ|×@×@Ò@ d×@×@Ò@Ð+×@×@Ò@Ð4×@×@Ò@¸×@×@×@×@×@×@×@Ò@r+   c                ó°   — t        t        «       «      \  }}t        j                  t        «      5  |j                  d¬«       d d d «       y # 1 sw Y   y xY w)NTr¤   )r*   r7   rw   rx   r   r­   ©rS   r®   r§   s      r)   Ú'test_route_free_only_never_returns_paidz:TestRouterFreeOnly.test_route_free_only_never_returns_paid®   sB   € Üœe›gÓ&‰	ˆˆ6ä�]‰]Ô+Ó,ñ 	)Ø�L‰L 4ˆLÔ(÷	)÷ 	)ñ 	)ús   °AÁAc                óö   — t        ddt        j                  t        j                  ¬«      }t        |«      \  }}t        j                  t        «      5  |j                  d¬«       d d d «       y # 1 sw Y   y xY w)NÚmysteryÚollamar.   Tr¤   )
r   r   r$   r   ÚUNKNOWNr*   rw   rx   r   r­   )rS   Úunknownr®   r§   s       r)   Ú0test_route_free_only_ignores_unknown_free_statuszCTestRouterFreeOnly.test_route_free_only_ignores_unknown_free_status´   sd   € ÜØØÜ×%Ñ%Ü'×/Ñ/ô	
ˆô ˜gÓ&‰	ˆˆ6ä�]‰]Ô+Ó,ñ 	)Ø�L‰L 4ˆLÔ(÷	)÷ 	)ñ 	)ús   ÁA/Á/A8c                óR  — t        t        «       t        «       «      \  }}|j                  } |«       }|j                  }ddh}||v }|sÕt        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }	t        t        j                  |	«      «      ‚d x}x}x}x}}y )	Nr¦   úpaid-b©Úin)zb%(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.route
}()
}.model_id
} in %(py9)sr§   ©rC   rD   rE   re   rH   úassert %(py11)sr©   r¬   )
rS   r®   r§   rT   rU   rW   Ú@py_assert8rl   rY   r°   s
             r)   Ú)test_route_without_free_only_may_use_paidz<TestRouterFreeOnly.test_route_without_free_only_may_use_paidÀ   s¹   € Üœe›g¤u£wÓ/‰	ˆˆ6à�|‰|Ð>‰|‹~Ð>ˆ~×&Ñ&Ð>¨8°XÐ*>Ð>Ð&Ð*>Ð>×>×>Õ>Ð&Ð*>×>×>×>×>×>Ñ>ˆv×>×>Ó>ˆv×>×>Ô>ˆ|×>×>Ò>ˆ~×>×>Ò>Ð&×>×>Ò>Ð*>×>×>×>×>×>×>×>Ð>r+   c                ó  — t        t        «       t        «       «      \  }}	 |j                  dd¬«      }|j
                  }d}||k7  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd	|iz  }t        t        j                  |«      «      ‚d x}x}}y # t        $ r Y y w xY w)
Nr½   T©r/   r¥   ©ú!=)z0%(py2)s
{%(py2)s = %(py0)s.model_id
} != %(py5)sÚresultrŽ   r�   rF   )r*   r3   r7   r­   r   r/   rK   rL   rM   rN   rO   rP   rQ   rR   )	rS   r®   r§   rÈ   rT   r•   rU   r”   rX   s	            r)   Ú8test_route_specific_paid_model_with_free_only_is_refusedzKTestRouterFreeOnly.test_route_specific_paid_model_with_free_only_is_refusedÅ   s°   € Üœe›g¤u£wÓ/‰	ˆˆ6ð	Ø—\‘\¨8¸t�\ÓDˆFð �‰Ð* (Ð*ˆ (Ñ*×*×*Õ*ˆ (×*×*×*×*×*Ñ*ˆv×*×*Ó*ˆv×*×*Ô*ˆ×*×*Ò* (×*×*×*×*×*×*Ô*øô  ò 	Ùð	ús   ¡C= Ã=	D	ÄD	c                óò  — t        t        «       t        «       «      \  }}|j                  dd¬«      }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }d	d
|iz  }t        t        j                  |«      «      ‚dx}x}}d}	|j                  }|	|v }
|
sÐt        j                  d|
fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }t        j                  d|j                  ›�«      dz   d
|iz  }t        t        j                  |«      «      ‚dx}	x}
}d}	|j                  }|j                  } |«       }|	|v }
|
søt        j                  d|
fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      dœz  }t        j                  d|j                  ›�«      dz   d|iz  }t        t        j                  |«      «      ‚dx}	x}
x}x}}d}	|j                  }|	|v }
|
sÐt        j                  d|
fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }t        j                  d|j                  ›�«      dz   d
|iz  }t        t        j                  |«      «      ‚dx}	x}
}y)uÞ  Substituce musÃ­ bÃ½t vyznaÄ�ena, ne schovÃ¡na v generickÃ©m `reason`.

        ProÄ� tento test existuje vedle
        `test_route_specific_paid_model_with_free_only_is_refused`: ten kontroluje
        jen `model_id != "paid-b"`, takÅ¾e projdou i pÅ™i tichÃ©m pÅ™esmÄ›rovÃ¡nÃ­ â€”
        volajÃ­cÃ­ by dostal jinÃ½ model a `reason` by znÄ›l `cost optimized`,
        tedy jako by dostal to, co Å¾Ã¡dal. Tento test padÃ¡, kdyÅ¾ se substituce
        pÅ™estane hlÃ¡sit.
        r½   TrÅ   r¦   r?   ©z0%(py2)s
{%(py2)s = %(py0)s.model_id
} == %(py5)srÈ   rŽ   r�   rF   Nr¾   )z.%(py1)s in %(py5)s
{%(py5)s = %(py3)s.reason
}©Úpy1r‰   r‹   u-   reason neuvÃ¡dÃ­, kterÃ½ model byl Å¾Ã¡dÃ¡n: z
>assert %(py7)sÚ	substitut)z`%(py1)s in %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.reason
}.lower
}()
}©rÍ   r‰   r‹   rF   rH   u+   reason neuvÃ¡dÃ­, Å¾e doÅ¡lo k substituci: ú
>assert %(py11)sr©   u&   reason neuvÃ¡dÃ­, Ä�Ã­m byl nahrazen: )r*   r3   r7   r­   r/   rK   rL   rM   rN   rO   rP   rQ   rR   ÚreasonÚ_format_assertmsgÚlower)rS   r®   r§   rÈ   rT   r•   rU   r”   rX   Ú@py_assert0r’   rV   rÂ   rY   r°   s                  r)   Ú2test_free_only_substitution_is_disclosed_in_reasonzETestRouterFreeOnly.test_free_only_substitution_is_disclosed_in_reasonÎ   sŽ  € ô œe›g¤u£wÓ/‰	ˆˆ6à—‘ x¸4�Ó@ˆà�‰Ð* (Ð*ˆ (Ñ*×*×*Õ*ˆ (×*×*×*×*×*Ñ*ˆv×*×*Ó*ˆv×*×*Ô*ˆ×*×*Ò* (×*×*×*×*×*×*Ó*Øð 	O˜6Ÿ=™=ð 	Oˆx˜=Ð(÷ 	Oß=NÑ=Nó	Oˆx˜=÷ 	Oñ 	OßENÁYð ÷ 	Oñ 	OßHNÉ÷	Oò 	Oß6NÑ6Nð "÷ 	Oñ 	OßENÁYð "÷ 	Oò 	OßENÁYð )÷ 	Oõ 	Oß=NÑ=NÐ;¸F¿M¹MÐ;LÐM÷	O÷ 	Oö 	Oß;NÑ;N÷	O÷ 	Oàð 	M˜fŸm™mð 	M˜m×1Ñ1ð 	MÑ1Ó3ð 	Mˆ{Ð3Ð3÷ 	Mß;LÑ;Ló	Mˆ{Ð3÷ 	Mñ 	MßCLÁ9ð ÷ 	Mñ 	MßFLÁf÷	Mò 	Mß4LÑ4Lð %÷ 	Mñ 	MßCLÁ9ð %÷ 	Mò 	MßCLÁ9ð ,÷ 	Mð 	MßCLÁ9ð 2÷ 	Mð 	MßCLÁ9ð 4÷ 	Mõ 	Mß;LÑ;LÐ9¸&¿-¹-Ð9JÐK÷	M÷ 	Mö 	Mß9LÑ9L÷	M÷ 	Mó 	Màð 	H˜6Ÿ=™=ð 	Hˆx˜=Ð(÷ 	Hß6GÑ6Gó	Hˆx˜=÷ 	Hñ 	Hß>G¹ið ÷ 	Hñ 	HßAGÁ÷	Hò 	Hß/GÑ/Gð "÷ 	Hñ 	Hß>G¹ið "÷ 	Hò 	Hß>G¹ið )÷ 	Hõ 	Hß6GÑ6GÐ4°V·]±]Ð4EÐF÷	H÷ 	Hö 	Hß4GÑ4G÷	H÷ 	Hð 	Hr+   c                óJ  — t        t        «       t        «       «      \  }}|j                  dd¬«      }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd	|iz  }t        t        j                  |«      «      ‚d
x}x}}d}	|j                  }|j                  }
 |
«       }|	|v}|søt        j                  d|fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |
«      t        j                  |«      dœz  }t        j                  d|j                  ›�«      dz   d|iz  }t        t        j                  |«      «      ‚d
x}	x}x}x}
}y
)u<   `reason` nesmÃ­ tvrdit substituci, kdyÅ¾ Å¾Ã¡dnÃ¡ nenastala.r¦   TrÅ   r?   rË   rÈ   rŽ   r�   rF   NrÎ   ©únot in©zd%(py1)s not in %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.reason
}.lower
}()
}rÏ   õ&   reason tvrdÃ­ substituci bez dÅ¯vodu: rÐ   r©   ©r*   r3   r7   r­   r/   rK   rL   rM   rN   rO   rP   rQ   rR   rÑ   rÓ   rÒ   ©rS   r®   r§   rÈ   rT   r•   rU   r”   rX   rÔ   rV   rÂ   r’   rY   r°   s                  r)   Ú<test_no_substitution_reason_when_requested_model_is_eligiblezOTestRouterFreeOnly.test_no_substitution_reason_when_requested_model_is_eligibleä   sÄ  € äœe›g¤u£wÓ/‰	ˆˆ6à—‘ x¸4�Ó@ˆà�‰Ð* (Ð*ˆ (Ñ*×*×*Õ*ˆ (×*×*×*×*×*Ñ*ˆv×*×*Ó*ˆv×*×*Ô*ˆ×*×*Ò* (×*×*×*×*×*×*Ó*Øð 	H &§-¡-ð 	H -×"5Ñ"5ð 	HÑ"5Ó"7ð 	Hˆ{Ð"7Ð7÷ 	Hß6GÑ6Gó	Hˆ{Ð"7÷ 	Hñ 	Hß>G¹ið ÷ 	Hñ 	HßAGÁ÷	Hò 	Hß/GÑ/Gð #)÷ 	Hñ 	Hß>G¹ið #)÷ 	Hò 	Hß>G¹ið #0÷ 	Hð 	Hß>G¹ið #6÷ 	Hð 	Hß>G¹ið #8÷ 	Hõ 	Hß6GÑ6GÐ4°V·]±]Ð4EÐF÷	H÷ 	Hö 	Hß4GÑ4G÷	H÷ 	Hô 	Hr+   c                óJ  — t        t        «       t        «       «      \  }}|j                  dd¬«      }|j                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd	|iz  }t        t        j                  |«      «      ‚d
x}x}}d}	|j                  }|j                  }
 |
«       }|	|v}|søt        j                  d|fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |
«      t        j                  |«      dœz  }t        j                  d|j                  ›�«      dz   d|iz  }t        t        j                  |«      «      ‚d
x}	x}x}x}
}y
)uD   Bez `free_only` je Å¾Ã¡danÃ½ model pouÅ¾it, takÅ¾e nenÃ­ co hlÃ¡sit.r½   FrÅ   r?   rË   rÈ   rŽ   r�   rF   NrÎ   r×   rÙ   rÏ   rÚ   rÐ   r©   rÛ   rÜ   s                  r)   Ú-test_no_substitution_reason_without_free_onlyz@TestRouterFreeOnly.test_no_substitution_reason_without_free_onlyî   sÄ  € äœe›g¤u£wÓ/‰	ˆˆ6à—‘ x¸5�ÓAˆà�‰Ð* (Ð*ˆ (Ñ*×*×*Õ*ˆ (×*×*×*×*×*Ñ*ˆv×*×*Ó*ˆv×*×*Ô*ˆ×*×*Ò* (×*×*×*×*×*×*Ó*Øð 	H &§-¡-ð 	H -×"5Ñ"5ð 	HÑ"5Ó"7ð 	Hˆ{Ð"7Ð7÷ 	Hß6GÑ6Gó	Hˆ{Ð"7÷ 	Hñ 	Hß>G¹ið ÷ 	Hñ 	HßAGÁ÷	Hò 	Hß/GÑ/Gð #)÷ 	Hñ 	Hß>G¹ið #)÷ 	Hò 	Hß>G¹ið #0÷ 	Hð 	Hß>G¹ið #6÷ 	Hð 	Hß>G¹ið #8÷ 	Hõ 	Hß6GÑ6GÐ4°V·]±]Ð4EÐF÷	H÷ 	Hö 	Hß4GÑ4G÷	H÷ 	Hô 	Hr+   c                ó”  — t        t        «       t        «       «      \  }}|j                  dd¬«      }|sedddt	        j
                  «       v st        j                  |«      rt        j                  |«      ndiz  }t        t        j                  |«      «      ‚d„ |D «       }t        |«      }|s•dd	t	        j
                  «       v st        j                  t        «      rt        j                  t        «      nd	t        j                  |«      t        j                  |«      d
œz  }t        t        j                  |«      «      ‚d x}}y )NÚ__missing__TrÅ   úassert %(py0)srC   Úroutesc              3  ó:   K  — | ]  }|j                   d k(  –— Œ y­w)r¦   N)r/   )Ú.0Úrs     r)   ú	<genexpr>zFTestRouterFreeOnly.test_fallback_respects_free_only.<locals>.<genexpr>þ   s   è ø€ Ò:¨a�1—:‘: Õ)Ñ:ùs   ‚ú,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}Úall©rC   rD   rE   )r*   r3   r7   Úroute_with_fallbackrM   rN   rK   rO   rP   rQ   rR   ré   )rS   r®   r§   rã   Ú@py_format1rT   rU   Ú@py_format5s           r)   Ú test_fallback_respects_free_onlyz3TestRouterFreeOnly.test_fallback_respects_free_onlyø   s«   € Üœe›g¤u£wÓ/‰	ˆˆ6à×+Ñ+°]ÈdÐ+ÓSˆá����Žˆv��‹ˆv�����Ù:°6Ô:Ð:ŒsÐ:Ó:Ð:Ñ:×:×:×:×:Õ:Œs×:×:Ó:Œs×:×:Ô:Ð:×:×:Ò:Ð:×:×:×:×:×:Ó:r+   c                ó²   — t        t        «       «      \  }}t        j                  t        «      5  |j                  dd¬«       d d d «       y # 1 sw Y   y xY w)Nrá   TrÅ   )r*   r7   rw   rx   r   rë   r´   s      r)   Ú1test_fallback_raises_when_no_free_model_availablezDTestRouterFreeOnly.test_fallback_raises_when_no_free_model_available   sK   € Üœe›gÓ&‰	ˆˆ6ä�]‰]Ô+Ó,ñ 	OØ×&Ñ&°ÈÐ&ÔN÷	O÷ 	Oñ 	Oús   °AÁAc                ó<  — t        j                  t        j                  «      j                  }t        j                  t        j
                  «      j                  }|d   }|j                  }d}||u }|s€t        j                  d|fd||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}|d   }|j                  }d}||u }|s€t        j                  d|fd||f«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}y )Nr¥   Fr`   )z/%(py3)s
{%(py3)s = %(py1)s.default
} is %(py6)s)rÍ   r‰   re   úassert %(py8)srf   )ÚinspectÚ	signaturer   r­   Ú
parametersrë   ÚdefaultrK   rL   rP   rQ   rR   )	rS   ÚparamsÚfallback_paramsrÔ   r’   rW   r•   Ú@py_format7Ú@py_format9s	            r)   Ú test_free_only_defaults_to_falsez3TestRouterFreeOnly.test_free_only_defaults_to_false  s  € Ü×"Ñ"¤;×#4Ñ#4Ó5×@Ñ@ˆÜ!×+Ñ+¬K×,KÑ,KÓL×WÑWˆà�kÑ"Ð3Ð"×*Ñ*Ð3¨eÐ3Ð*¨eÐ3×3×3Õ3Ð*¨e×3×3Ó3Ð"×3×3Ò3Ð*×3×3Ò3¨e×3×3×3×3×3×3Õ3Ø˜{Ñ+Ð<Ð+×3Ñ3Ð<°uÐ<Ð3°uÐ<×<×<Õ<Ð3°u×<×<Ó<Ð+×<×<Ò<Ð3×<×<Ò<°u×<×<×<×<×<×<Ö<r+   c                ó^	  — t        t        «       t        «       ¬«      }|j                  }t	        «       } ||«      }d}||u }|�st        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd	|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}|j                  }t        «       } ||«      }d
}||u }|�st        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd	|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}|j                  }d}d}t        j                  }t!        |||¬«      }	 ||	«      }
d}|
|u }|�s£t        j                  d|fd|
|f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  t         «      rt        j                  t         «      ndt        j                  |«      t        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |	«      t        j                  |
«      t        j                  |«      dœ
z  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}x}	x}
x}}y )Nr   Fr`   )zo%(py7)s
{%(py7)s = %(py2)s
{%(py2)s = %(py0)s._is_free_eligible
}(%(py5)s
{%(py5)s = %(py3)s()
})
} is %(py10)sr§   r7   )rC   rD   r‰   r‹   rF   rg   rh   ri   Tr3   r·   r¸   )r/   r   r0   )zÉ%(py14)s
{%(py14)s = %(py2)s
{%(py2)s = %(py0)s._is_free_eligible
}(%(py12)s
{%(py12)s = %(py3)s(model_id=%(py5)s, provider=%(py7)s, free_status=%(py10)s
{%(py10)s = %(py8)s.UNKNOWN
})
})
} is %(py17)sr   r   )
rC   rD   r‰   r‹   rF   rf   rg   ri   Úpy14Úpy17úassert %(py19)sÚpy19)r   r   r   Ú_is_free_eligibler7   rK   rL   rM   rN   rO   rP   rQ   rR   r3   r   r¹   r   )rS   r§   rT   r•   rV   rm   rÂ   rn   ro   Ú@py_assert11Ú@py_assert13Ú@py_assert16Ú@py_assert15Ú@py_format18Ú@py_format20s                  r)   Ú+test_free_eligible_rejects_paid_and_unknownz>TestRouterFreeOnly.test_free_eligible_rejects_paid_and_unknown  sŒ  € Ü¬M«OÔO_ÓOaÔbˆà×'Ñ'Ð9¬«Ð9Ñ'¨Ó0Ð9°EÐ9Ð0°EÐ9×9×9Ö9Ð0°E×9×9×9×9×9Ñ9ˆv×9×9Ó9ˆv×9×9Ô9Ð'×9×9×9×9×9Ð9¬×9×9Ó9¬×9×9Ô9¨×9×9Ò9Ð0×9×9Ò9°E×9×9×9×9×9×9×9Ø×'Ñ'Ð8¬«Ð8Ñ'¨Ó0Ð8°DÐ8Ð0°DÐ8×8×8Ö8Ð0°D×8×8×8×8×8Ñ8ˆv×8×8Ó8ˆv×8×8Ô8Ð'×8×8×8×8×8Ð8¬×8×8Ó8¬×8×8Ô8¨×8×8Ò8Ð0×8×8Ò8°D×8×8×8×8×8×8×8à×$Ñ$ð		
ð 'ð		
ð &ð			
ô
 !0× 7Ñ 7ð		
äØ&Ø%Ø 7ôð		
Ù$ðóð		
ð ð		
ðð ð÷		
ð 		
ïé ó		
ðð ÷		
ò 		
÷ 
�6÷		
ò 		
ïé ð ÷		
ñ 		
÷ 
�	ð ÷		
ò 		
÷ 
�	ð %÷		
ñ 		
÷ 
�6÷		
ò 		
ïé ô ÷		
ñ 		
÷ 
�	ô ÷		
ò 		
÷ 
�	ð '÷		
ð 		
÷ 
�	ð &÷			
ñ 		
÷ 
�6÷		
ò 		
ïé ô	 !0÷		
ñ 		
÷ 
�	ô	 !0÷		
ò 		
÷ 
�	ð	 !8÷		
ð 		
÷ 
�	ð÷		
ð 		
÷ 
�	ð÷		
ð 		
÷ 
�	ð ÷		
÷ 		
÷ 		
ñ 		
ïé ÷		
÷ 		
÷ 		
ò 		
r+   Nrš   )r�   rž   rŸ   r²   rµ   r»   rÃ   rÉ   rÕ   rÝ   rß   rî   rð   rû   r  r    r+   r)   r¢   r¢   ¨   sC   „ óAó
)ó
)ó?ó
+óHó,HóHó;óOó=ô
r+   r¢   c                  óD   — e Zd Zd	d„Zd	d„Zd	d„Zd	d„Zd	d„Zd	d„Zd	d„Z	y)
ÚTestGatewayFreeOnlyc                óâ  — t        «       }|j                  }d}||u }|sÉt        j                  d|fd||f«      dt	        j
                  «       v st        j                  t         «      rt        j                  t         «      ndt        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}y )NTr`   )zH%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s()
}.free_only
} is %(py7)sr   rB   rG   rH   )
r   r¥   rK   rL   rM   rN   rO   rP   rQ   rR   )rS   rT   rU   rV   rW   rX   rY   s          r)   Ú"test_gateway_defaults_to_free_onlyz6TestGatewayFreeOnly.test_gateway_defaults_to_free_only$  s‹   € Ü!Ó#Ð5Ð#×-Ñ-Ð5°Ð5Ð-°Ð5×5×5Õ5Ð-°×5×5×5×5×5Ñ5Ô!×5×5Ó5Ô!×5×5Ô5Ð#×5×5Ò5Ð-×5×5Ò5°×5×5×5×5×5×5Ö5r+   c                ór  — t        «       }|j                  t        ddt        j                  t
        j                  ¬«      «       t        |j                  j                  «       «      D ]?  }|j                  rŒ|j                  j                  |j                  |j                  «       ŒA |j                  «       d   }d}||k7  }|slt        j                   d|fd||f«      t        j"                  |«      t        j"                  |«      dœz  }dd	|iz  }t%        t        j&                  |«      «      ‚d x}x}}y )
Nz	paid-onlyr¸   r.   r/   rÆ   )z%(py1)s != %(py4)s©rÍ   rE   úassert %(py6)sre   )r   Úregister_modelr   r   r$   r   r6   Úlistr    Úlist_activer>   Ú
unregisterr/   r   r­   rK   rL   rP   rQ   rR   )rS   ÚgatewayÚmodelrÔ   rU   r’   rí   rù   s           r)   Ú0test_gateway_route_never_returns_paid_by_defaultzDTestGatewayFreeOnly.test_gateway_route_never_returns_paid_by_default'  sÝ   € Ü“.ˆØ×ÑÜØ$Ø!Ü"×)Ñ)Ü+×0Ñ0ô	ô	
ô ˜'×0Ñ0×<Ñ<Ó>Ó?ò 	RˆEØ—=“=Ø×&Ñ&×1Ñ1°%·.±.À%Ç.Á.ÕQð	Rð �}‰}‹˜zÑ*Ð9¨kÐ9Ð*¨kÑ9×9×9Õ9Ð*¨k×9×9Ó9Ð*×9×9Ò9¨k×9×9×9×9×9×9Ô9r+   c                ó~  — t        «       }t        |j                  j                  «       «      D ]2  }|j                  j	                  |j
                  |j                  «       Œ4 |j                  t        dd«      «       t        j                  t        «      5  |j                  d¬«       d d d «       y # 1 sw Y   y xY w)Núgateway-paidr¸   Tr¤   )r   r  r    r  r  r/   r   r  r7   rw   rx   r   r­   ©rS   r  r  s      r)   Ú.test_gateway_route_refuses_paid_when_free_onlyzBTestGatewayFreeOnly.test_gateway_route_refuses_paid_when_free_only7  s‘   € Ü“.ˆÜ˜'×0Ñ0×<Ñ<Ó>Ó?ò 	NˆEØ×"Ñ"×-Ñ-¨e¯n©n¸e¿n¹nÕMð	Nà×Ñœu ^°XÓ>Ô?ä�]‰]Ô+Ó,ñ 	*Ø�M‰M DˆMÔ)÷	*÷ 	*ñ 	*ús   ÂB3Â3B<c                ó€  — t        «       }t        |j                  j                  «       «      D ]2  }|j                  j	                  |j
                  |j                  «       Œ4 |j                  t        dd«      «       t        j                  t        «      5  |j                  dd¬«       d d d «       y # 1 sw Y   y xY w)Nr  r¸   rá   TrÅ   )r   r  r    r  r  r/   r   r  r7   rw   rx   r   rë   r  s      r)   Ú;test_gateway_route_with_fallback_refuses_paid_only_registryzOTestGatewayFreeOnly.test_gateway_route_with_fallback_refuses_paid_only_registry@  sš   € Ü“.ˆÜ˜'×0Ñ0×<Ñ<Ó>Ó?ò 	NˆEØ×"Ñ"×-Ñ-¨e¯n©n¸e¿n¹nÕMð	Nà×Ñœu ^°XÓ>Ô?ä�]‰]Ô+Ó,ñ 	PØ×'Ñ'°È$Ð'ÔO÷	P÷ 	Pñ 	Pús   ÂB4Â4B=c                ó  — t        «       }|j                  d¬«      }|sedddt        j                  «       v st	        j
                  |«      rt	        j                  |«      ndiz  }t        t	        j                  |«      «      ‚|D �]€  }|j                  j                  |d   «      }g }d }||u }|}	|s|j                  }
|
}	|	�s8t	        j                  d|fd||f«      d	t        j                  «       v st	        j
                  |«      rt	        j                  |«      nd	t	        j                  |«      d
œz  }dd|iz  }|j                  |«       |sldd	t        j                  «       v st	        j
                  |«      rt	        j                  |«      nd	t	        j                  
«      dœz  }|j                  |«       t	        j                  |d«      i z  }dd|iz  }t        t	        j                  |«      «      ‚d x}	x}x}x}}
�Œƒ y )NTr¤   râ   rC   rã   r/   r`   )z%(py2)s is %(py5)sr(   )rD   r‹   z%(py7)srF   z&%(py11)s
{%(py11)s = %(py9)s.is_free
})rH   r©   é   úassert %(py14)srý   )r   rë   rM   rN   rK   rO   rP   rQ   rR   r    r#   r>   rL   ÚappendÚ_format_boolop)rS   r  rã   rì   Úentryr(   rT   r•   rU   rÔ   r¯   r”   rX   r°   ro   Ú@py_format15s                   r)   Ú2test_gateway_route_with_fallback_accepts_free_onlyzFTestGatewayFreeOnly.test_gateway_route_with_fallback_accepts_free_onlyI  s  € Ü“.ˆà×,Ñ,°tÐ,Ó<ˆá����Žˆv��‹ˆv�����Øó 	4ˆEØ×+Ñ+×/Ñ/°°jÑ0AÓBˆFÙ3˜TÐ3�6˜T�>Ô3 V§^¡^Ð3 ^×3×3Ö3�6˜T×3×3×3×3×3Ñ3�6×3×3Ó3�6×3×3Ô3˜T×3×3×3×3×3×3×3×3×3Ð3 V×3×3Ó3 V×3×3Ô3 ^×3×3×3×3×3×3×3×3×3×3×3×3Ó3ñ	4r+   c                óâ  — t        t        «       t        «       «      \  }}|j                  d d d«      }|j                  d d d«      }|D �cg c]  }|j                  ‘Œ }}dg}||k(  }|slt        j                  d|fd||f«      t        j                  |«      t        j                  |«      dœz  }	dd|	iz  }
t        t        j                  |
«      «      ‚d x}x}}t        |«      }d	}||k(  }|söt        j                  d|fd
||f«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }
dd|
iz  }t        t        j                  |«      «      ‚d x}x}}y c c}w ©NTFr¦   r?   ©z%(py1)s == %(py4)sr  r  re   é   ©z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sÚlenÚ
everything©rC   rÍ   r‰   re   rò   rf   )r*   r3   r7   Ú_get_candidatesr/   rK   rL   rP   rQ   rR   r*  rM   rN   rO   ©rS   r®   r§   Úfreer+  ÚmrÔ   rU   r’   rí   rù   rW   r•   rú   s                 r)   Ú test_candidate_filter_drops_paidz4TestGatewayFreeOnly.test_candidate_filter_drops_paidS  s0  € Üœe›g¤u£wÓ/‰	ˆˆ6à×%Ñ% d¨D°$Ó7ˆØ×+Ñ+¨D°$¸Ó>ˆ
à$(Ö)˜q�—
“
Ð)Ð7Ð)¨h¨ZÐ7Ð)¨ZÑ7×7×7Õ7Ð)¨Z×7×7Ó7Ð)×7×7Ò7¨Z×7×7×7×7×7×7Ó7Ü�:‹Ð# !Ð#ˆ !Ñ#×#×#Õ#ˆ !×#×#×#×#×#Ñ#Œs×#×#Ó#Œs×#×#×#×#×#Ò#�:×#×#Ó#�:×#×#Ô#ˆ×#×#Ò# !×#×#×#×#×#×#Ô#ùò *s   Á
G,c                óÞ  — t        t        «       t        «       «      \  }}|j                  d d«      }|j                  d d«      }|D �cg c]  }|j                  ‘Œ }}dg}||k(  }|slt        j                  d|fd||f«      t        j                  |«      t        j                  |«      dœz  }	dd|	iz  }
t        t        j                  |
«      «      ‚d x}x}}t        |«      }d	}||k(  }|söt        j                  d|fd
||f«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }
dd|
iz  }t        t        j                  |«      «      ‚d x}x}}y c c}w r&  )r*   r3   r7   Ú_get_fallback_candidatesr/   rK   rL   rP   rQ   rR   r*  rM   rN   rO   r.  s                 r)   Ú)test_fallback_candidate_filter_drops_paidz=TestGatewayFreeOnly.test_fallback_candidate_filter_drops_paid\  s,  € Üœe›g¤u£wÓ/‰	ˆˆ6à×.Ñ.¨t°TÓ:ˆØ×4Ñ4°T¸5ÓAˆ
à$(Ö)˜q�—
“
Ð)Ð7Ð)¨h¨ZÐ7Ð)¨ZÑ7×7×7Õ7Ð)¨Z×7×7Ó7Ð)×7×7Ò7¨Z×7×7×7×7×7×7Ó7Ü�:‹Ð# !Ð#ˆ !Ñ#×#×#Õ#ˆ !×#×#×#×#×#Ñ#Œs×#×#Ó#Œs×#×#×#×#×#Ò#�:×#×#Ó#�:×#×#Ô#ˆ×#×#Ò# !×#×#×#×#×#×#Ô#ùò *s   ÁG*Nrš   )
r�   rž   rŸ   r  r  r  r  r$  r1  r4  r    r+   r)   r
  r
  #  s&   „ ó6ó:ó *óPó4ó$ô$r+   r
  c                  ól   — e Zd Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„Z	dd„Z
dd	„Zdd
„Zdd„Zdd„Zy)ÚTestKiloConfigBuilderc                ó†  — t        t        «       t        «       «      \  }}t        |«      }|j	                  «       }|d   d   d   }dg}||k(  }|slt        j                  d|fd||f«      t        j                  |«      t        j                  |«      dœz  }dd	|iz  }	t        t        j                  |	«      «      ‚d x}x}}y )
Nr   Úcb26Ú	whitelistr¦   r?   r'  r  r  re   )
r*   r3   r7   r	   Úbuild_kilo_provider_configrK   rL   rP   rQ   rR   )
rS   r&   r®   ÚbuilderÚconfigrÔ   rU   r’   rí   rù   s
             r)   Ú.test_build_whitelist_contains_only_free_modelszDTestKiloConfigBuilder.test_build_whitelist_contains_only_free_modelsl  sŒ   € Ü¤£¬«Ó1‰ˆ�!Ü# HÓ-ˆà×3Ñ3Ó5ˆà�jÑ! &Ñ)¨+Ñ6ÐD¸8¸*ÐDÐ6¸*ÑD×D×DÕDÐ6¸*×D×DÓDÐ6×D×DÒD¸*×D×D×D×D×D×DÔDr+   c                ó¾   — t        t        «       «      \  }}t        j                  t        «      5  t        |«      j                  «        d d d «       y # 1 sw Y   y xY w)N)r*   r7   rw   rx   r
   r	   r:  )rS   r&   r®   s      r)   Ú$test_build_raises_without_free_modelz:TestKiloConfigBuilder.test_build_raises_without_free_modelt  sI   € Ü¤£Ó(‰ˆ�!ä�]‰]Ô/Ó0ñ 	EÜ˜hÓ'×BÑBÔD÷	E÷ 	Eñ 	Eús   °AÁAc                ó¾  — t        t        «       t        «       «      \  }}t        |«      }dddi idgdœii}|j	                  |«      }|sedddt        j                  «       v st        j                  |«      rt        j                  |«      ndiz  }t        t        j                  |«      «      ‚d„ |D «       }t        |«      }|s•d	d
t        j                  «       v st        j                  t        «      rt        j                  t        «      nd
t        j                  |«      t        j                  |«      dœz  }	t        t        j                  |	«      «      ‚d x}}y )Nr   r8  r½   ©Úmodelsr9  râ   rC   Úproblemsc              3  ó$   K  — | ]  }d |v –— Œ
 y­w)r½   Nr    ©rå   r<   s     r)   rç   zGTestKiloConfigBuilder.test_validate_flags_paid_model.<locals>.<genexpr>„  s   è ø€ Ò3 Q�8˜q”=Ñ3ùó   ‚rè   Úanyrê   )r*   r3   r7   r	   Úvalidate_kilo_provider_configrM   rN   rK   rO   rP   rQ   rR   rG  )
rS   r&   r®   r;  r<  rC  rì   rT   rU   rí   s
             r)   Útest_validate_flags_paid_modelz4TestKiloConfigBuilder.test_validate_flags_paid_modelz  sÎ   € Ü¤£¬«Ó1‰ˆ�!Ü# HÓ-ˆà˜¨X°r¨NÈ(ÈÑ!TÐUð
ˆð ×8Ñ8¸Ó@ˆá����Žˆx��‹ˆx�����Ù3¨(Ô3Ð3ŒsÐ3Ó3Ð3Ñ3×3×3×3×3Õ3Œs×3×3Ó3Œs×3×3Ô3Ð3×3×3Ò3Ð3×3×3×3×3×3Ó3r+   c                óØ  — t        t        «       «      \  }}dddi ig dœii}t        |«      j                  |«      }d„ |D «       }t	        |«      }|s•ddt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |«      dœz  }t        t        j                  |«      «      ‚d x}}y )	Nr   r8  ÚghostrA  c              3  ó$   K  — | ]  }d |v –— Œ
 y­w)rK  Nr    rE  s     r)   rç   zJTestKiloConfigBuilder.test_validate_flags_unknown_model.<locals>.<genexpr>Œ  s   è ø€ Ò2 A�7˜a”<Ñ2ùrF  rè   rG  rê   )r*   r3   r	   rH  rG  rM   rN   rK   rO   rP   rQ   rR   )rS   r&   r®   r<  rC  rT   rU   rí   s           r)   Ú!test_validate_flags_unknown_modelz7TestKiloConfigBuilder.test_validate_flags_unknown_model†  sž   € Ü¤£Ó(‰ˆ�!Ø˜v°7¸B°-ÈbÑ'QÐRÐSˆä$ XÓ.×LÑLÈVÓTˆá2¨Ô2Ð2ŒsÐ2Ó2Ð2Ñ2×2×2×2×2Õ2Œs×2×2Ó2Œs×2×2Ô2Ð2×2×2Ò2Ð2×2×2×2×2×2Ó2r+   c                óÈ  — t        t        «       t        «       «      \  }}t        |«      }|j	                  «       }|j
                  } ||«      }g }||k(  }|�st        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }	dd|	iz  }
t        t        j                  |
«      «      ‚d x}x}x}}y )Nr?   )zc%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.validate_kilo_provider_config
}(%(py3)s)
} == %(py8)sr;  r<  )rC   rD   r‰   r‹   rf   úassert %(py10)srg   )r*   r3   r7   r	   r:  rH  rK   rL   rM   rN   rO   rP   rQ   rR   )rS   r&   r®   r;  r<  rT   r•   rl   rV   rú   rn   s              r)   Ú&test_validate_passes_clean_free_configz<TestKiloConfigBuilder.test_validate_passes_clean_free_configŽ  sÖ   € Ü¤£¬«Ó1‰ˆ�!Ü# HÓ-ˆØ×3Ñ3Ó5ˆà×4Ñ4ÐBÑ4°VÓ<ÐBÀÐBÐ<ÀÑB×B×BÖBÐ<À×B×B×B×B×BÑBˆw×B×BÓBˆw×B×BÔBÐ4×B×B×B×B×BÐB°V×B×BÓB°V×B×BÔBÐ<×B×BÒBÀ×B×B×B×B×B×BÖBr+   c                ó2  — t        t        «       «      \  }}t        |«      j                  i «      }|sedddt	        j
                  «       v st        j                  |«      rt        j                  |«      ndiz  }t        t        j                  |«      «      ‚y )Nrâ   rC   rC  )r*   r3   r	   rH  rM   rN   rK   rO   rP   rQ   rR   )rS   r&   r®   rC  rì   s        r)   Ú%test_validate_requires_provider_blockz;TestKiloConfigBuilder.test_validate_requires_provider_block•  sJ   € Ü¤£Ó(‰ˆ�!ä$ XÓ.×LÑLÈRÓPˆá����Žˆx��‹ˆx�����ˆxr+   c                ó¶  — t        t        «       t        «       «      \  }}t        |«      }|j	                  «       }|dz  }|j                  t        |«      |«      }|d   }d}	||	u }
|
slt        j                  d|
fd||	f«      t        j                  |«      t        j                  |	«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}
}	t        j                  }|j                  }d	} ||¬
«      } ||«      }||k(  }|�sst        j                  d|fd||f«      dt        j                   «       v st        j"                  t        «      rt        j                  t        «      ndt        j                  |«      dt        j                   «       v st        j"                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dt        j                   «       v st        j"                  |«      rt        j                  |«      nddœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}x}}d}||z  }	|	j$                  } |«       }| }|s¡ddt        j                   «       v st        j"                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      dœz  }t        t        j                  |«      «      ‚d x}x}	x}x}}y )Nú	kilo.jsonÚappliedTr`   ©z%(py1)s is %(py4)sr  r  re   úutf-8©Úencodingr?   )z”%(py11)s
{%(py11)s = %(py2)s
{%(py2)s = %(py0)s.loads
}(%(py9)s
{%(py9)s = %(py5)s
{%(py5)s = %(py3)s.read_text
}(encoding=%(py7)s)
})
} == %(py13)sÚjsonÚtargetr<  )rC   rD   r‰   r‹   rF   rH   r©   r«   úassert %(py15)sÚpy15zkilo.json.tmpzQassert not %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = (%(py0)s / %(py2)s).exists
}()
}Útmp_path©rC   rD   r‹   rF   )r*   r3   r7   r	   r:  Úapply_kilo_configÚstrrK   rL   rP   rQ   rR   rZ  ÚloadsÚ	read_textrM   rN   rO   Úexists)rS   r^  r&   r®   r;  r<  r[  rÈ   rÔ   rU   r’   rí   rù   rT   r•   rV   rÂ   r¯   Ú@py_assert12r±   Ú@py_format16rú   s                         r)   Ú!test_apply_writes_file_atomicallyz7TestKiloConfigBuilder.test_apply_writes_file_atomicallyœ  s  € Ü¤£¬«Ó1‰ˆ�!Ü# HÓ-ˆØ×3Ñ3Ó5ˆØ˜KÑ'ˆà×*Ñ*¬3¨v«;¸Ó?ˆà�iÑ Ð( DÐ(Ð  DÐ(×(×(Õ(Ð  D×(×(Ó(Ð ×(×(Ò( D×(×(×(×(×(×(Ó(Ü�z‰zÐG˜&×*Ñ*ÐG°GÐGÑ*°GÔ<ÐG‰zÐ<Ó=ÐGÐ=ÀÑG×G×GÖGÐ=À×G×G×G×G×GÑGŒt×G×GÓGŒt×G×GÔGˆz×G×G×G×G×GÐG˜&×G×GÓG˜&×G×GÔGÐ*×G×GÒG°G×G×GÒGÐ<×G×GÒGÐ=×G×G×G×G×GÐGÀ×G×GÓGÀ×G×G×G×G×G×G×GÓGØ.Ð8�H˜Ñ.Ð8Ð.×6Ñ6Ð8Ñ6Ó8Ð8Ð8Ð8Ð8Ñ8×8×8×8×8Õ8�H×8×8Ó8�H×8×8Ô8˜×8×8Ò8Ð6×8×8Ò8Ð8×8×8×8×8×8×8Ñ8r+   c                ó   — t        t        «       «      \  }}t        |«      }|dz  }|j                  dd¬«       di g dœih d£dœ}t	        j
                  t        «      5  |j                  t        |«      |«       d	d	d	«       |j                  }d} ||¬«      }	d}
|	|
k(  }|sÕt        j                  d
|fd|	|
f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |	«      t        j                  |
«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d	x}x}x}	x}}
y	# 1 sw Y   �Œ
xY w)zCAtomicity: a serialisation failure must not truncate the live file.rT  ú{"version": 1}rW  rX  r8  rA  >   r  r(  é   )r   ÚbadNr?   ©zX%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.read_text
}(encoding=%(py4)s)
} == %(py9)sr[  rÀ   rÁ   r©   )r*   r3   r	   Ú
write_textrw   rx   Ú	TypeErrorr`  ra  rc  rK   rL   rM   rN   rO   rP   rQ   rR   )rS   r^  r&   r®   r;  r[  ÚunserialisablerT   rU   rW   rÂ   rl   rY   r°   s                 r)   Ú*test_apply_keeps_original_when_write_failsz@TestKiloConfigBuilder.test_apply_keeps_original_when_write_fails¨  s.  € ä¤£Ó(‰ˆ�!Ü# HÓ-ˆØ˜KÑ'ˆØ×ÑÐ*°WÐÔ=Ø'-¸"È2Ñ/NÐ&OÚ!*ñ,ˆô �]‰]œ9Ó%ñ 	CØ×%Ñ%¤c¨&£k°>ÔB÷	Cð ×ÑÐE¨ÐEÑ¨Ô1ÐEÐ5EÐEÐ1Ð5EÑE×E×EÕEÐ1Ð5E×E×E×E×E×EÑEˆv×E×EÓEˆv×E×EÔEÐ×E×EÒE¨×E×EÒEÐ1×E×EÒEÐ5E×E×E×E×E×E×E×EÐE÷	Cñ 	Cús   ÁFÆFc                óT  — t        t        «       t        «       «      \  }}t        |«      }|dz  }|j	                  dd¬«       dddi idgdœii}|j                  t        |«      |«      }|d	   }d
}	||	u }
|
slt        j                  d|
fd||	f«      t        j                  |«      t        j                  |	«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}
}	|d   }|s8ddt        j                  |«      iz  }t        t        j                  |«      «      ‚d }|j                  }d}	 ||	¬«      }d}||k(  }|sÕt        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |	«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}	x}x}}y )NrT  z{"untouched": true}rW  rX  r   r8  r½   rA  rU  Fr`   rV  r  r  re   rC  zassert %(py1)srÍ   r?   rl  r[  rÀ   rÁ   r©   )r*   r3   r7   r	   rm  r`  ra  rK   rL   rP   rQ   rR   rc  rM   rN   rO   )rS   r^  r&   r®   r;  r[  rk  rÈ   rÔ   rU   r’   rí   rù   Ú@py_format2rT   rW   rÂ   rl   rY   r°   s                       r)   Ú!test_apply_refuses_invalid_configz7TestKiloConfigBuilder.test_apply_refuses_invalid_config¶  s‰  € Ü¤£¬«Ó1‰ˆ�!Ü# HÓ-ˆØ˜KÑ'ˆØ×ÑÐ/¸'ÐÔBØ˜F°¸"¨~ÈXÈJÑ$WÐXÐYˆà×*Ñ*¬3¨v«;¸Ó<ˆà�iÑ Ð) EÐ)Ð  EÐ)×)×)Õ)Ð  E×)×)Ó)Ð ×)×)Ò) E×)×)×)×)×)×)Ó)Ø�jÑ!Ð!Ñ!×!×!Ð!Ð!×!×!×!×!×!Ø×ÑÐJ¨ÐJÑ¨Ô1ÐJÐ5JÐJÐ1Ð5JÑJ×J×JÕJÐ1Ð5J×J×J×J×J×JÑJˆv×J×JÓJˆv×J×JÔJÐ×J×JÒJ¨×J×JÒJÐ1×J×JÒJÐ5J×J×J×J×J×J×J×JÐJr+   c                ód  — t        t        «       «      \  }}t        |«      }|j                  }d}||z  }t	        |«      } ||«      }	d }
|	|
u }|�sÐt        j                  d|fd|	|
f«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |	«      t        j                  |
«      dœ
z  }d	d
|iz  }t        t        j                  |«      «      ‚d x}x}x}x}x}x}	x}}
y )Nzabsent.jsonr`   )z¥%(py14)s
{%(py14)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.backup_kilo_config
}(%(py12)s
{%(py12)s = %(py6)s((%(py7)s / %(py9)s))
})
} is %(py17)sr	   r&   ra  r^  )
rC   rÍ   r‰   r‹   re   rF   rH   ri   rý   rþ   rÿ   r   )r*   r3   r	   Úbackup_kilo_configra  rK   rL   rM   rN   rO   rP   rQ   rR   )rS   r^  r&   r®   r’   r•   rÂ   r¯   r  r  r  r  r  r  s                 r)   Ú)test_backup_returns_none_for_missing_filez?TestKiloConfigBuilder.test_backup_returns_none_for_missing_fileÃ  s  € Ü¤£Ó(‰ˆ�!ä  Ó*ð 	Ð*×=Ñ=ð 	Ø(ð	Ø˜=Ñ(ð	ÜÐ(Ó)ð	Ñ=Ø)ó
ð 	àð	ð 
àð÷ 	ð 	ç Ñ ó	ð 
à÷	ò 	ç‰6÷	ò 	ïé ô !÷ 	ñ 	ç‰	ô !÷ 	ó 	ç‰6÷	ò 	ïé ð "*÷ 	ñ 	ç‰	ð "*÷ 	ò 	ç‰	ð +÷ 	ð 	ç‰	ð >÷ 	ñ 	ç‰6÷	ò 	ïé ô ÷	ñ 	ç‰	ô ÷	ó 	ç‰6÷	ò 	ïé ð ÷	ñ 	ç‰	ð ÷	ò 	ç‰	ð )÷	ð 	ç‰	ð *÷	ð 	ç‰	ð
÷ 	ð 	ç‰	ˆT÷	÷ 	÷ 	ñ 	ïé ÷	÷ 	÷ 	ò 	r+   c                ó¾  — t        t        «       «      \  }}t        |«      }|dz  }|j                  dd¬«       |j	                  t        |«      «      }d }||u}|s™t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }	d	d
|	iz  }
t        t        j                  |
«      «      ‚d x}}|j                  dd¬«       |j                  }t        |«      } |||«      }d}||u }|�s t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  t
        «      rt        j                  t
        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}|j                  }d} ||¬«      }d}||k(  }|sÕt        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}y )NrT  ri  rW  rX  r„   r†   r]   rˆ   rŠ   r‹   z{"version": 2}Tr`   )z�%(py9)s
{%(py9)s = %(py2)s
{%(py2)s = %(py0)s.restore_kilo_config
}(%(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}, %(py7)s)
} is %(py12)sr;  ra  r[  )rC   rD   r‰   rE   re   rF   rH   ri   r  rý   r?   rl  rÀ   rÁ   r©   )r*   r3   r	   rm  ru  ra  rK   rL   rM   rN   rO   rP   rQ   rR   Úrestore_kilo_configrc  )rS   r^  r&   r®   r;  r[  r]   r’   rT   r“   r”   rW   rÂ   r  r¯   ro   r#  rU   rl   rY   r°   s                        r)   Ú"test_backup_then_restore_roundtripz8TestKiloConfigBuilder.test_backup_then_restore_roundtripÊ  sW  € Ü¤£Ó(‰ˆ�!Ü# HÓ-ˆØ˜KÑ'ˆØ×ÑÐ*°WÐÔ=à×+Ñ+¬C°«KÓ8ˆØ!Ð!ˆv˜TÐ!×!×!Õ!ˆv˜T×!×!×!×!×!Ñ!ˆv×!×!Ó!ˆv×!×!Ô!˜T×!×!×!×!×!×!Ñ!à×ÑÐ*°WÐÔ=Ø×*Ñ*ÐG¬3¨v«;ÐGÑ*¨;¸Ó?ÐGÀ4ÐGÐ?À4ÐG×G×GÖGÐ?À4×G×G×G×G×GÑGˆw×G×GÓGˆw×G×GÔGÐ*×G×G×G×G×GÐG¬3×G×GÓG¬3×G×G×G×G×GÒG¨v×G×GÓG¨v×G×GÔG¨;×G×G×G×G×GÐG¸×G×GÓG¸×G×GÔGÐ?×G×GÒGÀ4×G×G×G×G×G×G×GØ×ÑÐE¨ÐEÑ¨Ô1ÐEÐ5EÐEÐ1Ð5EÑE×E×EÕEÐ1Ð5E×E×E×E×E×EÑEˆv×E×EÓEˆv×E×EÔEÐ×E×EÒE¨×E×EÒEÐ1×E×EÒEÐ5E×E×E×E×E×E×E×EÐEr+   c                óê  — t        t        «       «      \  }}|dz  }|j                  dd¬«       t        |«      }|j                  }t        |«      }d}||z  }	t        |	«      }
 |||
«      }d}||u }|�snt        j                  d|fd||f«      d	t        j                  «       v st        j                  t        «      rt        j                  t        «      nd	d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dt        j                  «       v st        j                  t
        «      rt        j                  t
        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  t
        «      rt        j                  t
        «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |
«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}x}	x}
x}x}}|j                  }d} ||¬«      }d}||k(  }|sÕt        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}y )NrT  ri  rW  rX  znope.bakFr`   )zÐ%(py18)s
{%(py18)s = %(py5)s
{%(py5)s = %(py3)s
{%(py3)s = %(py0)s(%(py1)s)
}.restore_kilo_config
}(%(py9)s
{%(py9)s = %(py6)s(%(py7)s)
}, %(py16)s
{%(py16)s = %(py10)s((%(py11)s / %(py13)s))
})
} is %(py21)sr	   r&   ra  r[  r^  )rC   rÍ   r‰   r‹   re   rF   rH   rg   r©   r«   Úpy16Úpy18Úpy21zassert %(py23)sÚpy23r?   rl  rÀ   rÁ   r©   )r*   r3   rm  r	   rx  ra  rK   rL   rM   rN   rO   rP   rQ   rR   rc  )rS   r^  r&   r®   r[  r’   r•   rÂ   re  Ú@py_assert14r  Ú@py_assert17Ú@py_assert20Ú@py_assert19Ú@py_format22Ú@py_format24rT   rU   rW   rl   rY   r°   s                         r)   Ú#test_restore_refuses_missing_backupz9TestKiloConfigBuilder.test_restore_refuses_missing_backup×  s‰  € Ü¤£Ó(‰ˆ�!Ø˜KÑ'ˆØ×ÑÐ*°WÐÔ=ô ˜hÓ'ð	
Ø'×;Ñ;ð	
ä�F“ð	
à,6ð	
à!)¨JÑ!6ð	
ä Ð!6Ó7ð	
Ù;ØÐ7óð	
ð ð		
ðð ð÷	
ð 	
ï
é ó	
ðð ÷		
ò 	
÷
 
�6÷	
ò 	
ï
é ô	 ÷	
ñ 	
÷
 
�	ô	 ÷	
ó 	
÷
 
�6÷	
ò 	
ï
é ð	 '÷	
ñ 	
÷
 
�	ð	 '÷	
ò 	
÷
 
�	ð	 (÷	
ð 	
÷
 
�	ð	 <÷	
ñ 	
÷
 
�6÷	
ò 	
ï
é ô ÷	
ñ 	
÷
 
�	ô ÷	
ó 	
÷
 
�6÷	
ò 	
ï
é ð ÷	
ñ 	
÷
 
�	ð ÷	
ò 	
÷
 
�	ð ÷	
ñ 	
÷
 
�6÷	
ò 	
ï
é ô !÷	
ñ 	
÷
 
�	ô !÷	
ó 	
÷
 
�6÷	
ò 	
ï
é ð "*÷	
ñ 	
÷
 
�	ð "*÷	
ò 	
÷
 
�	ð -7÷	
ð 	
÷
 
�	ð 8÷	
ð 	
÷
 
�	ð	÷	
ð 	
÷
 
�	ð ÷		
÷ 	
÷ 	
ñ 	
ï
é ÷	
÷ 	
÷ 	
ó 	
ð ×ÑÐE¨ÐEÑ¨Ô1ÐEÐ5EÐEÐ1Ð5EÑE×E×EÕEÐ1Ð5E×E×E×E×E×EÑEˆv×E×EÓEˆv×E×EÔEÐ×E×EÒE¨×E×EÒEÐ1×E×EÒEÐ5E×E×E×E×E×E×E×EÐEr+   Nrš   )r�   rž   rŸ   r=  r?  rI  rM  rP  rR  rg  rp  rs  rv  ry  r…  r    r+   r)   r6  r6  k  sE   „ óEóEó
4ó3óCóó
9óFóKóóFôFr+   r6  c                  óL   — e Zd Zd
d„Zd
d„Zd
d„Zd
d„Zd
d„Zd
d„Zd
d„Z	d
d„Z
y	)ÚTestModelEgressGatec           	     óÄ   — t        t        «       ¬«      }t        j                  t        «      5  |j                  ddddt        «       ¬«       d d d «       y # 1 sw Y   y xY w)N©Úegress_gateÚar<   r0  Ú@0000000000000000000000000000000000000000000000000000000000000000©Úagent_idÚprovider_idr/   Úpayload_sha256Úclassifications)r   r   rw   rx   r   Úauthorize_model_callÚ	frozenset©rS   Úgates     r)   Ú#test_missing_classifications_raisesz7TestModelEgressGate.test_missing_classifications_raisesë  sS   € Ü¬4«6Ô2ˆä�]‰]œ=Ó)ñ 	Ø×%Ñ%ØØØØ'Ü )£ð &ô ÷	÷ 	ñ 	ús   ®AÁAc           
     ó  — t        j                  t        «      5 }t        «       j	                  ddddt        dh«      ¬«       d d d «       d}j                  }t        |«      }||v }|�s
t        j                  d|fd	||f«      t        j                  |«      d
t        j                  «       v st        j                  t        «      rt        j                  t        «      nd
dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}}y # 1 sw Y   �Œ=xY w)Nr‹  r<   r0  rŒ  Úpublicr�  z	fail openr¾   ©zK%(py1)s in %(py8)s
{%(py8)s = %(py3)s(%(py6)s
{%(py6)s = %(py4)s.value
})
}ra  Úexcinfo©rÍ   r‰   rE   re   rf   rO  rg   )rw   rx   r   r   r’  r“  Úvaluera  rK   rL   rP   rM   rN   rO   rQ   rR   )rS   rš  rÔ   rW   rl   r’   rú   rn   s           r)   Ú'test_missing_egress_gate_is_fail_closedz;TestModelEgressGate.test_missing_egress_gate_is_fail_closed÷  s÷   € Ü�]‰]œ=Ó)ð 	¨WÜÓ×2Ñ2ØØØØ'Ü )¨8¨*Ó 5ð 3ô ÷	ð Ð0 '§-¡-Ð0œc -Ó0Ð0ˆ{Ð0Ð0×0×0Ö0ˆ{Ð0×0×0Ó0ˆ{×0×0×0×0×0Ð0œc×0×0Ó0œc×0×0×0×0×0Ò0 '×0×0Ó0 '×0×0Ô0 -×0×0Ò0Ð0×0×0×0×0×0×0Ö0÷	ñ 	ús   š)E>Å>Fc           	     ó  — t        «       }t        |¬«      }|j                  ddddt        dh«      ¬«       |j                  j                  «        |j                  j                  j                  d   }t        |t        «      }|�sd	d
t        j                  «       v st        j                  t        «      rt        j                  t        «      nd
dt        j                  «       v st        j                  |«      rt        j                  |«      nddt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      dœz  }t        t        j                   |«      «      ‚d}|j"                  }d}||k(  }|s­t        j$                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }	t        t        j                   |	«      «      ‚dx}x}}|j&                  }d}||k(  }|s­t        j$                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }	t        t        j                   |	«      «      ‚dx}x}}|j(                  }d}d}
||
z  }||k(  }|sÁt        j$                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |
«      dœz  }dd|iz  }t        t        j                   |«      «      ‚dx}x}x}x}
}y)z5Proves the gate is really consulted, not stubbed out.r‰  úagent-1r¸   r¦   Ú@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar˜  r�  r   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}Ú
isinstanceÚrequestr   )rC   rÍ   rD   rE   Nr?   ©z0%(py2)s
{%(py2)s = %(py0)s.agent_id
} == %(py5)srŽ   r�   rF   )z3%(py2)s
{%(py2)s = %(py0)s.provider_id
} == %(py5)sr‹  é@   )zB%(py2)s
{%(py2)s = %(py0)s.payload_sha256
} == (%(py5)s * %(py7)s)r_  rO  rg   )r   r   r’  r“  Ú	authorizeÚassert_called_onceÚ	call_argsÚargsr¡  r   rM   rN   rK   rO   rP   rQ   rR   rŽ  rL   r�  r�  )rS   Úspyr•  r¢  rU   rí   rT   r•   r”   rX   rV   rÂ   rú   rn   s                 r)   Útest_authorize_calls_gatez-TestModelEgressGate.test_authorize_calls_gate  sb  € ä‹fˆÜ¨3Ô/ˆà×!Ñ!ØØ ØØ#Ü% x jÓ1ð 	"ô 	
ð 	�‰×(Ñ(Ô*Ø—-‘-×)Ñ)×.Ñ.¨qÑ1ˆÜ˜'¤=Ó1Ð1Ò1×1×1×1×1Õ1Œz×1×1Ó1Œz×1×1×1×1×1Ò1˜'×1×1Ó1˜'×1×1×1×1×1Ò1¤=×1×1Ó1¤=×1×1Ô1Ð1×1×1×1×1×1Ð1Ø×ÑÐ, 9Ð,Ð 9Ñ,×,×,Õ,Ð 9×,×,×,×,×,Ñ,ˆw×,×,Ó,ˆw×,×,Ô,Ð×,×,Ò, 9×,×,×,×,×,×,Ó,Ø×"Ñ"Ð. hÐ.Ð" hÑ.×.×.Õ.Ð" h×.×.×.×.×.Ñ.ˆw×.×.Ó.ˆw×.×.Ô.Ð"×.×.Ò. h×.×.×.×.×.×.Ó.Ø×%Ñ%Ð1¨Ð1¨rÐ1¨¨r©Ð1Ð%¨Ñ1×1×1Õ1Ð%¨×1×1×1×1×1Ñ1ˆw×1×1Ó1ˆw×1×1Ô1Ð%×1×1Ò1¨×1×1Ò1¨r×1×1×1×1×1×1×1Ð1r+   c           
     óf  — t        «       }t        d«      |j                  _        t	        |¬«      }t        j                  t        «      5 }|j                  ddddt        dh«      ¬«       d d d «       d}j                  }t        |«      }||v }|�s
t        j                  d	|fd
||f«      t        j                  |«      dt        j                  «       v st        j                   t        «      rt        j                  t        «      nddt        j                  «       v st        j                   |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }	t#        t        j$                  |	«      «      ‚d x}x}x}}y # 1 sw Y   �Œ=xY w)Nzdenied by policyr‰  r‹  r<   r0  rŒ  r˜  r�  r¾   r™  ra  rš  r›  rO  rg   )r   r   r¥  Úside_effectr   rw   rx   r’  r“  rœ  ra  rK   rL   rP   rM   rN   rO   rQ   rR   )
rS   r©  r•  rš  rÔ   rW   rl   r’   rú   rn   s
             r)   Ú%test_authorize_propagates_gate_denialz9TestModelEgressGate.test_authorize_propagates_gate_denial  s  € Ü‹fˆÜ$1Ð2DÓ$Eˆ�‰Ô!Ü¨3Ô/ˆä�]‰]œ=Ó)ð 	¨WØ×%Ñ%ØØØØ'Ü )¨8¨*Ó 5ð &ô ÷	ð "Ð7¨¯©Ð7¤S¨Ó%7Ð7Ð!Ð%7Ð7×7×7Ö7Ð!Ð%7×7×7Ó7Ð!×7×7×7×7×7Ð7¤S×7×7Ó7¤S×7×7×7×7×7Ò7¨×7×7Ó7¨×7×7Ô7¨×7×7Ò7Ð%7×7×7×7×7×7×7Ö7÷	ñ 	ús   Á
!F&Æ&F0c                óø   — t        t        «       ¬«      }d	d„}t        j                  t        «      5  t        j                  |j                  |ddddt        dh«      ¬«      «       d d d «       y # 1 sw Y   y xY w)
Nr‰  c               “  ó    K  — t        d«      ‚­w©Nz coro_factory must not be reached©rQ   r    r+   r)   Únever_calledzUTestModelEgressGate.test_guarded_call_rejects_non_bytes_payload.<locals>.never_called*  ó   è ø€ Ü Ð!CÓDÐDùó   ‚r‹  r<   r0  é{   r˜  ©rŽ  r�  r/   Úpayloadr‘  ©r›   ra  )	r   r   rw   rx   rn  ÚasyncioÚrunÚguarded_model_callr“  )rS   r•  r²  s      r)   Ú+test_guarded_call_rejects_non_bytes_payloadz?TestModelEgressGate.test_guarded_call_rejects_non_bytes_payload'  so   € Ü¬4«6Ô2ˆó	Eô �]‰]œ9Ó%ñ 
	Ü�K‰KØ×'Ñ'Ø Ø Ø #Ø ØÜ$-¨x¨jÓ$9ð (ó ô	÷
	÷ 
	ñ 
	ús   ²5A0Á0A9c                óà   — dd„}t        j                  t        «      5  t        j                  t        «       j                  |ddddt        dh«      ¬«      «       d d d «       y # 1 sw Y   y xY w)	Nc               “  ó    K  — t        d«      ‚­wr°  r±  r    r+   r)   r²  zPTestModelEgressGate.test_guarded_call_refuses_without_gate.<locals>.never_called:  r³  r´  r‹  r<   r0  ó   hellor˜  r¶  r¸  )rw   rx   r   r¹  rº  r   r»  r“  )rS   r²  s     r)   Ú&test_guarded_call_refuses_without_gatez:TestModelEgressGate.test_guarded_call_refuses_without_gate9  sf   € ó	Eô �]‰]œ=Ó)ñ 
	Ü�K‰KÜÓ!×4Ñ4Ø Ø Ø #Ø Ø$Ü$-¨x¨jÓ$9ð 5ó ô	÷
	÷ 
	ñ 
	ús   ž=A$Á$A-c                ó”  ‡‡— t        «       Št        ‰¬«      }i Šdˆˆfd„}t        j                  |j	                  |ddddt        dh«      ¬«      «      }d	}||k(  }|s™t        j                  d
|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}}‰d   }t        j                  }	d}
 |	|
«      }|j                   } |«       }||k(  }|�st        j                  d
|fd||f«      t        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |	«      t        j                  |
«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}	x}
x}x}}y )Nr‰  c               “  ón   •K  — ‰j                   j                  j                  d   j                  ‰ d<   y­w)Nr   ÚdigestÚok)r¥  r§  r¨  r�  )Úseenr©  s   €€r)   ÚfakezPTestModelEgressGate.test_guarded_call_computes_digest_and_executes.<locals>.fakeN  s.   øè ø€ Ø Ÿ]™]×4Ñ4×9Ñ9¸!Ñ<×KÑKˆD�‰NØùs   ƒ25r‹  r<   r0  Úhellor˜  r¶  rÄ  r?   ©z%(py0)s == %(py3)srÈ   rˆ   rŠ   r‹   rÃ  r¿  )z†%(py1)s == %(py13)s
{%(py13)s = %(py11)s
{%(py11)s = %(py9)s
{%(py9)s = %(py5)s
{%(py5)s = %(py3)s.sha256
}(%(py7)s)
}.hexdigest
}()
}Úhashlib)rÍ   r‰   r‹   rF   rH   r©   r«   r\  r]  r¸  )r   r   r¹  rº  r»  r“  rK   rL   rM   rN   rO   rP   rQ   rR   rÉ  Úsha256Ú	hexdigest)rS   r•  rÆ  rÈ   r’   rT   r“   r”   rÔ   r•   rV   rÂ   r¯   re  r±   rf  rÅ  r©  s                   @@r)   Ú.test_guarded_call_computes_digest_and_executeszBTestModelEgressGate.test_guarded_call_computes_digest_and_executesI  s}  ù€ Ü‹fˆÜ¨3Ô/ˆØ!ˆö	ô —‘Ø×#Ñ#ØØØØØÜ )¨8¨*Ó 5ð $ó ó	
ˆð Ðˆv˜‰~××Õˆv˜×××××Ñˆv××Óˆv××Ô˜××××××ÑØ�H‰~ÐE¤§¡ÐE°ÐE¡°Ó!9ÐEÐ!9×!CÑ!CÐEÑ!CÓ!EÐEˆ~Ð!EÑE×E×EÖEˆ~Ð!E×E×EÓEˆ~×E×E×E×E×EÐE¤×E×EÓE¤×E×EÔE ×E×EÒE°×E×EÒEÐ!9×E×EÒEÐ!C×E×EÒEÐ!E×E×E×E×E×E×E×EÔEr+   c           
     ó^  — t        «       }t        t        «       |d¬«      }t        |¬«      }t	        j
                  t        «      5 }|j                  ddddt        dh«      ¬	«       d
d
d
«       d}j                  }t        |«      }||v }|�s
t        j                  d|fd||f«      t        j                  |«      dt        j                  «       v st        j                   t        «      rt        j                  t        «      nddt        j                  «       v st        j                   |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }	dd|	iz  }
t#        t        j$                  |
«      «      ‚d
x}x}x}}y
# 1 sw Y   �Œ=xY w)zAIntegration: the wrapper must reach the real gate and be refused.T)Ú	audit_logÚbase_decisionr‰  r‹  znot-in-any-allowlistr0  Ú@bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbr˜  r�  Nzegress deniedr¾   r™  ra  rš  r›  rO  rg   )r   r   r   r   rw   rx   r   r’  r“  rœ  ra  rK   rL   rP   rM   rN   rO   rQ   rR   )rS   ÚauditÚ	real_gateÚwrapperrš  rÔ   rW   rl   r’   rú   rn   s              r)   Ú-test_real_egress_gate_denies_unknown_providerzATestModelEgressGate.test_real_egress_gate_denies_unknown_provider`  s  € ä“ˆÜœ|›~¸ÈdÔSˆ	Ü!¨iÔ8ˆä�]‰]œ=Ó)ð 	¨WØ×(Ñ(ØØ2ØØ'Ü )¨8¨*Ó 5ð )ô ÷	ð Ð4 g§m¡mÐ4¤# mÓ"4Ð4ˆÐ"4Ð4×4×4Ö4ˆÐ"4×4×4Ó4ˆ×4×4×4×4×4Ð4¤#×4×4Ó4¤#×4×4×4×4×4Ò4 g×4×4Ó4 g×4×4Ô4 m×4×4Ò4Ð"4×4×4×4×4×4×4Ö4÷	ñ 	ús   Á!F"Æ"F,Nrš   )r�   rž   rŸ   r–  r�  rª  r­  r¼  rÀ  rÌ  rÔ  r    r+   r)   r‡  r‡  ê  s+   „ ó
ó
1ó2ó(8ó ó$ó Fô.5r+   r‡  c                  ó`   — e Zd ZdZdd„Zdd„Zdd„Zdd„Zdd„Zdd„Z	dd„Z
dd	„Zdd
„Zdd„Zy)ÚTestGatewayEgressAuthorizationzGThe gateway is the live path; without a gate the check is not optional.c                ó   — t        |d¬«      S )Núagent-under-test)rŠ  rŽ  )r   r”  s     r)   Ú_gatewayz'TestGatewayEgressAuthorization._gatewayz  s   € Ü¨Ð7IÔJÐJr+   c                ó<  ‡— t        «       }| j                  |«      }g Šˆfd„|_        |j                  ddddœgt	        dh«      ¬«      }d}||k(  }|s™t        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}}dg}‰|k(  }|s™t        j                  d	|fd
‰|f«      dt        j                  «       v st        j                  ‰«      rt        j                  ‰«      ndt        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}}|j                  j                  «        |j                  j                  j                   d   }|j"                  }d}	||	k(  }
|
s­t        j                  d	|
fd||	f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |	«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}
}	y )Nc                 ó.   •— ‰j                  d«      xs dS )NÚcalledÚresponse)r   )r¨  ÚkwargsÚexecuteds     €r)   ú<lambda>z`TestGatewayEgressAuthorization.test_chat_authorizes_before_reaching_a_provider.<locals>.<lambda>ƒ  s   ø€  H§O¡O°HÓ$=Ò$KÀ€ r+   ú	any-modelÚuserrÇ  ©ÚroleÚcontentr˜  ©r‘  rÝ  r?   rÈ  rÈ   rˆ   rŠ   r‹   rÜ  rß  r   rØ  r£  r¢  rŽ   r�   rF   )r   rÙ  Ú_execute_chatrƒ   r“  rK   rL   rM   rN   rO   rP   rQ   rR   r¥  r¦  r§  r¨  rŽ  )rS   r©  r  rÈ   r’   rT   r“   r”   r¢  r•   rU   rX   rß  s               @r)   Ú/test_chat_authorizes_before_reaching_a_providerzNTestGatewayEgressAuthorization.test_chat_authorizes_before_reaching_a_provider}  s®  ø€ Ü‹fˆØ—-‘- Ó$ˆØ ˆó Lð 	Ôð —‘ØØ¨Ñ1Ð2Ü% x jÓ1ð ó 
ˆð $Ð#ˆv˜Ñ#×#×#Õ#ˆv˜×#×#×#×#×#Ñ#ˆv×#×#Ó#ˆv×#×#Ô#˜×#×#×#×#×#×#Ñ#Ø$˜:Ð%ˆx˜:Ñ%×%×%Õ%ˆx˜:×%×%×%×%×%Ñ%ˆx×%×%Ó%ˆx×%×%Ô%˜:×%×%×%×%×%×%Ñ%Ø�‰×(Ñ(Ô*Ø—-‘-×)Ñ)×.Ñ.¨qÑ1ˆØ×ÑÐ5Ð#5Ð5ÐÐ#5Ñ5×5×5Õ5ÐÐ#5×5×5×5×5×5Ñ5ˆw×5×5Ó5ˆw×5×5Ô5Ð×5×5Ò5Ð#5×5×5×5×5×5×5Ô5r+   c                óô  — t        «       }| j                  |«      }dddœg}d„ |_        |j                  d|t	        dh«      ¬«       t        j                  t        j                  |dd	¬
«      j                  d«      «      j                  «       }|j                  j                  j                  d   }|j                  }||k(  }|s­t        j                   d|fd||f«      t        j"                  |«      t        j"                  |«      dt%        j&                  «       v st        j(                  |«      rt        j"                  |«      nddœz  }dd|iz  }	t+        t        j,                  |	«      «      ‚d x}x}}y )Nrâ  rÇ  rã  c                  ó   — y©NrÝ  r    ©r‹  Úks     r)   rà  z]TestGatewayEgressAuthorization.test_chat_digest_matches_the_message_payload.<locals>.<lambda>—  ó   � r+   rá  r˜  ræ  FT)Úensure_asciiÚ	sort_keysrW  r   r?   )z6%(py3)s
{%(py3)s = %(py1)s.payload_sha256
} == %(py5)sÚexpectedrÌ   r�   rF   )r   rÙ  rç  rƒ   r“  rÉ  rÊ  rZ  ÚdumpsÚencoderË  r¥  r§  r¨  r�  rK   rL   rP   rM   rN   rO   rQ   rR   )
rS   r©  r  Úmessagesrñ  rÔ   r’   r•   r”   rX   s
             r)   Ú,test_chat_digest_matches_the_message_payloadzKTestGatewayEgressAuthorization.test_chat_digest_matches_the_message_payload’  s  € Ü‹fˆØ—-‘- Ó$ˆØ#°Ñ8Ð9ˆá :ˆÔØ�‰�[ (¼IÀxÀjÓ<QˆÔRä—>‘>Ü�J‰J�x¨e¸tÔD×KÑKÈGÓTó
ç
‰)‹+ð 	ð �}‰}×&Ñ&×+Ñ+¨AÑ.ÐIÐ.×=Ñ=ÐIÐ=ÀÑI×I×IÕIÐ=À×I×IÓIÐ.×I×IÒIÐ=×I×I×I×I×IÐIÀ×I×IÓIÀ×I×I×I×I×I×IÖIr+   c                óv  — | j                  t        «       «      }t        «       |_        t        j                  t
        «      5 }|j                  ddddœg«       d d d «       d}j                  }t        |«      }||v }|�s
t        j                  d|fd||f«      t        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndd	t        j                  «       v st        j                  |«      rt        j                  |«      nd	t        j                  |«      t        j                  |«      d
œz  }dd|iz  }t        t        j                   |«      «      ‚d x}x}x}}|j                  j#                  «        y # 1 sw Y   �ŒWxY w)Nrá  râ  Úhirã  zassume PUBLICr¾   r™  ra  rš  r›  rO  rg   )rÙ  r   rç  rw   rx   r   rƒ   rœ  ra  rK   rL   rP   rM   rN   rO   rQ   rR   Úassert_not_called)	rS   r  rš  rÔ   rW   rl   r’   rú   rn   s	            r)   Ú(test_chat_refuses_missing_classificationzGTestGatewayEgressAuthorization.test_chat_refuses_missing_classificationŸ  s  € Ø—-‘-¤£Ó'ˆÜ $£ˆÔä�]‰]œ=Ó)ð 	K¨WØ�L‰L˜°À4Ñ'HÐ&IÔJ÷	Kð Ð4 g§m¡mÐ4¤# mÓ"4Ð4ˆÐ"4Ð4×4×4Ö4ˆÐ"4×4×4Ó4ˆ×4×4×4×4×4Ð4¤#×4×4Ó4¤#×4×4×4×4×4Ò4 g×4×4Ó4 g×4×4Ô4 m×4×4Ò4Ð"4×4×4×4×4×4×4Õ4Ø×Ñ×/Ñ/Õ1÷		Kñ 	Kús   ÁF.Æ.F8c                óò  — t        «       }| j                  |«      }d„ |_        d}|j                  dd|dœgt	        dh«      ¬«       |j
                  j                  j                  d   }t        |«      }||v}|söt        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      nddt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                   |«      «      ‚d x}x}}y )Nc                  ó   — yrë  r    rì  s     r)   rà  zXTestGatewayEgressAuthorization.test_chat_does_not_leak_message_content.<locals>.<lambda>¬  rî  r+   zcard=4111111111111111rá  râ  rã  Úpersonalræ  r   r×   )z4%(py0)s not in %(py6)s
{%(py6)s = %(py2)s(%(py4)s)
}ÚsecretÚrepr)rC   rD   rE   re   rò   rf   )r   rÙ  rç  rƒ   r“  r¥  r§  r¨  rþ  rK   rL   rM   rN   rO   rP   rQ   rR   )	rS   r©  r  rý  rU   rW   rT   rù   rú   s	            r)   Ú'test_chat_does_not_leak_message_contentzFTestGatewayEgressAuthorization.test_chat_does_not_leak_message_content©  sö   € Ü‹fˆØ—-‘- Ó$ˆÙ :ˆÔØ(ˆà�‰ØØ¨Ñ0Ð1Ü% z lÓ3ð 	ô 	
ð #&§-¡-×"9Ñ"9×">Ñ">¸qÑ"AÐBœTÐ"AÓBÐBˆvÐBÐB×B×BÕBˆvÐB×B×B×B×B×BÑBˆv×B×BÓBˆv×B×B×B×B×BÒBœT×B×BÓBœT×B×BÔBÐ"A×B×BÒBÐB×B×B×B×B×B×BÔBr+   c           	     óp  — t        «       }t        d¬«      |_        |j                  }d}dddœg} |||«      }d}||k(  }|sét	        j
                  d|fd||f«      d	t        j                  «       v st	        j                  |«      rt	        j                  |«      nd	t	        j                  |«      t	        j                  |«      t	        j                  |«      t	        j                  |«      t	        j                  |«      d
œz  }dd|iz  }	t        t	        j                  |	«      «      ‚d x}x}x}x}x}}y )NrÝ  )Úreturn_valuerá  râ  r÷  rã  r?   )zT%(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s.chat
}(%(py4)s, %(py6)s)
} == %(py11)sr  r¨   rª   r«   )r   r   rç  rƒ   rK   rL   rM   rN   rO   rP   rQ   rR   )
rS   r  rT   rU   rW   rl   r¯   rm   r°   r±   s
             r)   Ú+test_no_gate_means_no_check_and_is_explicitzJTestGatewayEgressAuthorization.test_no_gate_means_no_check_and_is_explicit·  sÎ   € Ü“.ˆÜ $°*Ô =ˆÔà�|‰|Ð[˜KÐ[°6ÀdÑ*KÐ)LÐ[‰|˜KÐ)LÓMÐ[ÐQ[Ð[ÐMÐQ[Ñ[×[×[Õ[ÐMÐQ[×[×[×[×[×[Ñ[ˆw×[×[Ó[ˆw×[×[Ô[ˆ|×[×[Ò[˜K×[×[Ò[Ð)L×[×[Ò[ÐM×[×[Ò[ÐQ[×[×[×[×[×[×[×[Ò[r+   c                óà  ‡— t        «       }| j                  |«      }g Š|j                  t        dd«      «       dˆfd„}||_        dg|j
                  _        |j                  ddddœgt        dh«      ¬«       |j                  j                  D �cg c]  }|j                  d	   j                  ‘Œ }}t        |«      }d
}||k\  }|söt        j                  d|fd||f«      dt!        j"                  «       v st        j$                  t        «      rt        j&                  t        «      nddt!        j"                  «       v st        j$                  |«      rt        j&                  |«      ndt        j&                  |«      t        j&                  |«      dœz  }	dd|	iz  }
t)        t        j*                  |
«      «      ‚d x}x}}d}||v }|s™t        j                  d|fd||f«      t        j&                  |«      dt!        j"                  «       v st        j$                  |«      rt        j&                  |«      nddœz  }dd|iz  }t)        t        j*                  |«      «      ‚d x}}y c c}w )Nzfallback-modelr¸   c                 ór   •— ‰j                  t        | d   «      «       t        ‰«      dk(  rt        d«      ‚y)Nr   r  úprimary downrÝ  )r   ra  r*  ÚRuntimeError©r¨  rÞ  Úcallss     €r)   Úflakyz]TestGatewayEgressAuthorization.test_fallback_provider_is_authorized_separately.<locals>.flakyÃ  s0   ø€ Ø�L‰Lœ˜T !™W›Ô&Ü�5‹z˜QŠÜ" >Ó2Ð2Ør+   râ  r÷  rã  r˜  ræ  r   r(  )ú>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr*  r'   r,  rò   rf   r¾   )z%(py1)s in %(py3)s)rÍ   r‰   rŠ   r‹   ©r¨  ÚobjectrÞ  r  r›   ra  )r   rÙ  r  r3   rç  r<  Úfallback_providersrƒ   r“  r¥  Úcall_args_listr¨  r�  r*  rK   rL   rM   rN   rO   rP   rQ   rR   )rS   r©  r  r	  Úcallr'   r’   rW   r•   rù   rú   rÔ   r“   r”   r  s                 @r)   Ú/test_fallback_provider_is_authorized_separatelyzNTestGatewayEgressAuthorization.test_fallback_provider_is_authorized_separately½  s‘  ø€ Ü‹fˆØ—-‘- Ó$ˆØˆØ×ÑœuÐ%5°xÓ@ÔAõ	ð !&ˆÔØ-5¨Jˆ�‰Ô)à�‰ØØ¨Ñ.Ð/Ü% x jÓ1ð 	ô 	
ð ;>¿-¹-×:VÑ:VÖW°$�T—Y‘Y˜q‘\×-Ó-ÐWˆ	ÐWÜ�9‹~Ð" Ð"ˆ~ Ñ"×"×"Õ"ˆ~ ×"×"×"×"×"Ñ"Œs×"×"Ó"Œs×"×"×"×"×"Ò"�9×"×"Ó"�9×"×"Ô"ˆ~×"×"Ò" ×"×"×"×"×"×"Ó"ØÐ$ˆx˜9Ð$×$×$Õ$ˆx˜9×$×$Ó$ˆx×$×$×$×$×$Ð$˜9×$×$Ó$˜9×$×$×$×$×$×$Ô$ùò Xs   Â I+c                ó   ‡— | j                  t        «       «      }g Šdˆfd„}||_        |j                  t	        dd«      «       dg|j
                  _        t        j                  t        «      5  |j                  ddddœgt        dh«      ¬«       d d d «       t        ‰«      }d	}||k(  }|�st        j                  d
|fd||f«      dt        j                   «       v st        j"                  t        «      rt        j$                  t        «      nddt        j                   «       v st        j"                  ‰«      rt        j$                  ‰«      ndt        j$                  |«      t        j$                  |«      dœz  }t        j&                  d«      dz   d|iz  }t)        t        j*                  |«      «      ‚d x}x}}y # 1 sw Y   �Œ2xY w)Nc                 óT   •— ‰j                  t        | d   «      «       t        d«      ‚©Nr   r  ©r   ra  r  r  s     €r)   Úalways_failszUTestGatewayEgressAuthorization.test_fallback_refuses_paid_model.<locals>.always_failsÚ  ó"   ø€ Ø�L‰Lœ˜T !™W›Ô&Ü˜~Ó.Ð.r+   z
paid-modelr¸   râ  r÷  rã  r˜  ræ  r  r?   r)  r*  r  r,  z'the paid fallback must never be reachedz
>assert %(py8)srf   r  )rÙ  r   rç  r  r7   r<  r  rw   rx   r   rƒ   r“  r*  rK   rL   rM   rN   rO   rP   rÒ   rQ   rR   ©	rS   r  r  r’   rW   r•   rù   rú   r  s	           @r)   Ú test_fallback_refuses_paid_modelz?TestGatewayEgressAuthorization.test_fallback_refuses_paid_modelÖ  s.  ø€ Ø—-‘-¤£Ó'ˆØˆõ	/ð !-ˆÔØ×Ñœu \°8Ó<Ô=Ø-5¨Jˆ�‰Ô)ä�]‰]Ô1Ó2ñ 	Ø�L‰LØØ ¨TÑ2Ð3Ü )¨8¨*Ó 5ð ô ÷	ô �5‹zÐI˜QÐIˆz˜Q‰×I×IÖIˆz˜Q×I×I×I×I×IÑIŒs×I×IÓIŒs×I×I×I×I×IÒI�5×I×IÓI�5×I×IÔIˆz×I×IÒI˜Q×I×I×IÐ I×I×I×I×I×I×IÑI÷	ñ 	ús   Á0#GÇGc                ó<  ‡— | j                  t        «       «      }g Šdˆfd„}||_        dg|j                  _        t        j                  t        «      5  |j                  ddddœgt        dh«      ¬«       d d d «       t        ‰«      }d	}||k(  }|söt        j                  d
|fd||f«      dt        j                  «       v st        j                  t        «      rt        j                   t        «      nddt        j                  «       v st        j                  ‰«      rt        j                   ‰«      ndt        j                   |«      t        j                   |«      dœz  }dd|iz  }t#        t        j$                  |«      «      ‚d x}x}}y # 1 sw Y   �ŒxY w)Nc                 óT   •— ‰j                  t        | d   «      «       t        d«      ‚r  r  r  s     €r)   r  zXTestGatewayEgressAuthorization.test_fallback_refuses_unknown_model.<locals>.always_failsï  r  r+   r¸   znot-in-registryrâ  r÷  rã  r˜  ræ  r  r?   r)  r*  r  r,  rò   rf   r  )rÙ  r   rç  r<  r  rw   rx   r   rƒ   r“  r*  rK   rL   rM   rN   rO   rP   rQ   rR   r  s	           @r)   Ú#test_fallback_refuses_unknown_modelzBTestGatewayEgressAuthorization.test_fallback_refuses_unknown_modelë  s  ø€ Ø—-‘-¤£Ó'ˆØˆõ	/ð !-ˆÔØ-5¨Jˆ�‰Ô)ä�]‰]Ô1Ó2ñ 	Ø�L‰LØ!Ø ¨TÑ2Ð3Ü )¨8¨*Ó 5ð ô ÷	ô �5‹zÐ˜QÐˆz˜Q‰××Õˆz˜Q×××××ÑŒs××ÓŒs×××××Ò�5××Ó�5××Ôˆz××Ò˜Q××××××Ô÷	ñ 	ús   Á#FÆFc                ó  — t        «       }|j                  }d} ||«      }d}||u }|sÕt        j                  d|fd||f«      dt	        j
                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}y )	Nzdefinitely-not-registeredFr`   )zT%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s._model_is_free
}(%(py4)s)
} is %(py9)sr  rÀ   rÁ   r©   )
r   Ú_model_is_freerK   rL   rM   rN   rO   rP   rQ   rR   )	rS   r  rT   rU   rW   rÂ   rl   rY   r°   s	            r)   Útest_model_is_free_fails_closedz>TestGatewayEgressAuthorization.test_model_is_free_fails_closedÿ  s¨   € Ü“.ˆà×%Ñ%ÐKÐ&AÐKÑ%Ð&AÓBÐKÀeÐKÐBÀeÐK×K×KÕKÐBÀe×K×K×K×K×KÑKˆw×K×KÓKˆw×K×KÔKÐ%×K×KÒKÐ&A×K×KÒKÐB×K×KÒKÀe×K×K×K×K×K×K×KÐKr+   N)r•  r  r›   r   rš   )r�   rž   rŸ   Ú__doc__rÙ  rè  rõ  rù  rÿ  r  r  r  r  r  r    r+   r)   rÖ  rÖ  w  s=   „ ÙQóKó6ó*Jó2óCó\ó%ó2Jó*ô(Lr+   rÖ  c                  ó4   — e Zd ZdZdZdd„Zdd„Z	 	 	 	 dd„Zy)	ÚTestSensitiveDataLeakageÚ4111111111111111zjan@example.invalidc                ó†  — t        «       }t        |¬«      }d| j                  › d| j                  › �}dd„}|j	                  t
        j                  «      5  t        j                  |j                  |ddd|t        dh«      ¬	«      «       d d d «       |j                  }|s�t        j                  d
«      dz   dt        j                  «       v st        j                   |«      rt        j"                  |«      ndt        j"                  |«      dœz  }t%        t        j&                  |«      «      ‚d }|j                  D �]ó  }|j)                  «       }	| j                  }||	v}
|
sÚt        j*                  d|
fd||	f«      dt        j                  «       v st        j                   | «      rt        j"                  | «      ndt        j"                  |«      dt        j                  «       v st        j                   |	«      rt        j"                  |	«      nddœz  }dd|iz  }t%        t        j&                  |«      «      ‚d x}}
| j                  }||	v}
|
sÚt        j*                  d|
fd||	f«      dt        j                  «       v st        j                   | «      rt        j"                  | «      ndt        j"                  |«      dt        j                  «       v st        j                   |	«      rt        j"                  |	«      nddœz  }dd|iz  }t%        t        j&                  |«      «      ‚d x}}
�Œö y # 1 sw Y   �Œ­xY w)Nr‰  úcard=z email=c               “  ó   K  — y­w©NrÄ  r    r    r+   r)   rÆ  zDTestSensitiveDataLeakage.test_raw_payload_never_logged.<locals>.fake  ó	   è ø€ Øùó   ‚rŸ  r¸   r¦   r˜  r¶  z,expected the call to be logged at some levelú-
>assert %(py2)s
{%(py2)s = %(py0)s.records
}Úcaplog©rC   rD   r×   )z7%(py2)s
{%(py2)s = %(py0)s.SECRET_CARD
} not in %(py4)srS   Úrenderedrê   r  re   )z8%(py2)s
{%(py2)s = %(py0)s.SECRET_EMAIL
} not in %(py4)sr¸  )r   r   ÚSECRET_CARDÚSECRET_EMAILÚat_levelÚloggingÚDEBUGr¹  rº  r»  r“  r%   rK   rÒ   rM   rN   rO   rP   rQ   rR   Ú
getMessagerL   )rS   r*  r©  r•  r·  rÆ  rT   Ú@py_format3r(   r,  rU   rí   rù   s                r)   Útest_raw_payload_never_loggedz6TestSensitiveDataLeakage.test_raw_payload_never_logged	  s  € Ü‹fˆÜ¨3Ô/ˆØ˜$×*Ñ*Ð+¨7°4×3DÑ3DÐ2EÐFˆó	ð �_‰_œWŸ]™]Ó+ñ 
	Ü�K‰KØ×'Ñ'ØØ&Ø (Ø%Ø#Ü$-¨x¨jÓ$9ð (ó ô	÷
	ð �~‰~ÐM‰~×MÖMÐM×M×M×M×M×MÓMˆv×M×MÓMˆv×M×MÔMˆ~×M×M×M×M×MÐMØ—n‘nó 	5ˆFØ×(Ñ(Ó*ˆHØ×#Ñ#Ð3Ð#¨8Ð3×3×3Õ3Ð#¨8×3×3×3×3×3Ñ3�4×3×3Ó3�4×3×3Ô3Ð#×3×3×3×3×3Ð3¨8×3×3Ó3¨8×3×3×3×3×3×3Ó3Ø×$Ñ$Ð4Ð$¨HÐ4×4×4Õ4Ð$¨H×4×4×4×4×4Ñ4�4×4×4Ó4�4×4×4Ô4Ð$×4×4×4×4×4Ð4¨H×4×4Ó4¨H×4×4×4×4×4×4Õ4ñ	5÷
	ñ 
	ús   Á5L6Ì6M c                ó´  — t        «       }t        |¬«      }d| j                  › �}dd„}t        j                  |j                  |ddd|t        dh«      ¬«      «       |j                  j                  j                  d	   }| j                  }t        |«      }||v}|�s7t        j                  d
|fd||f«      dt        j                  «       v st        j                  | «      rt        j                   | «      ndt        j                   |«      dt        j                  «       v st        j                  t        «      rt        j                   t        «      nddt        j                  «       v st        j                  |«      rt        j                   |«      ndt        j                   |«      dœz  }	dd|	iz  }
t#        t        j$                  |
«      «      ‚d x}x}}|j&                  }t(        j*                  }|j,                  } |«       } ||«      }|j.                  } |«       }||k(  }|�s›t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                   |«      ndt        j                   |«      dt        j                  «       v st        j                  t(        «      rt        j                   t(        «      ndt        j                   |«      dt        j                  «       v st        j                  |«      rt        j                   |«      ndt        j                   |«      t        j                   |«      t        j                   |«      t        j                   |«      t        j                   |«      dœ
z  }dd|iz  }t#        t        j$                  |«      «      ‚d x}x}x}x}x}x}x}}y )Nr‰  r$  c               “  ó   K  — y­wr&  r    r    r+   r)   rÆ  zUTestSensitiveDataLeakage.test_egress_request_carries_digest_not_content.<locals>.fake(  r'  r(  rŸ  r¸   r¦   r˜  r¶  r   r×   )zU%(py2)s
{%(py2)s = %(py0)s.SECRET_CARD
} not in %(py7)s
{%(py7)s = %(py4)s(%(py5)s)
}rS   rþ  r¢  )rC   rD   rE   r‹   rF   rG   rH   r?   )zá%(py2)s
{%(py2)s = %(py0)s.payload_sha256
} == %(py17)s
{%(py17)s = %(py15)s
{%(py15)s = %(py13)s
{%(py13)s = %(py6)s
{%(py6)s = %(py4)s.sha256
}(%(py11)s
{%(py11)s = %(py9)s
{%(py9)s = %(py7)s.encode
}()
})
}.hexdigest
}()
}rÉ  r·  )
rC   rD   rE   re   rF   rH   r©   r«   r]  rþ   rÿ   r   r¸  )r   r   r-  r¹  rº  r»  r“  r¥  r§  r¨  rþ  rK   rL   rM   rN   rO   rP   rQ   rR   r�  rÉ  rÊ  ró  rË  )rS   r©  r•  r·  rÆ  r¢  rT   rV   rU   rX   rY   rW   rÂ   r¯   re  r  r  r  r  s                      r)   Ú.test_egress_request_carries_digest_not_contentzGTestSensitiveDataLeakage.test_egress_request_carries_digest_not_content#  sZ  € Ü‹fˆÜ¨3Ô/ˆØ˜$×*Ñ*Ð+Ð,ˆó	ô 	�‰Ø×#Ñ#ØØ"Ø$Ø!ØÜ )¨8¨*Ó 5ð $ó ô		
ð —-‘-×)Ñ)×.Ñ.¨qÑ1ˆØ×ÑÐ4¤t¨G£}Ð4Ð }Ð4×4×4Ö4Ð }×4×4×4×4×4Ñ4ˆt×4×4Ó4ˆt×4×4Ô4Ð×4×4×4×4×4Ð4¤t×4×4Ó4¤t×4×4×4×4×4Ò4¨G×4×4Ó4¨G×4×4Ô4 }×4×4×4×4×4×4Ó4Ø×%Ñ%ÐU¬¯©ÐU¸¿¹ÐU¹Ó8HÐU©Ð8HÓ)IÐUÐ)I×)SÑ)SÐUÑ)SÓ)UÐUÐ%Ð)UÑU×U×UÖUÐ%Ð)U×U×U×U×U×UÑUˆw×U×UÓUˆw×U×UÔUÐ%×U×U×U×U×UÐU¬×U×UÓU¬×U×UÔU¨×U×U×U×U×UÐU¸×U×UÓU¸×U×UÔU¸×U×UÒUÐ8H×U×UÒUÐ)I×U×UÒUÐ)S×U×UÒUÐ)U×U×U×U×U×U×U×UÖUr+   c           
     óž  — t        «       }t        |¬«      }|j                  t        j                  «      5  |j                  ddddt        dh«      ¬«       d d d «       |j                  }|s�t        j                  d«      d	z   d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      dœz  }t        t        j                  |«      «      ‚d }|j                  D �]3  }| j                   }|j"                  } |«       }||v}	|	�st        j$                  d|	fd||f«      dt        j                  «       v st        j                  | «      rt        j                  | «      ndt        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }
dd|
iz  }t        t        j                  |«      «      ‚d x}x}	x}}�Œ6 y # 1 sw Y   �ŒíxY w)Nr‰  rŸ  r¸   r¦   Ú@ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccr˜  r�  z.authorize must leave an audit trail in the logr)  r*  r+  r×   )zn%(py2)s
{%(py2)s = %(py0)s.SECRET_CARD
} not in %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.getMessage
}()
}rS   r(   )rC   rD   rE   re   rf   rO  rg   )r   r   r/  r0  r1  r’  r“  r%   rK   rÒ   rM   rN   rO   rP   rQ   rR   r-  r2  rL   )rS   r*  r©  r•  rT   r3  r(   rW   rl   rU   rú   rn   s               r)   Útest_authorize_logs_digest_onlyz8TestSensitiveDataLeakage.test_authorize_logs_digest_only:  sx  € ô ‹fˆÜ¨3Ô/ˆà�_‰_œWŸ]™]Ó+ñ 	Ø×%Ñ%Ø"Ø$Ø!Ø'Ü )¨8¨*Ó 5ð &ô ÷	ð �~‰~ÐO‰~×OÖOÐO×O×O×O×O×OÓOˆv×O×OÓOˆv×O×OÔOˆ~×O×O×O×O×OÐOØ—n‘nó 	?ˆFØ×#Ñ#Ð>¨6×+<Ñ+<Ð>Ñ+<Ó+>Ð>Ð#Ð+>Ð>×>×>Ö>Ð#Ð+>×>×>×>×>×>Ñ>�4×>×>Ó>�4×>×>Ô>Ð#×>×>×>×>×>Ð>¨6×>×>Ó>¨6×>×>Ô>Ð+<×>×>Ò>Ð+>×>×>×>×>×>×>×>ñ	?÷	ñ 	ús   ¶!IÉIN)r*  zpytest.LogCaptureFixturer›   rœ   rš   )r�   rž   rŸ   r-  r.  r4  r7  r:  r    r+   r)   r!  r!    s,   „ Ø$€KØ(€Ló5ó4Vð.?Ø.ð?à	ô?r+   r!  )r%   r   r›   z!tuple[ModelRegistry, ModelRouter])r¦   r¸   )r/   ra  r   ra  r›   r   )r½   r¸   ):r  Ú
__future__r   ÚbuiltinsrM   Ú_pytest.assertion.rewriteÚ	assertionÚrewriterK   r¹  rÉ  ró   rZ  r0  Úunittest.mockr   rw   Ú(cyberbrain26.control_plane.model_gatewayr   r   r   Ú5cyberbrain26.control_plane.model_gateway.model_egressr   Ú$cyberbrain26.model_layer.kilo_configr	   r
   Ú'cyberbrain26.model_layer.model_registryr   r   r   r   Ú*cyberbrain26.model_layer.provider_registryr   r   r   Ú(cyberbrain26.model_layer.role_assignmentr   r   r   Úcyberbrain26.model_layer.routerr   r   Ú"cyberbrain26.security_plane.egressr   r   r   Ú&cyberbrain26.security_plane.permissionr   r*   r3   r7   r9   r¢   r
  r6  r‡  rÖ  r!  r    r+   r)   ú<module>rJ     sÚ   ðñõ #ç  „ ƒÛ Û Û Û Ý ã ÷ñ õ
 R÷÷ó ÷ñ ÷
ñ ÷
 Jß VÑ VÝ @óWô"ô÷BBñ BB÷Ts
ñ s
÷v@$ñ @$÷PwFñ wF÷~E5ñ E5÷ZKLñ KL÷\F?ò F?r+   