o
    %if'                     @  s   d 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mZ ddlZddlZddlmZ ejd*ddZejd+ddZd,ddZG dd dZd-ddZ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.
    )annotationsNPath)Any)Sequence)TerminalWriter)
visit_pathparserpytest.ParserreturnNonec                 C  s&   |  dd}|jddddddd	 d S )
N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)getgroup
_addoption)r	   group r   I/var/www/html/corbot_env/lib/python3.10/site-packages/xdist/looponfail.pypytest_addoption   s   
r   configpytest.Config
int | Nonec                 C  s4   |  dr|  dd}|rtdt|  dS d S )Nr   usepdbFz(--pdb is incompatible with --looponfail.   )	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|}z	 |  |js(|jr(qt|j|d |j	dd q t
yB   t  Y d S w )Nlooponfailrootsc                 S  s   g | ]}t |qS r   r   ).0rootr   r   r   
<listcomp>8   s    z#looponfail_main.<locals>.<listcomp>   )failreportsrootdirsg       @)checkinterval)RemoteControlgetinir   cwdStatRecorder	loop_oncefailures
wasfailingrepr_pytest_looponfailinfowaitonchangeKeyboardInterruptprint)r   remotecontrolconfig_rootsr*   statrecorderr   r   r   r"   3   s&   

	r"   c                   @  s\   e Zd ZU ded< dddZdddZdddZdddZdddZdddZ	dddZ
dS )r,   execnet.Gatewaygatewayr   r   r   r   c                 C  s   || _ g | _d S N)r   r1   )selfr   r   r   r   __init__K   s   
zRemoteControl.__init__argsobjectc                 G  s0   | j jjrddd |D }td| d S d S )N c                 s  s    | ]}t |V  qd S r<   )str)r%   xr   r   r   	<genexpr>Q   s    z&RemoteControl.trace.<locals>.<genexpr>zRemoteControl:)r   optiondebugjoinr6   )r=   r?   msgr   r   r   traceO   s   
zRemoteControl.tracec                 C  s
   t dS )Nz!execmodel=main_thread_only//popen)execnetmakegatewayr=   r   r   r   initgatewayT   s   
zRemoteControl.initgatewayc                   sz   t | drtd| j | d |  | _| jjt| jjt	| jj
d | _}| }t  d fd	d
}|| d S )Nr;   zalready have gateway %rzsetting up worker session)r?   option_dictsrB   r   r   c                   s    j |   j   d S r<   )_filewriteflush)rO   outr   r   rQ   e   s   z"RemoteControl.setup.<locals>.write)rO   rB   r   r   )hasattr
ValueErrorr;   rI   rM   remote_execinit_worker_sessionr   r?   varsrE   channelreceiver   setcallback)r=   rZ   remote_outchannelrQ   r   rS   r   setupW   s   



zRemoteControl.setupc                 C  s^   t | dr| j s| d| j | j  | `t | dr-| d| j | j  | `d S d S )NrZ   closingr;   exiting)rU   rZ   isclosedrI   closer;   exitrL   r   r   r   ensure_teardownk   s   




zRemoteControl.ensure_teardown!tuple[list[str], list[str], bool]c                 C  sl   z0|  d| j | j| j z| j W W |   S  | jjy0   t d }|  d|  w |   w )Nsendingr(   ERROR)	rI   r1   rZ   sendr[   rd   RemoteErrorsysexc_info)r=   er   r   r   
runsessionv   s   

zRemoteControl.runsessionc                 C  s^   |    | jot| j| _|  }|\}}}|rd S g }|D ]}||vr)|| q|| _d S r<   )r^   r1   lenr2   rm   append)r=   resultr1   reportscollection_faileduniq_failuresfailurer   r   r   r0      s   


zRemoteControl.loop_onceNr   r   r   r   r?   r@   r   r   )r   r:   r   r   )r   re   )__name__
__module____qualname____annotations__r>   rI   rM   r^   rd   rm   r0   r   r   r   r   r,   H   s   
 





r,   r)   Sequence[str]r*   Sequence[Path]c                 C  sh   t  }| r|jdddd | D ]}|r|j|dd q|jdddd |D ]}|jd| dd q%d S )N#LOOPONFAILINGT)bold)redzwaiting for changesz### Watching:   )r   sepline)r)   r*   trreportrootdirr   r   r   r3      s   r3   rZ   'execnet.Channel'r?   	list[str]rN   dict[str, 'Any']c                 C  s   dd l }dd l}| j }|d |_|_| | g }|jD ]}|r:|j	|s5|
ds5|j|}|| q ||jd d < ddlm} ||t|}	||	_ddlm}
 |
|	|   d S )Nr   wz.__path_hook__)Config)WorkerFailSession)osrj   r;   
newchannelmakefilestdoutstderrrh   pathisabsendswithabspathro   r    r   fromdictargslistr?   xdist.looponfailr   main)rZ   r?   rN   r   rj   
outchannelnewpathspr   r   r   r   r   r   rX      s$   



rX   c                   @  sZ   e Zd ZdddZdddZejdddZejdddZejd ddZ	d!ddZ
dS )"r   r   r   rZ   execnet.Channelr   r   c                 C  s8   || _ || _g | _d| _|j|  d|j_d|j_d S )NF)	r   rZ   recorded_failuresrr   pluginmanagerregisterrE   r   r   )r=   r   rZ   r   r   r   r>      s   zWorkerFailSession.__init__r?   r@   c                 G  s&   | j jjrtdtt| d S d S )NrA   )r   rE   rF   r6   rG   maprB   )r=   r?   r   r   r   DEBUG   s   
zWorkerFailSession.DEBUGsessionpytest.Sessionboolc                 C  sl   || _ | j| _| j j}z
|| jpd }W n tjy$   |d }Y nw |j||j|d |j	|d dS )N)r   r   items)r   T)
r   current_commandtrailsihookperform_collectr    r!   pytest_collection_modifyitemsr   pytest_collection_finish)r=   r   hookr   r   r   r   pytest_collection   s   z#WorkerFailSession.pytest_collectionr   pytest.TestReportc                 C  s   |j r| j| d S d S r<   )failedr   ro   r=   r   r   r   r   pytest_runtest_logreport   s   z*WorkerFailSession.pytest_runtest_logreportpytest.CollectReportc                 C  s    |j r| j| d| _d S d S )NT)r   r   ro   rr   r   r   r   r   pytest_collectreport   s   
z&WorkerFailSession.pytest_collectreportc                 C  s   |  d z| j }W n
 ty   Y d S w |  d| || _| jjj| jd g g }}| jD ]}|	|j
 |j}tt|d|}|	| q1||| jf}| j| d S )Nz:WORKER: received configuration, waiting for command trailsreceived)r   	reprcrash)r   rZ   r[   r5   r   r   r   r#   r   ro   nodeidlongreprrB   getattrrr   rh   )r=   commandr   r)   replocrp   r   r   r   r      s"   


zWorkerFailSession.mainN)r   r   rZ   r   r   r   rv   )r   r   r   r   )r   r   r   r   )r   r   r   r   rw   )rx   ry   rz   r>   r   r    hookimplr   r   r   r   r   r   r   r   r      s    

	r   c                   @  sB   e Zd ZdddZdd
dZdddZddddZddddZdS )r/   rootdirlistr}   r   r   c                 C  s   || _ i | _|   d S r<   )r   	statcachecheck)r=   r   r   r   r   r>      s   zStatRecorder.__init__r   r   r   c                 C  s    |  o|jd o|jdkS )N..pyc)is_filename
startswithsuffixr=   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      ?r+   floatc                 C  s   	 |   }|r	d S t| qr<   )r   timesleep)r=   r+   changedr   r   r   r4     s   
zStatRecorder.waitonchangeTremovepycfilesc           	   
   C  s   d}i }| j D ]\}t|| j| jdD ]P}| j|d }z| }W n ty.   |r,d}Y qw |||< |d ur`|j|jksC|j	|j	kr_d}t
d| |r_|jdkr_|d}| r_t| qd}qq| jrid}|| _|S )NF)filterrecurseTz
# MODIFIEDz.pyr   )r   r   r   r   r   popstatOSErrorst_mtimest_sizer6   r   with_suffixr   r   unlink)	r=   r   r   newstatr   r   oldstatcurstatpycfiler   r   r   r     s:   



zStatRecorder.checkN)r   r}   r   r   )r   r   r   r   )r   )r+   r   r   r   )T)r   r   r   r   )rx   ry   rz   r>   r   r   r4   r   r   r   r   r   r/      s    


r/   )r	   r
   r   r   )r   r   r   r   ru   )r)   r|   r*   r}   r   r   )rZ   r   r?   r   rN   r   r   r   )__doc__
__future__r   r   pathlibr   rj   r   typingr   r   _pytest._ior   rJ   r    xdist._pathr   r   r   r#   r"   r,   r3   rX   r   r/   r   r   r   r   <module>   s,    	


J
;