o
    Zh$                     @   s   d Z ddlZddlmZ ddlmZm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mZ ejdd Zejd	d
 ZdddZG dd dZdd Z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.
    NPath)DictSequence)TerminalWriter)
visit_pathc                 C   s&   |  dd}|jddddddd	 d S )
NZxdistz"distributed and subprocess testingz-fz--looponfail
store_true
looponfailFz\run tests in subprocess, wait for modified files and re-run failing test set until all pass.)actiondestdefaulthelp)ZgetgroupZ
_addoption)parsergroup r   G/var/www/html/lang_env/lib/python3.10/site-packages/xdist/looponfail.pypytest_addoption   s   
r   c                 C   s4   |  dr|  dd}|rtdt|  dS d S )Nr	   usepdbFz(--pdb is incompatible with --looponfail.   )Z	getoptionpytest
UsageErrorlooponfail_main)configr   r   r   r   pytest_cmdline_main$   s   

r   r   pytest.Configreturnc                 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 )NZlooponfailrootsc                 S   s   g | ]}t |qS r   r   ).0rootr   r   r   
<listcomp>3   s    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   .   s&   

	r   c                   @   sF   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Zdd Z	dS )r#   c                 C   s   || _ g | _d S N)r   r'   )selfr   r   r   r   __init__D   s   
zRemoteControl.__init__c                 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>J   s    z&RemoteControl.trace.<locals>.<genexpr>zRemoteControl:)r   optiondebugjoinr,   )r.   argsmsgr   r   r   traceH   s   
zRemoteControl.tracec                 C   s
   t dS )Npopen)execnetZmakegatewayr.   r   r   r   initgatewayM   s   
zRemoteControl.initgatewayNc                    s    d u rt   t| drtd| j | d |  | _| jjt| jj	t
| jjd | _}| } fdd}|| d S )Ngatewayzalready have gateway %rzsetting up worker session)r7   option_dictc                    s    j |   j   d S r-   )_filewriteflush)soutr   r   rA   ^   s   z"RemoteControl.setup.<locals>.write)r   hasattr
ValueErrorr>   r9   r=   Zremote_execinit_worker_sessionr   r7   varsr4   channelreceiveZsetcallback)r.   rE   rJ   Zremote_outchannelrA   r   rD   r   setupP   s   



zRemoteControl.setupc                 C   s^   t | dr| j s| d| j | j  | `t | dr-| d| j | j  | `d S d S )NrJ   closingr>   Zexiting)rF   rJ   isclosedr9   closer>   exitr<   r   r   r   ensure_teardownd   s   




zRemoteControl.ensure_teardownc                 C   sl   z0|  d| j | j| j z| j W W |   S  | jjy0   t d }|  d|  w |   w )NZsendingr   ERROR)	r9   r'   rJ   sendrK   rQ   ZRemoteErrorsysexc_info)r.   er   r   r   
runsessiono   s   

zRemoteControl.runsessionc                 C   s^   |    | jot| j| _|  }|\}}}|rd S g }|D ]}||vr)|| q|| _d S r-   )rL   r'   lenr(   rW   append)r.   resultr'   Zreportscollection_failedZuniq_failuresZfailurer   r   r   r&   |   s   


zRemoteControl.loop_oncer-   )
__name__
__module____qualname__r/   r9   r=   rL   rQ   rW   r&   r   r   r   r   r#   C   s    
r#   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#ZLOOPONFAILINGT)bold)redzwaiting for changesz### Watching:   )r   sepline)r    r!   trreportrootdirr   r   r   r)      s   r)   c                 C   s   dd l }dd l}| j }|d |_|_| | g }|jD ]}|r5|j	|s0|j
|}|| q ||jd d < ddlm} ||t|}	||	_ddlm}
 |
|	|   d S )Nr   w)Config)WorkerFailSession)osrT   r>   Z
newchannelmakefilestdoutstderrrS   pathisabsabspathrY   Z_pytest.configrh   Zfromdictargslistr7   Zxdist.looponfailri   main)rJ   r7   r?   rj   rT   Z
outchannelZnewpathsprh   r   ri   r   r   r   rH      s$   



rH   c                   @   sN   e Zd Zdd Zdd Zejdd Zejdd Zejd	d
 Z	dd Z
dS )ri   c                 C   s8   || _ || _g | _d| _|j|  d|j_d|j_d S )NF)	r   rJ   recorded_failuresr[   Zpluginmanagerregisterr4   r	   r   )r.   r   rJ   r   r   r   r/      s   zWorkerFailSession.__init__c                 G   s&   | j jjrtdtt| d S d S )Nr0   )r   r4   r5   r,   r6   mapr1   )r.   r7   r   r   r   DEBUG   s   
zWorkerFailSession.DEBUGc                 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)sessionr   items)rx   T)
rx   current_commandtrailsZihookZperform_collectr   r   Zpytest_collection_modifyitemsr   Zpytest_collection_finish)r.   rx   hookry   r   r   r   pytest_collection   s   z#WorkerFailSession.pytest_collectionc                 C   s   |j r| j| d S d S r-   )failedrt   rY   r.   re   r   r   r   pytest_runtest_logreport   s   z*WorkerFailSession.pytest_runtest_logreportc                 C   s    |j r| j| d| _d S d S )NT)r~   rt   rY   r[   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||| jf d S )Nz:WORKER: received configuration, waiting for command trailsZreceived)r   Z	reprcrash)rw   rJ   rK   r+   rz   r   r|   r   rt   rY   ZnodeidZlongreprr1   getattrrS   r[   )r.   commandr{   r    replocr   r   r   rr      s    


zWorkerFailSession.mainN)r\   r]   r^   r/   rw   r   hookimplr}   r   r   rr   r   r   r   r   ri      s    	


ri   c                   @   sd   e Zd Zdee ddfddZdedefddZdedefd	d
ZdddZ	ddedefddZ
dS )r%   rootdirlistr   Nc                 C   s   || _ i | _|   d S r-   )r   	statcachecheck)r.   r   r   r   r   r/      s   zStatRecorder.__init__rs   c                 C   s    |  o|jd o|jdkS )N..pyc)is_filename
startswithsuffixr.   rs   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      ?c                 C   s   	 |   }|r	d S t| qr-   )r   timesleep)r.   r"   changedr   r   r   r*      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_sizer,   r   with_suffixr   rj   unlink)	r.   r   r   Znewstatrf   rn   ZoldstatZcurstatZpycfiler   r   r   r      s:   



zStatRecorder.check)r   )T)r\   r]   r^   r   r   r/   boolr   r   r*   r   r   r   r   r   r%      s    
r%   )r   r   r   N)__doc__rj   pathlibr   typingr   r   r   rT   r   r;   Z_pytest._ior   Zxdist._pathr   r   r   r   r   r#   r)   rH   ri   r%   r   r   r   r   <module>   s(    


	H: