o
    %ifQ                     @  sb   d dl mZ d dlmZ d dlZd dlmZ d dlmZ d dl	m
Z
 d dl	mZ G dd	 d	ZdS )
    )annotations)SequenceN)Producer)report_collection_diff)parse_spec_config)WorkerControllerc                   @  s   e Zd ZdZd/d0d	d
Zed1ddZed2ddZed2ddZd3ddZ	d4ddZ
	d5d6d d!Zd7d$d%Zd8d(d)Zd9d+d,Zd:d-d.ZdS );EachSchedulinga#  Implement scheduling of test items on all nodes.

    If a node gets added after the test run is started then it is
    assumed to replace a node which got removed before it finished
    its collection.  In this case it will only be used if a node
    with the same spec got removed earlier.

    Any nodes added after the run is started will only get items
    assigned if a node with a matching spec was removed before it
    finished all its pending items.  The new node will then be
    assigned the remaining items from the removed node.
    Nconfigpytest.ConfiglogProducer | NonereturnNonec                 C  sR   || _ tt|| _i | _i | _g | _i | _|d u r td| _	n|j
| _	d| _d S )N	eachschedF)r	   lenr   numnodesnode2collectionnode2pending_started_removed2pendingr   r   r   collection_is_completed)selfr	   r    r   M/var/www/html/corbot_env/lib/python3.10/site-packages/xdist/scheduler/each.py__init__   s   
zEachScheduling.__init__list[WorkerController]c                 C  s   t | j S )z%A list of all nodes in the scheduler.)listr   keys)r   r   r   r   nodes(   s   zEachScheduling.nodesboolc                 C  s:   | j sdS | jr
dS | j D ]}t|dkr dS qdS )NF   T)r   r   r   valuesr   r   pendingr   r   r   tests_finished-   s   zEachScheduling.tests_finishedc                 C  s   | j  D ]}|r dS qdS )zReturn True if there are pending test items.

        This indicates that collection has finished and nodes are
        still processing test items, so this can be thought of as
        "the scheduler is active".
        TF)r   r!   r"   r   r   r   has_pending8   s
   zEachScheduling.has_pendingnoder   c                 C  s   || j vsJ g | j |< d S N)r   )r   r&   r   r   r   add_nodeE   s   zEachScheduling.add_node
collectionSequence[str]c                 C  s   || j v sJ | js%t|| j|< g | j |< t| j| jkr#d| _dS dS | jr`| jD ]6}|jj|jjkr_| j| }||krQt	|||jj
|jj
}| |  dS | j|}|| j |<  dS q+dS dS )a  Add the collected test items from a node.

        Collection is complete once all nodes have submitted their
        collection.  In this case its pending list is set to an empty
        list.  When the collection is already completed this
        submission is from a node which was restarted to replace a
        dead node.  In this case we already assign the pending items
        here.  In either case ``.schedule()`` will instruct the
        node to start running the required tests.
        TN)r   r   r   r   r   r   r   gatewayspecr   idr   pop)r   r&   r)   deadnodedead_collectionmsgr#   r   r   r   add_node_collectionI   s4   





z"EachScheduling.add_node_collectionr   
item_indexintdurationfloatc                 C  s   | j | | d S r'   )r   remove)r   r&   r3   r5   r   r   r   mark_test_completem   s   z!EachScheduling.mark_test_completeitemstrc                 C     t  r'   NotImplementedError)r   r9   r   r   r   mark_test_pendingr   s   z EachScheduling.mark_test_pendingindicesSequence[int]c                 C  r;   r'   r<   )r   r&   r?   r   r   r   remove_pending_tests_from_nodeu   s   z-EachScheduling.remove_pending_tests_from_node
str | Nonec                 C  s:   | j |}|s
d S | j| |d }|r|| j|< |S )Nr   )r   r.   r   r   )r   r&   r#   	crashitemr   r   r   remove_node|   s   
zEachScheduling.remove_nodec                 C  st   | j sJ | j D ]-\}}|| jv rq
|s,tt| j| |dd< |  |  n|	| | j
| q
dS )a2  Schedule the test items on the nodes.

        If the node's pending list is empty it is a new node which
        needs to run all the tests.  If the pending list is already
        populated (by ``.add_node_collection()``) then it replaces a
        dead node and we only need to run those tests.
        N)r   r   itemsr   ranger   r   send_runtest_allshutdownsend_runtest_someappend)r   r&   r#   r   r   r   schedule   s   



zEachScheduling.scheduler'   )r	   r
   r   r   r   r   )r   r   )r   r   )r&   r   r   r   )r&   r   r)   r*   r   r   )r   )r&   r   r3   r4   r5   r6   r   r   )r9   r:   r   r   )r&   r   r?   r@   r   r   )r&   r   r   rB   )r   r   )__name__
__module____qualname____doc__r   propertyr   r$   r%   r(   r2   r8   r>   rA   rD   rK   r   r   r   r   r      s"    


%



r   )
__future__r   typingr   pytestxdist.remoter   xdist.reportr   xdist.workermanager   r   r   r   r   r   r   <module>   s    