
    E0j                     :   d dl Zd dlmc mZ d dlZd dlZd dlm	Z	m
Z
 d dlmZ d dlmZmZ erd dlmZ  G d de          Z G d d	e	          Z G d
 de          Z G d de          Z	 	 	 	 	 	 ddZdddefdZ	 	 	 	 	 	 ddZ G d dej                  ZdS )    N)ABCabstractmethod)
itemgetter)TYPE_CHECKING
NamedTuple)nodesc                   .    e Zd ZU ded<   ded<   eed<   dS )	TestGrouplist[nodes.Item]selected
deselecteddurationN)__name__
__module____qualname____annotations__float     _/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/pytest_split/algorithms.pyr
   r
      s1             """"OOOOOr   r
   c            	       V    e Zd ZdZededdddddfd	            Zdefd
Zdede	fdZ
dS )AlgorithmBasez6Abstract base class for the algorithm implementations.splitsitemsr   	durationsdict[str, float]returnlist[TestGroup]c                     d S Nr   )selfr   r   r   s       r   __call__zAlgorithmBase.__call__   s	     	r   c                 4    t          | j        j                  S r    )hash	__class__r   )r!   s    r   __hash__zAlgorithmBase.__hash__   s    DN+,,,r   otherc                 n    t          |t                    st          S | j        j        |j        j        k    S r    )
isinstancer   NotImplementedr%   r   )r!   r'   s     r   __eq__zAlgorithmBase.__eq__   s/    %// 	"!!~&%/*BBBr   N)r   r   r   __doc__r   intr"   r&   objectboolr+   r   r   r   r   r      s        @@"4AS	   ^
-# - - - -CF Ct C C C C C Cr   r   c                   *    e Zd ZdZdeddddddfd	Zd
S )LeastDurationAlgorithma  
    Split tests into groups by runtime.
    It walks the test items, starting with the test with largest duration.
    It assigns the test with the largest runtime to the group with the smallest duration sum.

    The algorithm sorts the items by their duration. Since the sorting algorithm is stable, ties will be broken by
    maintaining the original order of items. It is therefore important that the order of items be identical on all nodes
    that use this plugin. Due to issue #25 this might not always be the case.

    :param splits: How many groups we're splitting in.
    :param items: Test items passed down by Pytest.
    :param durations: Our cached test runtimes. Assumes contains timings only of relevant tests
    :return:
        List of groups
    r   r   r   r   r   r   r   c                    t          ||          }d t          |          D             }t          |d           }t          |d d          }d t          |          D             }d t          |          D             }d	 t          |          D             }	d
 t          |          D             }
t	          j        |
           |D ]\  }}}t	          j        |
          \  }}||z   }||                             ||f           ||	|<   t          |          D ]#}||k    r||                             |           $t	          j        |
||f           g }t          |          D ]W}d t          ||         d           D             }t          |||         |	|                   }|                    |           X|S )Nc                 "    g | ]\  }}g ||R S r   r   ).0itups      r   
<listcomp>z3LeastDurationAlgorithm.__call__.<locals>.<listcomp>:   s3     (
 (
 (
 !SIcI1II(
 (
 (
r   c                 ,    t          | d                   S )Nr   )strr6   s    r   <lambda>z1LeastDurationAlgorithm.__call__.<locals>.<lambda>@   s    #c!f++ r   )keyc                     | d         S N   r   r:   s    r   r;   z1LeastDurationAlgorithm.__call__.<locals>.<lambda>E   s
    #a& r   T)r<   reversec                     g | ]}g S r   r   r4   _s     r   r7   z3LeastDurationAlgorithm.__call__.<locals>.<listcomp>H   s    7R7R7Rq7R7R7Rr   c                     g | ]}g S r   r   rB   s     r   r7   z3LeastDurationAlgorithm.__call__.<locals>.<listcomp>I       -H-H-HQb-H-H-Hr   c                     g | ]}d S r   r   rB   s     r   r7   z3LeastDurationAlgorithm.__call__.<locals>.<listcomp>J        : : :q : : :r   c                     g | ]}d |fS rG   r   r4   r5   s     r   r7   z3LeastDurationAlgorithm.__call__.<locals>.<listcomp>M   s    (G(G(GA!Q(G(G(Gr   c                     g | ]\  }}|S r   r   )r4   itemoriginal_indexs      r   r7   z3LeastDurationAlgorithm.__call__.<locals>.<listcomp>b   s,       (D.   r   c                     | d         S r>   r   r:   s    r   r;   z1LeastDurationAlgorithm.__call__.<locals>.<lambda>d   s    PSTUPV r   r   r   r   )
_get_items_with_durations	enumeratesortedrangeheapqheapifyheappopappendheappushr
   )r!   r   r   r   items_with_durationsitems_with_durations_indexedsorted_items_with_durationsr   r   r   heaprL   item_durationrM   summed_durations	group_idxnew_group_durationsr5   groupssgroups                        r   r"   zLeastDurationAlgorithm.__call__4   s<     9	JJ(
 (
$-.B$C$C(
 (
 (
$
 (.(.E.E(
 (
 (
$
 '-(.@.@$'
 '
 '
# 8S7RE&MM7R7R7R-H-H%---H-H-H
 : :E&MM : : : )H(Gv(G(G(Gd3N 	C 	C/D-*/-*=*='i"2]"B Y&&n'=>>>"5HY6]] / /	>>qM((... N4"5y!ABBBBv 
	! 
	!A ,28A;DVDV,W,W,W  A z!}x{  E MM%    r   Nr   r   r   r,   r-   r"   r   r   r   r1   r1   #   sR          66"46AS6	6 6 6 6 6 6r   r1   c                   *    e Zd ZdZdeddddddfd	Zd
S )DurationBasedChunksAlgorithma  
    Split tests into groups by runtime.
    Ensures tests are split into non-overlapping groups.
    The original list of test items is split into groups by finding boundary indices i_0, i_1, i_2
    and creating group_1 = items[0:i_0], group_2 = items[i_0, i_1], group_3 = items[i_1, i_2], ...

    :param splits: How many groups we're splitting in.
    :param items: Test items passed down by Pytest.
    :param durations: Our cached test runtimes. Assumes contains timings only of relevant tests
    :return: List of TestGroup
    r   r   r   r   r   r   r   c                 D  
 t          ||          }t          t          t          d          |                    |z  }d t	          |          D             d t	          |          D             
d t	          |          D             d}|D ]t\  }}|         |k    r|dz  }|                             |           t	          |          D ]#}	|	|k    r
|	                             |           $|xx         |z  cc<   u
fdt	          |          D             S )Nr?   c                     g | ]}g S r   r   rJ   s     r   r7   z9DurationBasedChunksAlgorithm.__call__.<locals>.<listcomp>   s    +F+F+F1B+F+F+Fr   c                     g | ]}g S r   r   rJ   s     r   r7   z9DurationBasedChunksAlgorithm.__call__.<locals>.<listcomp>   rE   r   c                     g | ]}d S rG   r   rJ   s     r   r7   z9DurationBasedChunksAlgorithm.__call__.<locals>.<listcomp>   rH   r   r   c                 X    g | ]&}t          |         |         |                    'S )rO   )r
   )r4   r5   r   r   r   s     r   r7   z9DurationBasedChunksAlgorithm.__call__.<locals>.<listcomp>   sN     
 
 
  !!ARS  
 
 
r   )rP   summapr   rS   rW   )r!   r   r   r   rY   time_per_groupr_   rL   r]   r5   r   r   r   s             @@@r   r"   z%DurationBasedChunksAlgorithm.__call__z   sc     9	JJSA0DEEFFO+F+Ff+F+F+F-H-H%---H-H-H
 : :E&MM : : :	#7 	1 	1D-	"n44Q	Y&&t,,,6]] / /	>>qM((...Y=0
 
 
 
 
 
 6]]	
 
 
 	
r   Nrd   r   r   r   rf   rf   m   sR        
 


"4
AS
	
 
 
 
 
 
r   rf   r   r   r   r   r   list[tuple[nodes.Item, float]]c                 f    t          |           t                    fd| D             }|S )Nc                 J    g | ]}|                     |j                  f S r   )getnodeid)r4   rL   avg_duration_per_testr   s     r   r7   z-_get_items_with_durations.<locals>.<listcomp>   s<       FJy}}T[*?@@A  r   )_remove_irrelevant_durations_get_avg_duration_per_test)r   r   rY   rt   s    ` @r   rP   rP      sY     -UI>>I6yAA    NS    r   c                 r    | r2t          |                                           t          |           z  }nd}|S r>   )rl   valueslen)r   rt   s     r   rv   rv      s@     " #I$4$4$6$6 7 7#i.. H !"  r   c                 <    d | D             }fd|D             S )Nc                     g | ]	}|j         
S r   )rs   )r4   rL   s     r   r7   z0_remove_irrelevant_durations.<locals>.<listcomp>   s    ......r   c                 *    i | ]}|v ||         S r   r   )r4   namer   s     r   
<dictcomp>z0_remove_irrelevant_durations.<locals>.<dictcomp>   s)    QQQ4ty?P?Py?P?P?Pr   r   )r   r   test_idss    ` r   ru   ru      s7     /....HQQQQ8QQQIr   c                   N    e Zd Z e            Z e            Zedd            ZdS )
Algorithmsr   	list[str]c                  $    d t           D             S )Nc                     g | ]	}|j         
S r   )r}   )r4   xs     r   r7   z$Algorithms.names.<locals>.<listcomp>   s    +++1+++r   )r   r   r   r   nameszAlgorithms.names   s    ++
++++r   N)r   r   )	r   r   r   rf   duration_based_chunksr1   least_durationstaticmethodr   r   r   r   r   r      sO        88::++--N, , , \, , ,r   r   )r   r   r   r   r   ro   )r   r   r   r   r   r   )builtins@py_builtins_pytest.assertion.rewrite	assertionrewrite
@pytest_arenumrT   abcr   r   operatorr   typingr   r   _pytestr   r
   r   r1   rf   rP   r   rv   ru   Enumr   r   r   r   <module>r      s                  # # # # # # # #       , , , , , , , ,     
   C C C C CC C C C$G G G G G] G G GT'
 '
 '
 '
 '
= '
 '
 '
T  *< %       !*< ! ! ! ! !*<   , , , , , , , , , ,r   