ó
    ¦ÉjÛ  ã                   óÆ   • S r SSKrSSKJs  Jr  SSKrSSKrSSK	r	SSK
Jr  SSKJr  SSKJr  SSKJrJr  SSKJrJrJr  S\4S	 jrS
 rS rS rS rS rS rS rS r S r!g)u*  
test_cleanup_service.py â€” nettoyage RGPD (services/cleanup_service.py), Ã  l'origine
de l'incident du 2026-09-03 oÃ¹ des photos de familles ont Ã©tÃ© supprimÃ©es sans trace.

Utilise exclusivement des dossiers temporaires (tmp_path, monkeypatch) : ne touche
JAMAIS aux vrais dossiers de photos.
é    N)Ú	timedelta)Úconfig)Úget_db)ÚutcnowÚ
utcnow_iso)Úaudit_serviceÚcleanup_serviceÚschool_serviceÚage_daysc                 óÀ   • U R                   R                  SSS9  U R                  S5        [        R                  " 5       US-  -
  n[        R
                  " XU45        g )NT)ÚparentsÚexist_oks   fake-image-contenti€Q )ÚparentÚmkdirÚwrite_bytesÚtimeÚosÚutime)Úpathr   Úmtimes      Ú]D:\Ingenieria\TRABAJOS ONLINE\Projects\11- Photo School\backend\tests\test_cleanup_service.pyÚ_touchr      sM   € Ø‡K�K×Ñ˜d¨TÐÑ2Ø×ÑÐ*Ô+Ü�IŠI‹K˜( UÑ*Ñ*€EÜ‡H‚HˆT˜5�>Õ"ó    c                 ó¨   • U R                  [        SUS-  5        U R                  [        SUS-  5        U R                  [        SUS-  5        US-  $ )NÚ
PHOTOS_DIRÚphotosÚINCOMING_DIRÚincomingÚ
THUMBS_DIRÚthumbs)Úsetattrr	   )ÚmonkeypatchÚtmp_paths     r   Ú_patch_dirsr$      sR   € Ø×Ñœ¨°xÀ(Ñ7JÔKØ×Ñœ¨¸ÀJÑ9NÔOØ×Ñœ¨°xÀ(Ñ7JÔKØ�hÑÐr   c                 ó  • [        X5      nUS-  S-  nUS-  S-  nUS-  S-  n[        USS9  [        USS9  [        USS9  [        R                  of" 5       nSo‡U:H  o™(       d×  [        R
                  " S	U	4S
Xx45      S[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  n
SSU
0-  n[        [        R                  " U5      5      eS =n=n=p˜UR                  of" 5       ow(       + o™(       dš  SS[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =n=pyUR                  of" 5       ow(       dš  SS[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =pgUR                  of" 5       ow(       d±  [        R                  " S5      S-   S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =pgg )NzOLD-1234zportrait.jpgzNEW-5678z	meta.jsonéZ   ©r   é   é   ©ú==©zG%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.run_once
}()
} == %(py7)sr	   ©Úpy0Úpy2Úpy4Úpy7úassert %(py9)sÚpy9úEassert not %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}Ú	old_photo©r.   r/   r0   úAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}Úrecent_photou@   meta.json n'est pas une image â€” ne doit jamais Ãªtre supprimÃ©zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}Ú	non_image)r$   r   r	   Úrun_onceÚ
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚAssertionErrorÚ_format_explanationÚexistsÚ_format_assertmsg)r#   r"   Ú
photos_dirr5   r8   r9   Ú@py_assert1Ú@py_assert3Ú@py_assert6Ú@py_assert5Ú@py_format8Ú@py_format10Ú@py_format6Ú@py_format5s                 r   Ú,test_deletes_only_files_older_than_retentionrN   !   s  € Ü˜[Ó3€JØ 
Ñ*¨^Ñ;€IØ 
Ñ*¨^Ñ;€LØ 
Ñ*¨[Ñ8€IÜ
ˆ9˜rÒ"Ü
ˆ< !Ò$Ü
ˆ9˜rÒ"ä×#Ñ#Ð*Ð#Ó%Ð*¨Ð*¨Ñ*×*×*×*Ò*Ð%×*×*×*×*×*Õ*Œ?×*×*×*Ñ*Œ?×*×*Õ*Ð#×*×*Ó*Ð%×*×*Ó*¨×*×*×*×*×*×*Õ*Ø×ÑÐ!ÐÓ!Ð!Ô!Ð!Õ!×!×!×!×!×!Ñ!ˆy×!×!×!Ñ!ˆy×!×!Õ!Ð×!×!Ó!Ð!×!×!×!×!×!Ô!Ø×ÑÐ ÐÓ Ð Õ × × × × × Ñ ˆ<× × × Ñ ˆ<× × Õ Ð× × Ó Ð × × × × × Ò Ø×ÑÐaÐÓÐaÕ×a×aÐa×a×a×a×a×a×aˆ9×a×a×aÑaˆ9×a×aÕaÐ×a×aÓaÐ×a×a×a×a×aÓar   c           	      ó\  • [        X5      n[        R                  " SS[        R                  " 5       R
                  SS  3S9S   n[        R                  " SS[        R                  " 5       R
                  SS  3S9S   n[        R                  " US	S
05        [        R                  " US	S05        [        5        nSU4SU44 H"  u  pgUR                  SXf[        5       U45        M$     UR                  5         SSS5        US-  S-  nUS-  S-  n	[        USS9  [        U	SS9  [        R                  oª" 5       nSoËU:H  oÝ(       d×  [        R                  " SU4SX¼45      S[         R"                  " 5       ;   d  [        R$                  " [        5      (       a  [        R&                  " [        5      OS[        R&                  " U
5      [        R&                  " U5      [        R&                  " U5      S.-  nSSU0-  n[)        [        R*                  " U5      5      eS=n
=n=pÜUR,                  oª" 5       o»(       + oÝ(       dš  SS[         R"                  " 5       ;   d  [        R$                  " U5      (       a  [        R&                  " U5      OS[        R&                  " U
5      [        R&                  " U5      S.-  n[)        [        R*                  " U5      5      eS=n
=p½U	R,                  oª" 5       o»(       dš  SS[         R"                  " 5       ;   d  [        R$                  " U	5      (       a  [        R&                  " U	5      OS[        R&                  " U
5      [        R&                  " U5      S.-  n[)        [        R*                  " U5      5      eS=p«g! , (       d  f       GN¦= f)uC   Deux Ã©coles, deux durÃ©es : 20 jours chez l'une, 120 chez l'autre.u   RÃ©tention courtezshort-Nr(   ©ÚslugÚidu   RÃ©tention longuezlong-Ú	rgpd_daysé   éx   zSHT-0001zLNG-0001z[INSERT OR REPLACE INTO families (code, family_name, created_at, school_id) VALUES (?,?,?,?)úa.jpgzb.jpgé   r'   r)   r*   r,   r	   r-   r2   r3   r4   Úar6   r7   Úb)r$   r
   Úcreate_schoolÚuuidÚuuid4ÚhexÚupdate_settingsr   Úexecuter   Úcommitr   r	   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   )r#   r"   rE   ÚshortÚlong_ÚconnÚcodeÚsidrX   rY   rF   rG   rH   rI   rJ   rK   rL   rM   s                     r   Ú+test_retention_follows_each_schools_settingrf   0   ss  € ä˜[Ó3€JÜ×(Ò(Ð)<ÀVÌDÏJÊJËL×L\ÑL\Ð]_Ð^_ÐL`ÐKaÐCbÑcÐdhÑi€EÜ×(Ò(Ð)<ÀUÌ4Ï:Ê:Ë<×K[ÑK[Ð\^Ð]^ÐK_ÐJ`ÐCaÑbÐcgÑh€EÜ×"Ò" 5¨;¸Ð*;Ô<Ü×"Ò" 5¨;¸Ð*<Ô=Ü	Œ�TØ% uÐ-°
¸EÐ/BÓC‰IˆDØ�L‰LÐvØ¤j£l°CÐ8ö:ñ Dð 	�‰Œ÷	 
ð
 	�ZÑ 'Ñ)€AØ�ZÑ 'Ñ)€AÜ
ˆ1�rÒÜ
ˆ1�rÒä×#Ñ#Ð*Ð#Ó%Ð*¨Ð*¨Ñ*×*×*×*Ò*Ð%×*×*×*×*×*Õ*Œ?×*×*×*Ñ*Œ?×*×*Õ*Ð#×*×*Ó*Ð%×*×*Ó*¨×*×*×*×*×*×*Õ*Ø�x‰xÐˆx‹zÐŒ>Ð�>×××××Ñˆq×××Ñˆq××Õˆx××Óˆz×××××ÔØ�8‰8Ðˆ8‹:Ð�:×××××Ñˆ1×××Ñˆ1××Õˆ8××Óˆ:×××××Ó÷ 
Žús   Â>?NÎ
N+c                 óš  • [        X5      n[        R                  " SS[        R                  " 5       R
                  S S  3S9S   n[        5        nUR                  S[        5       U45        UR                  5         S S S 5        [        US-  S-  S	S
9  [        R                  " 5         [        R                  " SSS9 Vs/ s H  oUS   S:X  d  M  UPM     nnU(       d‡  [        R                   " S5      S-   SS["        R$                  " 5       ;   d  [        R&                  " U5      (       a  [        R(                  " U5      OS0-  n[+        [        R,                  " U5      5      eUS   S   nSo˜U	:H  oª(       do  [        R.                  " SU
4SX‰45      [        R(                  " U5      [        R(                  " U	5      S.-  nSSU0-  n[+        [        R,                  " U5      5      eS =n=p©US   S   S   nSo˜U	:H  oª(       do  [        R.                  " SU
4SX‰45      [        R(                  " U5      [        R(                  " U	5      S.-  nSSU0-  n[+        [        R,                  " U5      5      eS =n=p©US   S   oˆU:H  oª(       d¥  [        R.                  " SU
4SXƒ45      [        R(                  " U5      S ["        R$                  " 5       ;   d  [        R&                  " U5      (       a  [        R(                  " U5      OS S!.-  nS"S#U0-  n[+        [        R,                  " U5      5      eS =pŠg ! , (       d  f       GN¿= fs  snf )$Nu   Audit Ã©colezaud-r(   rP   rR   zfINSERT OR REPLACE INTO families (code, family_name, created_at, school_id) VALUES ('AUD-0001','A',?,?)zAUD-0001zfratrie.jpgr&   r'   zphoto.rgpd_deleteé2   )ÚactionÚlimitÚresource_idu)   toute suppression RGPD doit Ãªtre tracÃ©ez
>assert %(py0)sr.   Úmatchingr   ÚseverityÚcriticalr*   ©z%(py1)s == %(py4)s©Úpy1r0   úassert %(py6)sÚpy6ÚdetailsÚfiles_deletedr)   Ú	school_id)z%(py1)s == %(py3)sre   ©rq   Úpy3úassert %(py5)sÚpy5)r$   r
   rZ   r[   r\   r]   r   r_   r   r`   r   r	   r:   r   Úlist_eventsr;   rD   r=   r>   r?   r@   rA   rB   r<   )r#   r"   rE   re   rc   Úerl   Ú@py_format1Ú@py_assert0rG   Ú@py_assert2rM   Ú@py_format7Ú@py_format4rL   s                  r   Ú;test_deletion_is_logged_as_critical_audit_event_with_schoolr‚   F   s%  € Ü˜[Ó3€JÜ
×
&Ò
& ~¸dÄ4Ç:Â:Ã<×CSÑCSÐTVÐUVÐCWÐBXÐ<YÑ
ZÐ[_Ñ
`€CÜ	Œ�TØ�‰Ð}Ü “l CÐ(ô	*à�‰Œ÷ 
ô ˆ:˜
Ñ" ]Ñ2¸RÒ@ä×ÒÔä(×4Ò4Ð<OÐWYÒZÓ}ÒZ�aÐ`mÑ^nÐr|Ñ^|—ÑZ€HÐ}Þ×@×@Ð@×@×@×@×@×@×@Ð@ˆ8×@×@×@Ñ@ˆ8×@×@×@×@×@Ð@Ø�A‰;�zÑ"Ð0 jÐ0 jÑ0×0×0×0Ò0Ð"×0×0Ô0Ð"×0×0Ó0 j×0×0×0×0×0×0Ó0Ø�A‰;�yÑ! /Ñ2Ð7°aÐ7°aÑ7×7×7×7Ò7Ð2×7×7Ô7Ð2×7×7Ó7°a×7×7×7×7×7×7Ó7Ø�A‰;�{Ñ#Ð* sÑ*×*×*×*Ò*Ð#×*×*Ô*Ð#×*×*×*×*×*Ô* s×*×*×*Ñ* s×*×*×*×*×*×*Ô*÷ 
Žüò ~s   Á-L6ÃMÃMÌ6
Mc                 óâ  • [        X5      nUS-  n[        US-  SS9  [        R                  " 5         UR                  oD" 5       oU(       + of(       dš  SS[
        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =n=pVg )NzPRU-0001zonly_photo.jpgr&   r'   r4   Ú
family_dirr6   ©r$   r   r	   r:   rC   r=   r>   r;   r?   r@   rA   rB   )r#   r"   rE   r„   rF   rG   rI   rL   s           r   Ú1test_empty_family_folder_is_pruned_after_deletionr†   X   sœ   € Ü˜[Ó3€JØ˜jÑ(€JÜ
ˆ:Ð(Ñ(°2Ò6Ü×ÒÔØ× Ñ Ð"Ð Ó"Ð"Ô"Ð"Õ"×"×"×"×"×"Ñ"ˆz×"×"×"Ñ"ˆz×"×"Õ"Ð ×"×"Ó"Ð"×"×"×"×"×"Õ"r   c                 ó>  • [        X5      n[        US-  S-  SS9  [        US-  S-  SS9  [        R                  o3" 5       nSoTU:H  of(       d×  [        R
                  " SU4S	XE45      S
[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OS
[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS =n=n=peSo2U-  nSo”U	-  oUR                  oª" 5       o»(       dÄ  SS[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U	5      [        R                  " U
5      [        R                  " U5      S.-  n[        [        R                  " U5      5      eS =n=n=n	=n=p«g )NzFRESH-01rV   r)   r'   zb.webpé
   r   r*   r,   r	   r-   r2   r3   z[assert %(py10)s
{%(py10)s = %(py8)s
{%(py8)s = ((%(py0)s / %(py2)s) / %(py5)s).exists
}()
}rE   )r.   r/   rz   Úpy8Úpy10)r$   r   r	   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   )r#   r"   rE   rF   rG   rH   rI   rJ   rK   Ú@py_assert4Ú@py_assert7Ú@py_assert9Ú@py_format11s                r   Ú/test_nothing_deleted_when_all_photos_are_recentr�   `   sQ  € Ü˜[Ó3€JÜ
ˆ:˜
Ñ" WÑ,°qÒ9Ü
ˆ:˜
Ñ" XÑ-¸Ò;Ü×#Ñ#Ð*Ð#Ó%Ð*¨Ð*¨Ñ*×*×*×*Ò*Ð%×*×*×*×*×*Õ*Œ?×*×*×*Ñ*Œ?×*×*Õ*Ð#×*×*Ó*Ð%×*×*Ó*¨×*×*×*×*×*×*Õ*Ø#Ð7˜Ñ#Ð7 gÐ7 gÑ-Ð7×5Ñ5Ð7Ð5Ó7Ð7Õ7×7×7×7×7×7Ñ7ˆJ×7×7×7Ñ7ˆJ×7×7Õ7˜×7×7Ó7 g×7×7Ó7Ð5×7×7Ó7Ð7×7×7×7×7×7×7Ó7r   c                 ó  • [        X5      n[        US-  S-  SS9  U S-  S-  S-  n[        USS9  [        R                  " 5         UR                  oD" 5       oU(       + of(       dš  SS	[
        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS	[        R                  " U5      [        R                  " U5      S
.-  n[        [        R                  " U5      5      eS =n=pVg )NzPRV-0001zx.jpgr&   r'   r    z	x.wm.webpr)   r4   Úpreviewr6   r…   )r#   r"   rE   r‘   rF   rG   rI   rL   s           r   Ú>test_orphan_watermarked_previews_are_removed_with_the_originalr’   h   s°   € Ü˜[Ó3€JÜ
ˆ:˜
Ñ" WÑ,°rÒ:Ø˜Ñ! JÑ.°Ñ<€GÜ
ˆ7˜QÒÜ×ÒÔØ�~‰~Ðˆ~ÓÐÔÐÕ×××××Ñˆw×××Ñˆw××Õˆ~××ÓÐ×××××Õr   c                 óz  ^• [        X5      n/ mUR                  [        R                  SSU4S jj5        UR                  [        SS5        [        S5       H  n[        US-  U S3-  SS	9  M     [        R                  " 5         S
oDT;   oU(       d¦  [        R                  " SU4SUT45      [        R                  " U5      S[        R                  " 5       ;   d  [        R                  " T5      (       a  [        R                  " T5      OSS.-  nSSU0-  n[        [        R                  " U5      5      eS =pEg )NÚnotifyc                 ó&   >• TR                  U 5      $ ©N)Úappend)ÚkeyÚsubjectÚbodyÚalertss      €r   Ú<lambda>Ú6test_mass_deletion_triggers_an_alert.<locals>.<lambda>t   s   ø€ Ð_e×_lÑ_lÐmpÔ_qr   ÚRGPD_ALERT_THRESHOLDé   r(   zMAS-0001z.jpgr&   r'   zrgpd-mass-delete)Úin)z%(py1)s in %(py3)sr›   rw   ry   rz   )Ú )r$   r!   r	   Úalert_servicer   Úranger   r:   r;   r<   r@   r=   r>   r?   rA   rB   )	r#   r"   rE   Úir~   r   r�   rL   r›   s	           @r   Ú$test_mass_deletion_triggers_an_alertr¥   q   sÑ   ø€ Ü˜[Ó3€JØ€FØ×Ñœ×5Ñ5°xÖAqÔrØ×ÑœÐ 6¸Ô:Ü�1ŽXˆÜˆz˜JÑ&¨A¨3¨d¨Ñ3¸bÔAñ ä×ÒÔØÐ' Ñ'×'×'×'Ò'Ð ×'×'Ô'Ð×'×'×'×'×'Ô' ×'×'×'Ñ' ×'×'×'×'×'×'Ô'r   c           	      ó:  ^• [        X5        SSKJnJn  [	        5       [        [        R                  S-   S9-
  R                  5       nS [        S5       5       u  pVpxU" USSU" 5       /S	US
9  U" USSU" 5       /SUS
9  U" USSU" 5       /S	S9  U" USSU" 5       /SUS
9  [        R                  o™" 5       n
SoºU:¬  oÌ(       d×  [        R                  " SU4SX«45      S[        R                  " 5       ;   d  [        R                   " [        5      (       a  [        R"                  " [        5      OS[        R"                  " U	5      [        R"                  " U
5      [        R"                  " U5      S.-  nSSU0-  n[%        [        R&                  " U5      5      eS =n	=n
=pË[)        5        mU4S jnU" U5      S   U" U5      S   4nSn
UU
:H  nU(       dp  [        R                  " SU4SUU
45      [        R"                  " U5      [        R"                  " U
5      S.-  nSSU0-  n[%        [        R&                  " U5      5      eS =n=nn
U" U5      S   nSn
UU
:H  nU(       dp  [        R                  " SU4SUU
45      [        R"                  " U5      [        R"                  " U
5      S.-  nSSU0-  n[%        [        R&                  " U5      5      eS =n=nn
U" U5      S   nSn
UU
:H  nU(       dp  [        R                  " SU4SUU
45      [        R"                  " U5      [        R"                  " U
5      S.-  nSSU0-  n[%        [        R&                  " U5      5      eS =n=nn
U" U5      S   U" U5      S   4nSn
UU
:H  nU(       dp  [        R                  " SU4SUU
45      [        R"                  " U5      [        R"                  " U
5      S.-  nSSU0-  n[%        [        R&                  " U5      5      eS =n=nn
S S S 5        g ! , (       d  f       g = f) Nr   )Úinsert_orderÚitemé   )Úhoursc              3   ó^   #   • U  H#  n[        [        R                  " 5       5      v •  M%     g 7fr–   )Ústrr[   r\   )Ú.0Ú_s     r   Ú	<genexpr>ÚLtest_abandoned_unpaid_orders_expire_and_paid_ones_survive.<locals>.<genexpr>€   s   é € Ð'LÂ8¸a¬¬D¯JªJ«L×(9Ð(9Â8ùs   ‚+-é   zTST-1001z
ecole-testÚunpaid)Úpayment_statusÚ
created_atÚfailed)r³   Úpaid)ú>=)zS%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.expire_unpaid_orders
}()
} >= %(py7)sr	   r-   r2   r3   c                 óF   >• TR                  SU 45      R                  5       $ )Nz4SELECT status, payment_status FROM orders WHERE id=?)r_   Úfetchone)r¤   rc   s    €r   rœ   ÚKtest_abandoned_unpaid_orders_expire_and_paid_ones_survive.<locals>.<lambda>ˆ   s   ø€ ˜Ÿ™Ð%[Ð^_Ð]aÓb×kÑkÔmr   Ústatusr³   )Ú	cancelledÚexpiredr*   ro   rp   rr   rs   r¼   Úpending)r¾   r¶   )r$   Úconftestr§   r¨   r   r   r   ÚUNPAID_ORDER_TTL_HOURSÚ	isoformatr£   r	   Úexpire_unpaid_ordersr;   r<   r=   r>   r?   r@   rA   rB   r   )r#   r"   r§   r¨   ÚoldÚstaleÚstale_failedÚfreshr¶   rF   rG   rH   rI   rJ   rK   Úgetr~   r   rM   r€   rc   s                       @r   Ú9test_abandoned_unpaid_orders_expire_and_paid_ones_surviverÈ   |   sÉ  ø€ Ü�Ô&ß+Ü‹8”i¤f×&CÑ&CÀaÑ&GÑHÑH×
SÑ
SÓ
U€CÙ'LÄ5ÈÄ8Ó'LÑ$€E˜Ù�˜
 L±4³6°(È8Ð`cÒdÙ�˜z¨<¹$»&¸ÐRZÐgjÒkÙ�˜
 L±4³6°(È8ÒTÙ��z <±$³&°È&Ð]`Òaä×/Ñ/Ð6Ð/Ó1Ð6°QÐ6°QÑ6×6×6×6Ò6Ð1×6×6×6×6×6Õ6Œ?×6×6×6Ñ6Œ?×6×6Õ6Ð/×6×6Ó6Ð1×6×6Ó6°Q×6×6×6×6×6×6Õ6Ü	Œ�TÜmˆÙ�E“
˜8Ñ$¡c¨%£jÐ1AÑ&BÐCÐ_ÐG_Ð_ÐCÐG_Ñ_×_×_×_Ó_ÐCÐG_×_×_Ô_ÐC×_×_Ó_ÐG_×_×_×_×_×_×_Ô_Ù�<Ó  Ñ*Ð9¨kÐ9Ð*¨kÑ9×9×9×9Ó9Ð*¨k×9×9Ô9Ð*×9×9Ó9¨k×9×9×9×9×9×9Ô9Ù�5‹z˜(Ñ#Ð0 yÐ0Ð# yÑ0×0×0×0Ó0Ð# y×0×0Ô0Ð#×0×0Ó0 y×0×0×0×0×0×0Ô0Ù�D“	˜(Ñ#¡S¨£YÐ/?Ñ%@ÐAÐXÐEXÐXÐAÐEXÑX×X×X×XÓXÐAÐEX×X×XÔXÐA×X×XÓXÐEX×X×X×X×X×X×XÔX÷ 
�Žús   Æ*IPÐ
P)"Ú__doc__Úbuiltinsr=   Ú_pytest.assertion.rewriteÚ	assertionÚrewriter;   r   r   r[   Údatetimer   Úcorer   Úcore.dbr   Úcore.timeutilr   r   Úservicesr   r	   r
   Úfloatr   r$   rN   rf   r‚   r†   r�   r’   r¥   rÈ   © r   r   Ú<module>rÕ      sf   ðñ÷ „ ƒ	Û Û Ý å Ý ß ,ß CÑ Cð#˜5ô #òòbòò,+ò$#ò8ò ò(óYr   