a
    4ñ»jŸ'  ã                   @  s  d Z ddlmZ ddlmZ ddlZddlmZ ddlZddl	Z	ddl
mZ ddlmZ ddlZddlZddlmZ ejd	d
dœdd„ƒZejdddœdd„ƒZdd
dœdd„ZG dd„ dƒZddd
dœdd„Zdddd
dœd d!„ZG d"d#„ d#ƒZG d$d%„ d%ƒZdS )&a&  
Implement -f aka looponfailing for pytest.

NOTE that we try to avoid loading and depending on application modules
within the controlling process (the one that starts repeatedly test
processes) otherwise changes to source code can crash
the controlling process which should best never happen.
é    )Úannotations)ÚSequenceN©ÚPath)ÚAny)ÚTerminalWriter)Ú
visit_pathzpytest.ParserÚNone)ÚparserÚreturnc                 C  s&   |   dd¡}|jddddddd	� d S )
NZxdistz"distributed and subprocess testingz-fz--looponfailÚ
store_trueÚ
looponfailFzdRun tests in subprocess: wait for files to be modified, then re-run failing test set until all pass.)ÚactionÚdestÚdefaultÚhelp)ZgetgroupZ
_addoption)r
   Úgroup© r   ú6E:\soccer\ml_env\Lib\site-packages\xdist/looponfail.pyÚpytest_addoption   s    úr   úpytest.Configz
int | None©Úconfigr   c                 C  s4   |   d¡r0|   dd¡}|r$t d¡‚t| ƒ dS d S )Nr   ÚusepdbFz(--pdb is incompatible with --looponfail.é   )Z	getoptionÚpytestÚ
UsageErrorÚlooponfail_main)r   r   r   r   r   Úpytest_cmdline_main(   s    

r   c                 C  sŠ   t | ƒ}|  d¡}|s t ¡ g}dd„ |D ƒ}t|ƒ}z6| ¡  |jsN|jrNq8t|j|d� |j	dd� q8W n t
y„   tƒ  Y n0 d S )NZlooponfailrootsc                 S  s   g | ]}t |ƒ‘qS r   r   )Ú.0Úrootr   r   r   Ú
<listcomp>8   ó    z#looponfail_main.<locals>.<listcomp>)ÚfailreportsÚrootdirsg       @)Úcheckinterval)ÚRemoteControlZgetinir   ÚcwdÚStatRecorderÚ	loop_onceÚfailuresÚ
wasfailingÚrepr_pytest_looponfailinfoÚwaitonchangeÚKeyboardInterruptÚprint)r   ZremotecontrolZconfig_rootsr$   Zstatrecorderr   r   r   r   3   s     

ÿr   c                   @  s|   e Zd ZU ded< dddœdd„Zddd	œd
d„Zddœdd„Zddœdd„Zddœdd„Zddœdd„Z	ddœdd„Z
dS )r&   zexecnet.GatewayÚgatewayr   r	   r   c                 C  s   || _ g | _d S ©N)r   r*   )Úselfr   r   r   r   Ú__init__K   s    zRemoteControl.__init__Úobject©Úargsr   c                 G  s,   | j jjr(d dd„ |D ƒ¡}td|ƒ d S )Nú c                 s  s   | ]}t |ƒV  qd S r1   )Ústr)r   Úxr   r   r   Ú	<genexpr>Q   r"   z&RemoteControl.trace.<locals>.<genexpr>zRemoteControl:)r   ÚoptionÚdebugÚjoinr/   )r2   r6   Úmsgr   r   r   ÚtraceO   s    
zRemoteControl.trace©r   c                 C  s
   t  d¡S )Nz!execmodel=main_thread_only//popen)ÚexecnetZmakegateway©r2   r   r   r   ÚinitgatewayT   s    zRemoteControl.initgatewayc                   s€   t | dƒrtd| j ƒ‚|  d¡ |  ¡ | _| jjt| jjt	| jj
ƒd� | _}| ¡ }tƒ ‰ dddœ‡ fdd	„}| |¡ d S )
Nr0   zalready have gateway %rzsetting up worker session)r6   Úoption_dictr8   r	   )Úsr   c                   s   ˆ j  | ¡ ˆ j  ¡  d S r1   )Ú_fileÚwriteÚflush)rE   ©Úoutr   r   rG   e   s    z"RemoteControl.setup.<locals>.write)ÚhasattrÚ
ValueErrorr0   r?   rC   Zremote_execÚinit_worker_sessionr   r6   Úvarsr;   ÚchannelÚreceiver   Zsetcallback)r2   rO   Zremote_outchannelrG   r   rI   r   ÚsetupW   s    



ýzRemoteControl.setupc                 C  sZ   t | dƒr0| j ¡ s,|  d| j¡ | j ¡  | `t | dƒrV|  d| j¡ | j ¡  | `d S )NrO   Úclosingr0   Zexiting)rK   rO   Úisclosedr?   Úcloser0   ÚexitrB   r   r   r   Úensure_teardownk   s    




zRemoteControl.ensure_teardownz!tuple[list[str], list[str], bool]c                 C  s€   zp|   d| j¡ | j | j¡ z| j ¡ W W |  ¡  S  | jjyd   t ¡ d }|   d|¡ ‚ Y n0 W |  ¡  n
|  ¡  0 d S )NZsendingé   ÚERROR)	r?   r*   rO   ÚsendrP   rV   ZRemoteErrorÚsysÚexc_info)r2   Úer   r   r   Ú
runsessionv   s    ú
zRemoteControl.runsessionc                 C  s\   |   ¡  | jot| jƒ| _|  ¡ }|\}}}|r2n&g }|D ]}||vr:| |¡ q:|| _d S r1   )rQ   r*   Úlenr+   r]   Úappend)r2   Úresultr*   ZreportsÚcollection_failedZuniq_failuresZfailurer   r   r   r)   ƒ   s    
zRemoteControl.loop_onceN)Ú__name__Ú
__module__Ú__qualname__Ú__annotations__r3   r?   rC   rQ   rV   r]   r)   r   r   r   r   r&   H   s   
r&   zSequence[str]úSequence[Path])r#   r$   r   c                 C  sh   t ƒ }| r6|jdddd� | D ]}|r|j|dd� q|jdddd� |D ]}|jd|› �dd� qJd S )Nú#ZLOOPONFAILINGT)Úbold)Úredzwaiting for changesz### Watching:   )r   ÚsepÚline)r#   r$   ÚtrÚreportÚrootdirr   r   r   r,   ’   s    r,   z'execnet.Channel'z	list[str]zdict[str, 'Any'])rO   r6   rD   r   c                 C  sÄ   dd l }dd l}| j ¡ }| d¡ |_|_|  |¡ g }|jD ]4}|r@|j 	|¡sj| 
d¡sj|j |¡}| |¡ q@||jd d …< ddlm} | |t|ƒ¡}	||	_ddlm}
 |
|	| ƒ ¡  d S )Nr   Úwz.__path_hook__)ÚConfig)ÚWorkerFailSession)ÚosrZ   r0   Z
newchannelÚmakefileÚstdoutÚstderrrY   ÚpathÚisabsÚendswithÚabspathr_   r   rp   ZfromdictargsÚlistr6   Zxdist.looponfailrq   Úmain)rO   r6   rD   rr   rZ   Z
outchannelZnewpathsÚprp   r   rq   r   r   r   rM       s"    


rM   c                   @  s~   e Zd Zddddœdd„Zdddœd	d
„Zejdddœdd„ƒZejdddœdd„ƒZejdddœdd„ƒZ	ddœdd„Z
dS )rq   r   zexecnet.Channelr	   )r   rO   r   c                 C  s8   || _ || _g | _d| _|j | ¡ d|j_d|j_d S )NF)	r   rO   Úrecorded_failuresra   ZpluginmanagerÚregisterr;   r   r   )r2   r   rO   r   r   r   r3   À   s    zWorkerFailSession.__init__r4   r5   c                 G  s"   | j jjrtd tt|ƒ¡ƒ d S )Nr7   )r   r;   r<   r/   r=   Úmapr8   )r2   r6   r   r   r   ÚDEBUGÉ   s    
zWorkerFailSession.DEBUGzpytest.SessionÚbool)Úsessionr   c                 C  sl   || _ | j| _| j j}z| | jp$d ¡}W n tjyH   | d ¡}Y n0 |j||j|d� |j	|d� dS )N)r‚   r   Úitems)r‚   T)
r‚   Úcurrent_commandÚtrailsZihookZperform_collectr   r   Zpytest_collection_modifyitemsr   Zpytest_collection_finish)r2   r‚   Úhookrƒ   r   r   r   Úpytest_collectionÍ   s    ÿz#WorkerFailSession.pytest_collectionzpytest.TestReport)rm   r   c                 C  s   |j r| j |¡ d S r1   )Úfailedr}   r_   ©r2   rm   r   r   r   Úpytest_runtest_logreportÜ   s    z*WorkerFailSession.pytest_runtest_logreportzpytest.CollectReportc                 C  s   |j r| j |¡ d| _d S )NT)rˆ   r}   r_   ra   r‰   r   r   r   Úpytest_collectreportá   s    z&WorkerFailSession.pytest_collectreportr@   c                 C  s°   |   d¡ z| j ¡ }W n ty,   Y d S 0 |   d|¡ || _| jjj| jd� g g  }}| jD ]0}| 	|j
¡ |j}tt|d|ƒƒ}| 	|¡ qb||| jf}| j |¡ d S )Nz:WORKER: received configuration, waiting for command trailsZreceived)r   Z	reprcrash)r€   rO   rP   r.   r„   r   r†   r   r}   r_   ZnodeidZlongreprr8   Úgetattrra   rY   )r2   Úcommandr…   r#   ÚrepÚlocr`   r   r   r   r{   ç   s     


zWorkerFailSession.mainN)rb   rc   rd   r3   r€   r   Úhookimplr‡   rŠ   r‹   r{   r   r   r   r   rq   ¿   s   	rq   c                   @  s`   e Zd Zdddœdd„Zdddœd	d
„Zdddœdd„Zddddœdd„Zddddœdd„ZdS )r(   rf   r	   )Úrootdirlistr   c                 C  s   || _ i | _|  ¡  d S r1   )r‘   Ú	statcacheÚcheck)r2   r‘   r   r   r   r3   û   s    zStatRecorder.__init__r   r�   )r|   r   c                 C  s    |  ¡ o|j d¡ o|jdkS )NÚ.ú.pyc)Úis_fileÚnameÚ
startswithÚsuffix©r2   r|   r   r   r   Úfil   s    zStatRecorder.filc                 C  s   |j  d¡ o| ¡ S )Nr”   )r—   r˜   Úexistsrš   r   r   r   Úrec  s    zStatRecorder.recç      ð?Úfloat)r%   r   c                 C  s    |   ¡ }|rd S t |¡ q d S r1   )r“   ÚtimeÚsleep)r2   r%   Úchangedr   r   r   r-     s    zStatRecorder.waitonchangeT)Úremovepycfilesr   c           	   
   C  sÜ   d}i }| j D ]¸}t|| j| jd�D ] }| j |d ¡}z| ¡ }W n ty\   |rXd}Y q$0 |||< |d urÀ|j|jks†|j	|j	krÄd}t
d|ƒ |rÄ|jdkrÄ| d¡}| ¡ rÄt |¡ q$d}q$q| jrÒd}|| _|S )NF)ÚfilterZrecurseTz
# MODIFIEDz.pyr•   )r‘   r   r›   r�   r’   ÚpopÚstatÚOSErrorÚst_mtimeÚst_sizer/   r™   Úwith_suffixr–   rr   Úunlink)	r2   r£   r¢   Znewstatrn   rv   ZoldstatZcurstatZpycfiler   r   r   r“     s6    


ÿ
þ

zStatRecorder.checkN)rž   )T)rb   rc   rd   r3   r›   r�   r-   r“   r   r   r   r   r(   ú   s
   r(   )Ú__doc__Ú
__future__r   Úcollections.abcr   rr   Úpathlibr   rZ   r    Útypingr   Z_pytest._ior   rA   r   Zxdist._pathr   r�   r   r   r   r&   r,   rM   rq   r(   r   r   r   r   Ú<module>   s*   	
J;