1
+ from collections .abc import Mapping
1
2
import importlib .metadata
2
3
import json
3
4
import os
13
14
14
15
import howso
15
16
from howso .client import HowsoClient
16
- from howso .client .client import _check_isfile , get_configuration_path , get_howso_client_class , LEGACY_CONFIG_FILENAMES
17
+ from howso .client .client import (
18
+ _check_isfile , # type: ignore reportPrivateUsage
19
+ get_configuration_path ,
20
+ get_howso_client_class ,
21
+ LEGACY_CONFIG_FILENAMES
22
+ )
17
23
from howso .client .exceptions import HowsoApiError , HowsoConfigurationError , HowsoError
18
24
from howso .client .protocols import ProjectClient
19
25
from howso .client .schemas .reaction import Reaction
20
26
from howso .direct import HowsoDirectClient
21
27
from howso .utilities .testing import get_configurationless_test_client , get_test_options
28
+ from howso .utilities .constants import _RENAMED_DETAIL_KEYS , _RENAMED_DETAIL_KEYS_EXTRA # type: ignore reportPrivateUsage
22
29
23
30
TEST_OPTIONS = get_test_options ()
24
31
@@ -577,8 +584,8 @@ def test_a_la_cart_data(self, trainee):
577
584
['similarity_conviction' , ]
578
585
),
579
586
(
580
- {'feature_residuals_robust ' : True , },
581
- ['feature_residuals_robust ' , ]
587
+ {'feature_robust_residuals ' : True , },
588
+ ['feature_robust_residuals ' , ]
582
589
),
583
590
]
584
591
for audit_detail_set , keys_to_expect in details_sets :
@@ -590,6 +597,112 @@ def test_a_la_cart_data(self, trainee):
590
597
details = response ['details' ]
591
598
assert (all (details [key ] is not None for key in keys_to_expect ))
592
599
600
+ @pytest .mark .parametrize ('old_key,new_key' , _RENAMED_DETAIL_KEYS .items ())
601
+ def test_deprecated_detail_keys_react (self , trainee , old_key , new_key ):
602
+ """Ensure using any of the deprecated keys raises a warning, but continues to work."""
603
+ # These keys shouldn't be tested like this:
604
+ if new_key in [
605
+ "feature_full_directional_prediction_contributions" ,
606
+ "feature_robust_directional_prediction_contributions" ,
607
+ "feature_full_accuracy_contributions_permutation" ,
608
+ "feature_robust_accuracy_contributions_permutation" ,
609
+ ]:
610
+ return True
611
+
612
+ with pytest .warns (DeprecationWarning ) as record :
613
+ self .client .train (
614
+ trainee .id , [[1 , 2 ], [1 , 2 ], [1 , 2 ]],
615
+ features = ['penguin' , 'play' ]
616
+ )
617
+ reaction = self .client .react (
618
+ trainee .id ,
619
+ contexts = [['1' ]],
620
+ context_features = ['penguin' ],
621
+ action_features = ['play' ],
622
+ details = {old_key : True }
623
+ )
624
+
625
+ # Check that the correct warning was raised.
626
+ assert len (record )
627
+ # There may be multiple warnings. Ensure at least one of them contains
628
+ # the deprecation message.
629
+ assert any ([
630
+ f"'{ old_key } ' is deprecated" in str (r .message )
631
+ for r in record
632
+ ])
633
+
634
+ # We DO want the old_key to be present during the deprecation period.
635
+ assert old_key in reaction .get ('details' , {}).keys ()
636
+
637
+ # We do NOT want the new_key present during the deprecation period.
638
+ assert new_key not in reaction .get ('details' , {}).keys ()
639
+
640
+ # Some keys request multiple keys to be returned, these too should be
641
+ # converted to the old names if the old name was originally used.
642
+ if old_key in _RENAMED_DETAIL_KEYS_EXTRA .keys ():
643
+ for old_extra_key , new_extra_key in _RENAMED_DETAIL_KEYS_EXTRA [old_key ]["additional_keys" ].items ():
644
+ assert new_extra_key not in reaction .get ('details' , {}).keys ()
645
+ assert old_extra_key in reaction .get ('details' , {}).keys ()
646
+
647
+ @pytest .mark .parametrize ('old_key,new_key' , _RENAMED_DETAIL_KEYS .items ())
648
+ def test_deprecated_detail_keys_react_aggregate (self , trainee , old_key , new_key ):
649
+ """Ensure using any of the deprecated keys raises a warning, but continues to work."""
650
+ # These keys shouldn't be tested like this:
651
+ if new_key in {
652
+ "case_full_prediction_contributions" ,
653
+ "case_robust_prediction_contributions" ,
654
+ "feature_full_prediction_contributions_for_case" ,
655
+ "feature_robust_prediction_contributions_for_case" ,
656
+ "feature_full_residual_convictions_for_case" ,
657
+ "feature_robust_residual_convictions_for_case" ,
658
+ "feature_full_residuals_for_case" ,
659
+ "feature_robust_residuals_for_case" ,
660
+ "case_full_accuracy_contributions" ,
661
+ "case_robust_accuracy_contributions" ,
662
+ "feature_full_directional_prediction_contributions" ,
663
+ "feature_robust_directional_prediction_contributions" ,
664
+ "feature_full_accuracy_contributions_ex_post" ,
665
+ "feature_robust_accuracy_contributions_ex_post" ,
666
+ }:
667
+ return
668
+
669
+ with pytest .warns (DeprecationWarning ) as record :
670
+ self .client .train (
671
+ trainee .id , [[1 , 2 ], [1 , 2 ], [1 , 2 ]],
672
+ features = ['penguin' , 'play' ]
673
+ )
674
+ response = self .client .react_aggregate (
675
+ trainee .id ,
676
+ action_feature = 'penguin' ,
677
+ num_samples = 1 ,
678
+ details = {old_key : True }
679
+ )
680
+
681
+ # Check that the correct warning was raised.
682
+ assert len (record )
683
+ # There may be multiple warnings. Ensure at least one of them contains
684
+ # the deprecation message.
685
+ assert any ([
686
+ f"'{ old_key } ' is deprecated" in str (r .message )
687
+ for r in record
688
+ ])
689
+
690
+ # No point in testing further if we didn't get back a Mapping instance.
691
+ assert isinstance (response , Mapping ), "react_aggregate did not return a Mapping."
692
+
693
+ # We DO want the old_key to be present during the deprecation period.
694
+ assert old_key in response .keys ()
695
+
696
+ # We do NOT want the new_key present during the deprecation period.
697
+ assert new_key not in response .keys ()
698
+
699
+ # Some keys request multiple keys to be returned, these too should be
700
+ # converted to the old names if the old name was originally used.
701
+ if old_key in _RENAMED_DETAIL_KEYS_EXTRA .keys ():
702
+ for old_extra_key , new_extra_key in _RENAMED_DETAIL_KEYS_EXTRA [old_key ]["additional_keys" ].items ():
703
+ assert new_extra_key not in response .keys ()
704
+ assert old_extra_key in response .keys ()
705
+
593
706
def test_get_version (self ):
594
707
"""Test get_version()."""
595
708
version = self .client .get_version ()
0 commit comments