
    	]j&                         d 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 ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZmZmZ ddlmZ ddlmZ  e       Zej<                  j>                   G d d             Z y)a  
Test file for prediction validation functionality using LabelInterface.

This module tests the enhanced validation system for predictions during data import.
It covers various validation scenarios including:
- Valid prediction creation
- Invalid prediction structure
- Score validation
- Model version validation
- Result structure validation against project configuration using LabelInterface
- Preannotated fields validation
- Detailed error reporting from LabelInterface
    )patchN)ImportPredictionsAPI)reformat_predictions)ImportApiSerializer)get_user_model)OrganizationFactory)ProjectFactory)ValidationError)APIRequestFactoryforce_authenticate)
Annotation
PredictionTask)TaskFactory)UserFactoryc                      e Zd ZdZ ej
                  d      d        Zd Z edd       ed      d	               Z	 ed
d*d       ed      d               Z
d Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd  Zd! Zd" Zd# Zd$ Z d% Z!d& Z"ejF                  jH                  d'        Z%d( Z&y))+TestPredictionValidationzHTest cases for prediction validation functionality using LabelInterface.T)autousec                    |j                         5  t               | _        t        | j                        | _        | j                  | j                  _        | j                  j                          t        dd| j                  | j                        | _        t        | j                  ddi      | _
        ddd       y# 1 sw Y   yxY w)	z!Set up test data using factories.)
created_byzTest Projecta  
                    <View>
                        <Text name="text" value="$text"/>
                        <Choices name="sentiment" toName="text">
                            <Choice value="positive"/>
                            <Choice value="negative"/>
                            <Choice value="neutral"/>
                        </Choices>
                        <TextArea name="summary" toName="text"/>
                    </View>
                titlelabel_configorganizationr   textzThis is a test text.)projectdataN)unblockr   userr   r   active_organizationsaver	   r   r   task)selfdjango_db_setupdjango_db_blockers      W/root/env/lib/python3.12/site-packages/label_studio/tests/test_prediction_validation.pysetupzTestPredictionValidation.setup%   s     &&( 	a#DI 3tyy ID,0,=,=DII)IINN *$
 "..99DL$ $DLLH^?_`DI3	a 	a 	as   B&C  C	c                    ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ |j                  | j                  j                        }t        |      dk(  sJ |d   j                  j                         dk(  sJ |d   j                  j                         }|j                  dk(  sJ |j                  dk(  sJ y)z5Test that valid predictions are created successfully.r   	Test text	sentimentchoicespositive	from_nameto_nametypevalueffffff?v1.0resultscoremodel_versionr   predictionsTr   r   manycontext
project_id   r   N)r   r   is_validr!   idlenr9   countfirstr6   r7   r#   tasks
serializercreated_tasks
predictions        r&   test_valid_prediction_creationz7TestPredictionValidation.test_valid_prediction_creationC   s     -
 .9+1(1*3j\)B	# "&)/ 
( )e$TXT`T`Hab
""$$$"4<<??C=!Q&&&Q++113q888"1%11779
4'''''6111    ztasks.serializers.flag_set)return_valuez tasks.serializers.LabelInterfacec                 X   |j                   }dd}||j                  _        ddiddddddd	gid
gdddgdg}t        |dd| j                  i      }|j                         sJ |j                         |j                  | j                  j                        }t        |      dk(  sJ y)zMImportApiSerializer must strip export-only keys before validate_prediction().Tc                     d| v rdgS g S NstatezUnexpected field: state payloadreturn_errorss     r&   _validate_predictionzoTestPredictionValidation.test_import_tasks_sanitizes_prediction_before_validation.<locals>._validate_predictionj       '!122IrK   r   zSanitize before validateCREATEDo   r*   r+   r,   r-   g?zmv-sanitize)rP   rA   r5   r6   r7   r8   r   r:   r=   r?   NT)
rL   validate_predictionside_effectr   r   r@   errorsr!   rA   rB   )r#   mock_li_cls_mock_flag_setmock_lirU   rF   rG   rH   s           r&   8test_import_tasks_sanitizes_prediction_before_validationzQTestPredictionValidation.test_import_tasks_sanitizes_prediction_before_validationd   s     **	
 3G##/  !;< "+! .9+1(1*3j\)B	# "%)6 
, )e$TXT`T`Hab
""$7j&7&77$"4<<??C=!Q&&&rK   zdata_import.api.flag_setc                     | dk(  S )N1fflag_feat_utc_210_prediction_validation_15082025rQ   )	flag_namer   kwargss      r&   <lambda>z!TestPredictionValidation.<lambda>   s    LL rK   r[   zdata_import.api.LabelInterfacec                    |j                   }dd}||j                  _        t               }dddddddgidgd	d
| j                  j
                  dg}|j                  d| j                  j
                   d|d      }t        || j                          t        j                         || j                  j
                        }|j                  dk(  sJ |j                  d   dk(  sJ y)zTBulk import API should sanitize payload before LabelInterface.validate_prediction().c                     d| v rdgS g S rO   rQ   rR   s     r&   rU   z{TestPredictionValidation.test_import_predictions_endpoint_sanitizes_payload_before_validation.<locals>._validate_prediction   rV   rK   rW      r*   r   r+   neutralr-   g      ?zmv-sanitize-endpoint)rP   rA   r5   r6   r7   r"   z/api/projects/z/import/predictionsjsonr   formatr   )pk   createdr?   NrY   )rL   rZ   r[   r   r"   rA   postr   r   r   r   as_viewstatus_coder   )	r#   r]   r^   r_   rU   request_factoryrS   requestresponses	            r&   Dtest_import_predictions_endpoint_sanitizes_payload_before_validationz]TestPredictionValidation.test_import_predictions_endpoint_sanitizes_payload_before_validation   s    **	
 3G##/+- # &1#) )"+i[!9	 !7		
" "&&T\\__--@A ' 

 	731'//1'dllooN##s***}}Y'1,,,rK   c                     ddidddgdg}t        |dd| j                  i	      }|j                         rJ |j                  sJ y
)z>Test validation fails when prediction is missing result field.r   r)   r2   r3   )r6   r7   r8   Tr   r:   N)r   r   r@   r\   )r#   rF   rG   s      r&   &test_invalid_prediction_missing_resultz?TestPredictionValidation.test_invalid_prediction_missing_result   sg      - "&)/ 	
 )e$TXT`T`Hab
&&(((    rK   c                 R   ddiddddgdg}t        |dd	| j                  i
      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)z5Test validation fails when prediction result is None.r   r)   Nr2   r3   r4   r8   Tr   r:   r=   r9   
r   r   r@   pytestraisesr
   r!   rA   r1   detailr#   rF   rG   exc_infos       r&   #test_invalid_prediction_none_resultz<TestPredictionValidation.test_invalid_prediction_none_result   s     k*tVZms<t;uv
 )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555	8 	8s   'BB&c                 P   ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ |j                  | j                  j                        }t        |      dk(  sJ |d   j                  j                         }|j                  dk(  sJ y)z;Test that valid scores within 0.00-1.00 range are accepted.r   r)   r*   r+   r,   r-   g      ?r3   r4   r8   Tr   r:   r=   r?   r   N	r   r   r@   r!   rA   rB   r9   rD   r6   rE   s        r&   test_valid_score_rangez/TestPredictionValidation.test_valid_score_range   s      -
 .9+1(1*3j\)B	# "&)/ 
( )e$TXT`T`Hab
""$$$"4<<??C=!Q&&&"1%11779
4'''rK   c                    ddidddddgidgddd	gd
ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ |j                  | j                  j                        }t        |      dk(  sJ |d   j                  j                         j                  dk(  sJ |d   j                  j                         j                  dk(  sJ y)z5Test that boundary values 0.00 and 1.00 are accepted.r   r)   r*   r+   r,   r-   g        r3   r4   r8   Test text 2negativeg      ?Tr   r:   r=      r   r?   Nr   )r#   rF   rG   rH   s       r&    test_valid_score_boundary_valuesz9TestPredictionValidation.test_valid_score_boundary_values   s3     -
 .9+1(1*3j\)B	# "%)/ $  /
 .9+1(1*3j\)B	# "%)/ %#
J )e$TXT`T`Hab
""$$$"4<<??C=!Q&&&Q++11399S@@@Q++11399S@@@rK   c                    ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ t        |j                  j                        }d|v sJ y# 1 sw Y   IxY w)z8Test validation fails when score is outside valid range.r   r)   r*   r+   r,   r-         ?r3   r4   r8   Tr   r:   r=   Nr9   z#Score must be between 0.00 and 1.00r   r   r@   r}   r~   r
   r!   rA   r1   r   strr#   rF   rG   r   
error_texts        r&   test_invalid_score_rangez1TestPredictionValidation.test_invalid_score_range%  s      -
 .9+1(1*3j\)B	# "%)/ 
( )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555../
4
BBB	8 	8   'CCc                    ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ t        |j                  j                        }d|v sJ y# 1 sw Y   IxY w)z1Test validation fails when score is not a number.r   r)   r*   r+   r,   r-   invalid_scorer3   r4   r8   Tr   r:   r=   Nr9   zScore must be a valid numberr   r   s        r&   test_invalid_score_typez0TestPredictionValidation.test_invalid_score_typeE  s      -
 .9+1(1*3j\)B	# "1)/ 
( )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555../
-;;;	8 	8r   c                 P   ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ |j                  | j                  j                        }t        |      dk(  sJ |d   j                  j                         }|j                  dk(  sJ y)z9Test validation fails when model_version is not a string.r   r)   r*   r+   r,   r-   r2   {   r4   r8   Tr   r:   r=   r?   r   123N	r   r   r@   r!   rA   rB   r9   rD   r7   rE   s        r&   test_invalid_model_version_typez8TestPredictionValidation.test_invalid_model_version_typee  s      -
 .9+1(1*3j\)B	# "&), 
( )e$TXT`T`Hab
""$$$"4<<??C=!Q&&&"1%11779
''5000rK   c                 J   ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ |j                  | j                  j                        }t        |      dk(  sJ |d   j                  j                         }|j                  J y)z5Test validation fails when model_version is too long.r   r)   r*   r+   r,   r-   r2   ,  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar4   r8   Tr   r:   r=   r?   r   Nr   rE   s        r&   !test_invalid_model_version_lengthz:TestPredictionValidation.test_invalid_model_version_length  s      -
 .9+1(1*3j\)B	# "&)2 
( )e$TXT`T`Hab
""$$$"4<<??C=!Q&&&"1%11779
''333rK   c                 X   ddiddigdddgdg}t        |d	d
| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)zDTest validation fails when result items are missing required fields.r   r)   r.   r*   r2   r3   r4   r8   Tr   r:   r=   Nr9   r|   r   s       r&   +test_invalid_result_missing_required_fieldszDTestPredictionValidation.test_invalid_result_missing_required_fields  s      -
 !,[# "&)/	 
$ )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555	8 	8s   'B  B)c                 d   ddidddddgidgddd	gd
g}t        |dd| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)zETest validation fails when from_name doesn't exist in project config.r   r)   nonexistent_tagr+   r,   r-   r2   r3   r4   r8   Tr   r:   r=   Nr9   r|   r   s       r&   +test_invalid_result_from_name_not_in_configzDTestPredictionValidation.test_invalid_result_from_name_not_in_config  s      -
 .?+1(1*3j\)B	# "&)/ 
( )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555	8 	8   'B&&B/c                 d   ddidddddgidgdd	d
gdg}t        |dd| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)zDTest validation fails when result type doesn't match project config.r   r)   r*   labelsr+   r,   r-   r2   r3   r4   r8   Tr   r:   r=   Nr9   r|   r   s       r&   !test_invalid_result_type_mismatchz:TestPredictionValidation.test_invalid_result_type_mismatch  s      -
 .9+1(0*3j\)B	# "&)/ 
( )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555	8 	8r   c                 d   ddidddddgidgdd	d
gdg}t        |dd| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)z@Test validation fails when to_name doesn't match project config.r   r)   r*   wrong_targetr+   r,   r-   r2   r3   r4   r8   Tr   r:   r=   Nr9   r|   r   s       r&   $test_invalid_result_to_name_mismatchz=TestPredictionValidation.test_invalid_result_to_name_mismatch  s      -
 .9+9(1*3j\)B	# "&)/ 
( )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555	8 	8r   c                    ddl m}  || j                  j                        }dddigi}|j	                  |d      }t        |t              sJ t        |      dkD  sJ dj                  |      }d	|v sd
|j                         v sJ yy)z:Test that LabelInterface provides detailed error messages.r   LabelInterfacer5   r.   r*   TrT    zMissing required fieldmissingN
 label_studio_sdk.label_interfacer   r   r   rZ   
isinstancelistrB   joinlowerr#   r   liinvalid_predictionr\   r   s         r&   -test_label_interface_detailed_error_reportingzFTestPredictionValidation.test_label_interface_detailed_error_reporting  s    CDLL556 
 ''(:$'O&$'''6{QXXf%
':5jFVFVFX9XXX9X5rK   c                     ddl m}  || j                  j                        }ddddddgidgi}|j	                  |d	
      }t        |t              sJ t        |      dkD  sJ dj                  |      }d|v sJ y)z5Test LabelInterface reports invalid from_name errors.r   r   r5   r   r   r+   r,   r-   Tr   r   	not foundN	r   r   r   r   rZ   r   r   rB   r   r   s         r&   &test_label_interface_invalid_from_namez?TestPredictionValidation.test_label_interface_invalid_from_name'  s    CDLL556 !2%%'*6		
 ''(:$'O&$'''6{QXXf%
j(((rK   c                     ddl m}  || j                  j                        }ddddddgid	gi}|j	                  |d
      }t        |t              sJ t        |      dkD  sJ dj                  |      }d|v sd|j                         v sJ yy)z0Test LabelInterface reports invalid type errors.r   r   r5   r*   r   r   r+   r,   r-   Tr   r   zdoes not match expected typer0   Nr   r   s         r&   !test_label_interface_invalid_typez:TestPredictionValidation.test_label_interface_invalid_type>  s    CDLL556 !,%$'*6		
 ''(:$'O&$'''6{QXXf%
-;vIYIYI[?[[[?[;rK   c                     ddl m}  || j                  j                        }ddddddgidgi}|j	                  |d	
      }t        |t              sJ t        |      dkD  sJ dj                  |      }d|v sJ y)z3Test LabelInterface reports invalid to_name errors.r   r   r5   r*   r   r+   r,   r-   Tr   r   r   Nr   r   s         r&   $test_label_interface_invalid_to_namez=TestPredictionValidation.test_label_interface_invalid_to_nameU  s    CDLL556 !,-%'*6		
 ''(:$'O&$'''6{QXXf%
j(((rK   c                     ddddddg}dg}t        ||      }t        |      dk(  sJ d|d	   v sJ d
|d	   v sJ t        |d	   d
         dk(  sJ y)z@Test validation of predictions created from preannotated fields.Test text 1r,   r   r*   r   r   r*   r   r   r   r9   r?   N)r   rB   )r#   rF   preannotated_fieldsreformatted_taskss       r&   #test_preannotated_fields_validationz<TestPredictionValidation.test_preannotated_fields_validationl  s    'jAMhrCst*m 18KL$%****1---- 1! 4444$Q'671<<<rK   c                     ddidddg}dg}t        j                  t              5  t        ||d       d	d	d	       y	# 1 sw Y   y	xY w)
z9Test validation fails when preannotated field is missing.r   r   r   r   r   r*   T)raise_errorsN)r}   r~   r
   r   )r#   rF   r   s      r&   &test_preannotated_fields_missing_fieldz?TestPredictionValidation.test_preannotated_fields_missing_fieldz  sY     ]#"<

  +m ]]?+ 	P (;$O	P 	P 	Ps	   >Ac                 n   ddiddddddddd	gid
gdddgdg}t        |dd| j                  i      }|j                         sJ t        j                  t
              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)z@Test that multiple validation errors are collected and reported.r   r)   Nr2   r3   r4   r*   r+   r,   r-   r   r8   Tr   r:   r=   r9   r|   r   s       r&   test_multiple_validation_errorsz8TestPredictionValidation.test_multiple_validation_errors  s      -#dVL .9+1(1*3j\)B	# "%)/ 
* )e$TXT`T`Hab
""$$$]]?+ 	8xOOt||O7	8 5 5555	8 	8s   !'B++B4c                    t        dd| j                  | j                        }ddidddddgid	gd
ddgdg}t        |dd|i      }|j	                         sJ t        j                  t              5 }|j                  |j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)z>Test validation fails when project has no label configuration.zNo Config Projectz.<View><Text name="text" value="$text"/></View>r   r   r)   r*   r+   r,   r-   r2   r3   r4   r8   Tr   r:   r=   Nr9   )r	   r   r   r   r@   r}   r~   r
   r!   rA   r1   r   )r#   project_no_configrF   rG   r   s        r&   !test_project_without_label_configz:TestPredictionValidation.test_project_without_label_config  s     +%I**yy	
  -
 .9+1(1*3j\)B	# "&)/ 
( )e$TeHfg
""$$$]]?+ 	=xOO'8';';O<	= 5 5555	= 	=s   5B55B>c                    ddidddddgidgddd	gd
g}t        dt        d            5  t        |dd| j                  i      }|j	                         sJ t        j                  t              5 }|j                  | j                  j                         ddd       dj                  j                  v sJ 	 ddd       y# 1 sw Y   -xY w# 1 sw Y   yxY w)zETest that exceptions during prediction creation are properly handled.r   r)   r*   r+   r,   r-   r2   r3   r4   r8   z1tasks.models.Prediction.prepare_prediction_resultzTest exceptionrf   Tr   r:   r=   Nr9   )r   	Exceptionr   r   r@   r}   r~   r
   r!   rA   r1   r   r   s       r&   0test_prediction_creation_with_exception_handlingzITestPredictionValidation.test_prediction_creation_with_exception_handling  s      -
 .9+1(1*3j\)B	# "&)/ 
* FT]^nTop 	:,%dYX\XdXdLefJ&&(((/ <84<<??;< HNN$9$9999	: 	:< <	: 	:s$   AC3'C"CC	CCc                     ddl m}  || j                  j                        }ddddddgidgi}|j	                  |      }|d	u sJ dd
ddddgidgi}|j	                  |      }|du sJ y)zNTest that LabelInterface.validate_prediction maintains backward compatibility.r   r   r5   r*   r   r+   r,   r-   Tr   FN)r   r   r   r   rZ   )r#   r   r   valid_predictionr5   r   s         r&   +test_label_interface_backward_compatibilityzDTestPredictionValidation.test_label_interface_backward_compatibility  s    CDLL556 )fi[dgqfrZst
 ''(89~~ !2%%'*6		
 ''(:;rK   c                    t         j                  j                  | j                        j	                         }t
        j                  j                  | j                        j	                         }t        j                  j                  | j                        j	                         }ddidddddgidg| j                  j                  dgdddddgidgd	d
dgdddidddddgidg| j                  j                  dgdddddgidgdd
dgdg}t        |dd| j                  i      }|j                         sJ t        j                  t              5 }|j                  | j                  j                         ddd       dj                  j                   v sJ t         j                  j                  | j                        j	                         }t
        j                  j                  | j                        j	                         }t        j                  j                  | j                        j	                         }	||k(  sJ d       ||k(  sJ d       |	|k(  sJ d       t#        |j                  j                   d   d         }
d|
v sJ d|
v sJ d|
v sd|
v sd|
v sJ yyy# 1 sw Y   2xY w)a'  Test that when prediction validation fails, the entire transaction is rolled back.

        This ensures that no tasks or annotations are saved to the database when
        prediction validation errors occur, since the entire create() method is wrapped
        in an atomic transaction.
        )r   r   r   r*   r+   r,   r-   )r5   completed_byr2   r3   r4   )r   annotationsr9   r   r   invalid_choiceg333333?Tr   r:   r=   Nr9   z:Tasks should not be saved when prediction validation failsz@Annotations should not be saved when prediction validation failsz@Predictions should not be saved when prediction validation failsr   zTask 1, prediction 0rj   )r   objectsfilterr   rC   r   r   r   rA   r   r@   r}   r~   r
   r!   r1   r   r   )r#   initial_task_countinitial_annotation_countinitial_prediction_countrF   rG   r   final_task_countfinal_annotation_countfinal_prediction_counterror_messages              r&   Atest_atomic_transaction_rollback_on_prediction_validation_failurezZTestPredictionValidation.test_atomic_transaction_rollback_on_prediction_validation_failure  s    "\\000FLLN#-#5#5#<#<T\\#<#R#X#X#Z #-#5#5#<#<T\\#<#R#X#X#Z   /
 .9+1(1*3j\)B	# )-		
 " .9+1(1*3j\)B	# "&)/ >  /
 .9+1(1*3j\)B	# )-		
 " .9+1(1*36F5G)H	# "&)/ ?=
~ )e$TXT`T`Hab
""$$$ ]]?+ 	8xOOt||O7	8  5 5555  <<..t||.DJJL!+!3!3!:!:4<<!:!P!V!V!X!+!3!3!:!:4<<!:!P!V!V!X#55s7ss5"&>>	NM	N> #&>>	NM	N> HNN11-@CD%666=000]*jM.IYZgMgggMg.I*1	8 	8s   'J33J=c                     t        | j                  | j                        }|j                  du sJ ddiddddddgd	d	ggd
gddgigdg}t	        |dd|i      }|j                         sJ |j                  |j                         d}||_        |j                          |j                  sJ t	        |dd|i      }|j                         sJ |j                  |j                         d}||_        |j                          t	        |dd|i      }|j                         sJ t        j                  t              5 }|j                  |j                         ddd       dj                  j                  v sJ y# 1 sw Y   $xY w)aq  End-to-end: importing predictions before and after setting label config.

        1) With default config (empty View), predictions should not be validated and import succeeds.
        2) After setting a matching config, import with same prediction succeeds.
        3) After changing config to mismatch the prediction, import should fail with validation error.
        r   r   Fimagehttps://example.com/img1.pngr5   	polylabelpolygonlabelsr   
   Apointsr   r-   r8   Tr   r:   r=   
            <View>
              <Image name="image" value="$image"/>
              <PolygonLabels name="polylabel" toName="image">
                <Label value="A"/>
              </PolygonLabels>
            </View>
            
            <View>
              <Image name="image" value="$image"/>
              <PolygonLabels name="otherlabel" toName="image">
                <Label value="A"/>
              </PolygonLabels>
            </View>
            Nr9   )r	   r   r   label_config_is_not_defaultr   r@   r!   rA   r   r}   r~   r
   r1   r   )r#   project_defaultrF   rG   matching_configmismatching_configr   s          r&   8test_import_predictions_with_default_and_changed_configszQTestPredictionValidation.test_import_predictions_with_default_and_changed_configso  s    )d6G6GTXT]T]^::eCCC !"@A !-8+2(767Vb"X4FZ]Y^)_	#	 
& )e$TcHde
""$$$?#5#56 (7$::::(e$TcHde
""$$$?#5#56 (:$(e$TcHde
""$$$]]?+ 	;xOO'9'9O:	; 5 5555	; 	;s   FFc                    ddl m} t        | j                  | j                        }ddlm}  |       }|j                  | j                         |j                  du sJ ddid	d
ddddgddggdgddgigdg} |dd|j                  i      }|j                  | d|d      }|j                  dv sJ d}	|	|_        |j                          |j                  | d|d      }
|
j                  dv sJ d}||_        |j                          |j                  | d|d      }|j                  dk(  sJ |j                         xs i }d|v s|j                  d      dk(  sJ yy) a  Exercise the HTTP ImportAPI to verify validation skip with default config and enforcement later.

        - POST /api/projects/{id}/import?commit_to_project=false with default config should succeed (skip validation)
        - Update project to matching config: same request with commit_to_project=true should succeed
        - Update project to mismatching config: same request with commit_to_project=true should fail
        r   )reverser   )	APIClientrn   Fr   r   r5   r   r   r   r   r   r-   r8   z'data_import:api-projects:project-importro   )rd   z?commit_to_project=falserk   rl   )rp      r   z?commit_to_project=truer   i  r9   r   zValidation errorN)django.urlsr   r	   r   r   rest_framework.testr   r   r   rA   rr   rt   r   r!   rk   get)r#   clientr   r   r   
api_clientrF   urlrespr   resp2r   resp3r   s                 r&   "test_import_api_skip_then_validatez;TestPredictionValidation.test_import_api_skip_then_validate  s    	( d.?.?DIIV1[
%%499%522e;;; !"@A !-8+2(767Vb"X4FZ]Y^)_	#	 
$ ?wzzHZ[ #&>?eTZ[:---  /3%'> ?eTZ[  J...  23%'> ?eTZ[  C'''zz|!r%488H+=AS+STT+S%rK   c           	          t        | j                  | j                  d      }ddiddddddgddggid	gigd
g}t        |dd|i      }|j	                         sJ |j                  |j                         y)z[Taxonomy predictions with nested paths should validate using flattened labels subset check.a  
                <View>
                  <Text name="text" value="$text"/>
                  <Taxonomy name="taxonomy" toName="text">
                    <Choice value="Eukarya"/>
                    <Choice value="Oppossum"/>
                    <Choice value="Bacteria"/>
                    <Choice value="Archaea"/>
                  </Taxonomy>
                </View>
                )r   r   r   r   zTaxonomy sampler5   taxonomyEukaryaOppossumr-   r8   Tr   r:   r=   N)r	   r   r   r   r@   r!   rA   )r#   r   rF   rG   s       r&   #test_taxonomy_prediction_validationz<TestPredictionValidation.test_taxonomy_prediction_validation  s     !**yy
	
(  !23 !-7+1(2$.)2)2J(?1&*"	
# 
. )e$T[H\]
""$$$7::.rK   N)auto)'__name__
__module____qualname____doc__r}   fixturer'   rJ   r   r`   rx   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   mark	django_dbr  r  rQ   rK   r&   r   r   !   s6   RV^^D!a "a:2B 'd;
-.#' / <#'J "
 +,$- -$-L!(
6(<-A^C@<@1<4>64686868Y.).\.).=P6:"6H:<@ghRD6L [[GU GUR//rK   r   )!r  unittest.mockr   r}   data_import.apir   data_import.functionsr   data_import.serializersr   django.contrib.authr   organizations.tests.factoriesr   projects.tests.factoriesr	   rest_framework.exceptionsr
   r   r   r   tasks.modelsr   r   r   tasks.tests.factoriesr   users.tests.factoriesr   Userr  r  r   rQ   rK   r&   <module>r     sd       0 6 7 . = 3 5 E 5 5 - - L/ L/ L/rK   