
    i`                    h    S SK Jr  S SKJ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   " S S	5      rg)
    )annotations)SequenceN)Producer)report_collection_diff)parse_tx_spec_config)WorkerControllerc                      \ rS rSrSrSSS jjr\SS j5       r\SS j5       r\SS j5       r	SS jr
      SS	 jr S       SS
 jjrSS jr      SS jrSS jrSS jrSrg)EachScheduling   a  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.
Nc                    Xl         [        [        U5      5      U l        0 U l        0 U l        / U l        0 U l        Uc  [        S5      U l	        OUR                  U l	        SU l        g )N	eachschedF)configlenr   numnodesnode2collectionnode2pending_started_removed2pendingr   logr   collection_is_completed)selfr   r   s      S/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/xdist/scheduler/each.py__init__EachScheduling.__init__   s\    089BD?A02CE;,DH}}DH',$    c                H    [        U R                  R                  5       5      $ )z%A list of all nodes in the scheduler.)listr   keys)r   s    r   nodesEachScheduling.nodes(   s     D%%**,--r   c                    U R                   (       d  gU R                  (       a  gU R                  R                  5        H  n[	        U5      S:  d  M    g   g)NF   T)r   r   r   valuesr   r   pendings     r   tests_finishedEachScheduling.tests_finished-   sG    ++  ((//1G7|q  2 r   c                X    U R                   R                  5        H  nU(       d  M    g   g)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$   s     r   has_pendingEachScheduling.has_pending8   s*     ((//1Gw 2 r   c                D    XR                   ;  d   e/ U R                   U'   g N)r   )r   nodes     r   add_nodeEachScheduling.add_nodeE   s$    ,,,,,"$$r   c                   XR                   ;   d   eU R                  (       dS  [        U5      U R                  U'   / U R                   U'   [	        U R                  5      U R
                  :  a  SU l        ggU R                  (       a  U R                   H  nUR                  R                  UR                  R                  :X  d  M3  U R                  U   nX$:w  aI  [        UUUR                  R                  UR                  R                  5      nU R                  U5          gU R                  R                  U5      nX`R                   U'     g   gg)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-   
collectiondeadnodedead_collectionmsgr%   s          r   add_node_collection"EachScheduling.add_node_collectionI   s    (((((++)-j)9D  &&(Dd#4''(DMM9/3, :"" 11##((DLL,=,==&*&:&:8&DO!44+&$,,// LLOO	 "3377AG.5%%d+ 2 #r   c                @    U R                   U   R                  U5        g r,   )r   remove)r   r-   
item_indexdurations       r   mark_test_complete!EachScheduling.mark_test_completem   s     	$&&z2r   c                    [        5       er,   NotImplementedError)r   items     r   mark_test_pending EachScheduling.mark_test_pendingr   s    !##r   c                    [        5       er,   rB   )r   r-   indicess      r   remove_pending_tests_from_node-EachScheduling.remove_pending_tests_from_nodeu   s    
 "##r   c                    U R                   R                  U5      nU(       d  g U R                  U   UR                  S5         nU(       a  X R                  U'   U$ )Nr   )r   r4   r   r   )r   r-   r%   	crashitems       r   remove_nodeEachScheduling.remove_node|   sR    ##''-((.w{{1~>	*1!!$'r   c                   U R                   (       d   eU R                  R                  5        H  u  pXR                  ;   a  M  U(       dE  [	        [        U R                  U   5      5      USS& UR                  5         UR                  5         OUR                  U5        U R                  R                  U5        M     g)a
  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%   s      r   scheduleEachScheduling.schedule   s     ++++!..446MD}}$"3t';';D'A#BC
%%'&&w/MM  & 7r   )r   r   r   r   r   r   r   r   r,   )r   zpytest.Configr   zProducer | NonereturnNone)rX   zlist[WorkerController])rX   bool)r-   r   rX   rY   )r-   r   r5   zSequence[str]rX   rY   )r   )r-   r   r=   intr>   floatrX   rY   )rD   strrX   rY   )r-   r   rH   zSequence[int]rX   rY   )r-   r   rX   z
str | None)rX   rY   )__name__
__module____qualname____firstlineno____doc__r   propertyr   r&   r)   r.   r9   r?   rE   rI   rM   rV   __static_attributes__ r   r   r
   r
      s    - . .   
 
%"$"2?"	"J JK3$3253AF3	3
$$$ $ 
	$'r   r
   )
__future__r   collections.abcr   pytestxdist.remoter   xdist.reportr   xdist.workermanager   r   r
   re   r   r   <module>rl      s&    " $  ! / 3 /K' K'r   