
    Q3jRN                     "   d dl mZ d dlZd dlZd dlmZmZ d dlm	Z	m
Z
mZ d dlmZmZmZmZmZmZmZmZmZmZmZ 	 d%dZd Zd Zd	 Zd
 Zd Zd Zd Zd Z d Z!ejD                  jG                  deeeg      d        Z$d Z%d Z&ejD                  jG                  deeg      d        Z'ejD                  jG                  dddg      d        Z(ejD                  jG                  dddg      d        Z)d Z*d Z+d Z,d Z-d Z.d  Z/d! Z0d" Z1d# Z2d$ Z3y)&    )partialN)CallbackSupportMixinwith_callbacks)CallbackContext_from_reconstruction_attributesget_context_path)MaxIterEstimatorMetaEstimatorNoCallbackEstimatorNoSubtaskEstimatorNotRequiredKwargsCallbackNotValidHookCallbackParentFitEstimatorRecordingAutoPropagatedCallbackRecordingCallbackStopFitCallbackThirdPartyEstimatorc                 4    t        j                  | ||||      S )zHelper function to create a callback context with default values.

    To be used instead of estimator._init_callback_context in tests that only check
    the context tree (without callbacks).
    )r   _from_estimator)	estimator	task_nametask_idmax_subtaskssequential_subtaskss        Y/DATA/.local/lib/python3.12/site-packages/sklearn/callback/tests/test_callback_context.py_make_callback_ctxr      s#     **9g|5H     c                     t               } t               }t               }t        |      }|j	                  | |       t        |d      rJ t        |      }|j                  |      5  t        |d      sJ | |j                  vsJ ||j                  v sJ 	 ddd       t        |d      rJ t        |d      rJ y# 1 sw Y   &xY w)z9Check that only auto-propagated callbacks are propagated._skl_callbacks_parent_callback_ctxN)	r   r   r	   r
   set_callbackshasattrr   propagate_callback_contextr   )not_propagated_callbackpropagated_callbackr   metaestimatorcallback_ctxs        r   .test_propagate_callback_context_autopropagatedr(   +   s    /19; "I!),M 79LMy"2333%m4L		0	0	;y"8999&i.F.FFFF"i&>&>>>> 
<
 y"2333y"89999 
<	;s   &/B;;Cc                     t               } t               j                  |       }t               }t	        |      }|j                  |       |j
                  | gk(  sJ t        |      }|j                  |      5  t        |d      sJ | |j
                  v sJ ||j
                  v sJ 	 ddd       |j
                  | gk(  sJ t        |d      rJ y# 1 sw Y   *xY w)z9Check that only propagated callbacks are removed on exit.r    N)	r   r	   r!   r   r
   r   r   r#   r"   )est_callbackr   meta_est_callbackr&   r'   s        r   (test_propagate_callback_context_clean_upr,   @   s    $&L "00>I79!),M 12##~555%m4L		0	0	;y"8999y77777 I$<$<<<< 
<
 ##~555y"89999 
<	;s   8/CCc                     t               } t        |       }t        |      }t        |j                        dk(  sJ |j                  |       5  t        | d      sJ t        |d      rJ t        | d      rJ 	 ddd       t        | d      rJ t        | d      rJ t        |d      rJ t        |d      rJ y# 1 sw Y   BxY w)z<Check that no callback is propagated if there's no callback.r   r    r   N)r	   r
   r   len
_callbacksr#   r"   )r   r&   r'   s      r   +test_propagate_callback_context_no_callbackr0   U   s     "I!),M%m4L|&&'1,,,		0	0	;y"8999=*:;;;9&67777 
<
 y"2333y"8999}&6777}&<==== 
<	;s   +B99Cc                      t               } | j                  t                      t        |       }d}t	        j
                  t        |      5  |j                  dd       ddd       y# 1 sw Y   yxY w)zrCheck that it's not possible to set an auto-propagated callback on the
    sub-estimator of a meta-estimator.
    r   zJsub-estimator .*of a meta-estimator .*can't have auto-propagated callbacksmatchN)Xy)r	   r!   r   r
   pytestraises	TypeErrorfit)r   meta_estimatorr4   s      r   test_auto_propagated_callbacksr<   h   sb     !"I;=>"Y7N 	V 
 
y	.TT* 
/	.	.s   A**A3c                     t               }t        || d      }t        |       D ]8  }|j                  d||      }t        |      D ]  }|j                  d      } : |S )zGHelper function to create a tree of tasks with a context for each task.Fr   r   
child task)r   r   r   zgrandchild taskr   )r	   r   range
subcontext)
n_childrenn_grandchildrenr   rootichildj
grandchilds           r   _make_task_treerJ   w   st     "I
D :"(   
 'A))4E)FJ (  Kr   c                  T   t        dd      } | j                  J t        t        |             dk(  sJ t        | j                        dk(  sJ | j                  j                         D ]  }|j                  | u sJ t        t        |            dk(  sJ t        |j                        dk(  sJ |j                  j                         D ]E  }|j                  |u sJ t        t        |            dk(  sJ t        |j                        dk(  rEJ   | D ]&  }t        |j                        |j                  k(  r&J  t        j                  t        j                  g d            }t        d	 | D              }||k(  sJ t        d
 | D              sJ t        d | D              sJ y)z,Check that the task tree is correctly built.      )rC   rD   N      r   )rN   rL   rM   c              3       K   | ]  }d   yw)rN   N ).0_s     r   	<genexpr>z!test_task_tree.<locals>.<genexpr>   s     )DqDs   c              3   8   K   | ]  }|j                   d u   y wN)source_estimator_namerR   nodes     r   rT   z!test_task_tree.<locals>.<genexpr>   s     Cddt))T1d   c              3   8   K   | ]  }|j                   d u   y wrV   )source_task_namerX   s     r   rT   z!test_task_tree.<locals>.<genexpr>   s     >t$$,rZ   )rJ   parentr.   r   _children_mapvaluesr   npsumcumprodall)rE   rG   rI   rY   expected_n_nodesactual_n_nodess         r   test_task_treerf      s   a;D;;%&!+++t!!"a'''##**,||t####E*+q0005&&'1,,,--446J$$---'
34999z//0A555 7 - 4%%&$*;*;;;;  vvbjj34)D))N---- CdCCCC>>>>>r   c                     t               } t        | dd      }t        | dd      }|j                  |       |j                  dk(  sJ t	        |j
                        dk(  sJ |j                  dk(  sJ t        | dd      }t        j                  t        d	      5  |j                  |       d
d
d
       d|_        |j                  |       t	        |j
                        dk(  sJ t        | dd      }t        j                  t        d	      5  |j                  |       d
d
d
       y
# 1 sw Y   xY w# 1 sw Y   y
xY w)z)Sanity check for the `_add_child` method.rO   Fr>   r?   r   r   r   rN   z6Callback context .* already has a child with task_id=0r3   Nz$Cannot add child to callback context)
r	   r   
_add_childr   r.   r^   r   r7   r8   
ValueError)r   rE   first_childsecond_childthird_childs        r   test_add_childrn      s#    "IiaUSD$Y,PQRKOOK !!!t!!"a'''!### &i<QRSL	S
 	%

 LOOL!t!!"a''' %Y,PQRK	z)P	Q$ 
R	Q
 
 
R	Qs   D-D9-D69Ec                  &   t               } t        |       }t        |d      }|j                  ddd      }t        | dd	      }|j	                  |       |j
                  |u sJ |j                  |j                  k(  sJ ||j                  j                         vsJ ||j                  j                         v sJ |j                  dk(  sJ |j                  rJ |j                  |j                  k(  sJ |j                  |j                  k(  sJ y)
z*Sanity check for the `_merge_with` method.Nr   rG   r   T)r   r   r   rO   Fr>   )r	   r
   r   rB   _merge_withr]   r   r^   r_   r   r   r\   r   rW   estimator_name)r   r;   
outer_rootouter_child
inner_roots        r   test_merge_withrv      s$    "I"9-N#NFJ ''t ( K $uJ ;'
***!4!4444j66==????1188:::: ""a'''---- &&+*?*????++{/I/IIIIr   c                     t               } t        |       }t        |       }t        |d      }|j                  d       t	        j
                  t        d      5  |j                  |       ddd       y# 1 sw Y   yxY w)z8Check that merging with a non-leaf node raises an error.Nrp   rG   r@   zCannot merge callback contextr3   )r	   r   r
   rB   r7   r8   rj   rq   )r   ru   r;   rs   s       r   test_merge_with_error_not_leafrx      sg     "I#I.J"9-N#NFJ G,	z)I	Jz* 
K	J	Js   A66A?estimator_classc                 J     |        j                         }t        |d      rJ y)zBCheck that the _callback_fit_ctx attribute gets removed after fit._callback_fit_ctxN)r:   r"   )ry   r   s     r   #test_callback_ctx_removed_after_fitr|      s)    
  !%%'Iy"56666r   c                      t               } t        |       }|j                  t                      t	        j
                  t        d      5  |j                          ddd       y# 1 sw Y   yxY w)zCheck that meta estimators can have sub estimators without callback support.

    No error is raised when the sub-estimator does not support callbacks. If callbacks
    would be propagated, a warning is raised instead.
    =The estimator NoCallbackEstimator does not support callbacks.r3   N)r   r
   r!   r   r7   warnsUserWarningr:   )r   r;   s     r   (test_inner_estimator_no_callback_supportr      sX     $%I"9-N  !@!BC	M
 		
 
 
s   
A$$A-c                  j    t               } | j                  t                      | j                          y)zCheck that callback support works for an estimator without subtasks.

    This test is about verifying that an estimator that does not call its callback
    context's `call_on_fit_task_end` does not cause a problem.
    N)r   r!   r   r:   r2   s    r   test_estimator_without_subtaskr     s'     #$I-/0MMOr   Callbackc                 $   d} |        }t        |      j                  |      j                          |j                  d      dk(  sJ |j                  d      d|z   k(  sJ |j                  d      d|z   k(  sJ |j                  d      dk(  sJ y)	zCheck the number of callback hook calls in a regular estimator.

    For a regular estimator, it does not depend whether it's an autopropagated callback
    or not.
    
   max_itersetuprN   on_fit_task_beginon_fit_task_endteardownN)r	   r!   r:   count_hooks)r   r   callbacks      r   test_callback_hooks_calledr     s     HzHh'55h?CCE(A--- 34HDDD 12a(lBBB
+q000r   n_jobsrN   rO   c                    d\  }}}t               }t        t        |      |||       j                  |      j	                          |j                  d      dk(  sJ t        j                  t        j                  d|||g            }|j                  d      |k(  sJ |j                  d      |k(  sJ |j                  d      dk(  sJ y	)
a  Check the number of callback hook calls in a meta-estimator.

    For an auto-propagated callback, setup and teardown are called only once,
    by the meta-estimator. To count the number of task ends, we need to aggregate the
    number of tasks from all the levels of the global task tree (which contains the
    task tree of the meta-estimator and the task trees of each sub-estimator).
    rO   rL   rM   r   n_outern_innerr   r   rN   r   r   r   N)	r   r
   r	   r!   r:   r   r`   ra   rb   )r   r   r   r   r   expected_n_taskss         r   8test_meta_estimator_autopropagated_callback_hooks_calledr   /  s     ")GWh.0H(+	
 mHcce(A---vvbjj!Wgx)HIJ 348HHHH 126FFFF
+q000r   c                 f   d\  }}}t               }t        |      j                  |      }t        ||||       j	                          ||z  }|j                  d      |k(  sJ |j                  d      |d|z   z  k(  sJ |j                  d      |d|z   z  k(  sJ |j                  d      |k(  sJ y	)
a  Check the number of callback hook calls in a meta-estimator.

    For a non auto-propagated callback, setup and teardown are called once for
    each fit of the sub-estimator. The number of task ends is the sum of the number of
    task ends from all the sub-estimators.
    r   r   r   r   r   rN   r   r   N)r   r	   r!   r
   r:   r   )r   r   r   r   r   estn_fitss          r   )test_meta_estimator_callback_hooks_calledr   I  s     ")GWh "H
H
-
;
;H
EC#wGKKMwF(F222 34!h,8OOOO 12fH6MMMM
+v555r   c                     d\  } }t               }t        t               | |      j                  |      }t	        j
                  t        d      5  |j                          ddd       |j                  d      dk(  sJ t        j                  t        j                  d| |g            }|j                  d      |k(  sJ |j                  d	      |k(  sJ |j                  d
      dk(  sJ y# 1 sw Y   xY w)zCheck the number of hook calls when the sub-estimator doesn't support callbacks.

    The number of task begins and ends is just the number of nodes in the context tree
    of the meta-estimator.
    )rO   rL   )r   r   r~   r3   Nr   rN   r   r   r   )r   r
   r   r!   r7   r   r   r:   r   r`   ra   rb   )r   r   r   r;   r   s        r   6test_autopropagation_to_callback_agnostic_subestimatorr   ^  s     GW.0H"wmH  
M
 		
 (A---vvbjj!Wg)>?@ 348HHHH 126FFFF
+q000
 
s   C--C6c                      t               } | j                  t                     j                         }d}t	        j
                  t        |      5  |j                  | dd       ddd       y# 1 sw Y   yxY w)zLCheck that a callback with invalid kwargs in its signatures raises an error.z6on_fit_task_begin .* has parameters that are not validr3   rN   rO   )r   r5   r6   N)r	   r!   r   _init_callback_contextr7   r8   r9   call_on_fit_task_begin)r   contextmsgs      r   $test_hook_calling_invalid_kwargs_outr   y  s[     "I%%&:&<=TTVG
CC	y	,&&a1&E 
-	,	,s   A--A6c                  &   t               } | j                  t                     j                         }|j	                  |       }|du sJ | j                  t               t                      | j                         j	                  |       }|du sJ y)z)Check the return value of the hook calls.r2   FTN)r	   r!   r   r   call_on_fit_task_endr   )r   r   results      r   test_hook_calling_return_valuer     s     "I%%&7&9:QQSG))I)>FU??-/1BC--/DD E F T>>r   c                     dddfd} t               }t               }|j                  |      j                         }|j	                  |t        | d      t        | d             d   dk(  sJ d   dk(  sJ ddi|j                  t               t                      |j                         }|j                  |t        | d             d   dk(  sJ y	)
zCheck lazy evaluation of kwargs.

    kwargs are not evaluated if no callback uses them.
    They are evaluated only once and passed to all callbacks that use them.
    r   )r5   metadatac                      | xx   dz  cc<   y)NrN   rQ   )keyeval_countss    r   
eval_kwargz5test_hook_calling_lazy_evaluation.<locals>.eval_kwarg  s    CAr   r5   r   )r   r5   r   rN   )r   r5   N)r	   r   r!   r   r   r   r   r   )r   r   r   r   r   s       @r   !test_hook_calling_lazy_evaluationr     s     q)K
 !"I(*H%%h/FFHG  
*c
"Z0 ! 
 sq   z"a''' (K-/1B1DE..0G""Y'*c:R"Ssq   r   c                  Z   t               } t               }| j                  |      j                         }|j	                  | d        d|j
                  d   d   vsJ d|j
                  d   d   v sJ |j
                  d   d   d   }t        |t               sJ |j                  dk(  sJ y)	zCheck lazy evaluation of reconstruction_attributes.

    "reconstruction_attributes" is processed by the context and used to create a
    fitted estimator that is passed to the callback as "fitted_estimator".
    c                  
    ddiS )Nn_iter_rN   rQ   rQ   r   r   <lambda>zMtest_hook_calling_lazy_evaluation_reconstruction_attributes.<locals>.<lambda>  s    	1~r   )r   reconstruction_attributesr   kwargsfitted_estimatorrN   N)r	   r   r!   r   r   record
isinstancer   )r   r   r   r   s       r   ;test_hook_calling_lazy_evaluation_reconstruction_attributesr     s     !"I "H%%h/FFHG  7M !  'hoob.A(.KKKK!4X!>>>>r*845GH&(8999##q(((r   c                      d} t        |       }t        |ddi      }t        |t               sJ ||usJ |j                         |j                         k(  sJ |j                  dk(  sJ y)z9Test the _from_reconstruction_attributes helper function.rM   r   r   rO   N)r	   r   r   
get_paramsr   )r   r   reconstructed_ests      r   #test_from_reconstruction_attributesr     sv    H (3I7	Iq>R')9:::I---'')Y-A-A-CCCC$$)))r   c                      t               } t        | dd      }t        d      D ]#  }|j                         }|j                  |k(  r#J  y)zFCheck that the task_id is automatically assigned in the correct order.rM   Tr>   N)r	   r   rA   rB   r   )r   r   rF   rB   s       r    test_subcontext_task_id_orderingr     sI     "I PTUG1X'')
!!Q&&& r   c                  Z   t               } t        | dd      }t        j                  t        d      5  |j                  dd       d	d	d	       t        | dd
      }t        j                  t        d      5  |j                  d       d	d	d	       y	# 1 sw Y   NxY w# 1 sw Y   y	xY w)zCheck errors raised when task_id and sequential_subtasks are inconsistent.

    - if sequential_subtasks is True, children task_ids must be left to None
    - if sequential_subtasks is False, children task_ids must be provided
    rN   Tr>   z\task_id for MaxIterEstimator child_task must be None if sequential_subtasks is True for fit.r3   
child_taskr   rh   NFzatask_id for MaxIterEstimator child_task must be provided if sequential_subtasks is False for fit.r@   )r	   r   r7   r8   rj   rB   )r   r   s     r   &test_subcontext_task_id_ordering_errorr     s     !"I PTUG	3
 	\1=
 !PUVG	4
 	\2
 

 

 
s   B9B!B!B*c                  6    G d dt               }  |        }t               }|j                  |       |j                          |j	                  d      dk(  sJ |j	                  d      dk(  sJ |j	                  d      dk(  sJ |j	                  d      dk(  sJ y)	z<Check registering a callback on a locally defined estimator.c                       e Zd Zedd       Zy)?test_locally_defined_estimator.<locals>.LocallyDefinedEstimatorNc                 n    | j                         }|j                  |        |j                  |        | S )Nr2   )r   r   r   )selfr5   r6   r'   s       r   r:   zCtest_locally_defined_estimator.<locals>.LocallyDefinedEstimator.fit  s7    668L//$/?---=Kr   )NN)__name__
__module____qualname__r   r:   rQ   r   r   LocallyDefinedEstimatorr     s    		 
	r   r   r   rN   r   r   r   N)r   r   r!   r:   r   )r   r   r   s      r   test_locally_defined_estimatorr     s    "6  ()I "HH%MMO(A--- 34999 12a777
+q000r   c                  X    t               } t        | dd      }d}t        |      |k(  sJ y)z0Smoke test for the repr of the callback context.mytask*   rh   zRCallbackContext(estimator_name='MaxIterEstimator', task_name='mytask', task_id=42)N)r	   r   repr)r   r   expected_reprs      r   test_callback_context_reprr     s6     "I hKG	  =M)))r   )r:   r   r   T)4	functoolsr   numpyr`   r7   sklearn.callbackr   r   "sklearn.callback._callback_contextr   r   r   sklearn.callback.tests._utilsr	   r
   r   r   r   r   r   r   r   r   r   r   r(   r,   r0   r<   rJ   rf   rn   rv   rx   markparametrizer|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rQ   r   r   <module>r      s^      A 
     PT
:*:*>&+(?@%:J@+ (*=?QR77" 02CD11  Aq6*1 +12 Aq6*6 +6(16F !@),*'381,*r   