55from amplitude import Amplitude
66
77from .config import LocalEvaluationConfig
8+ from .evaluate_options import EvaluateOptions
89from ..assignment import Assignment , AssignmentFilter , AssignmentService
10+ from ..exposure import Exposure , ExposureFilter , ExposureService
911from ..cohort .cohort import USER_GROUP_TYPE
1012from ..cohort .cohort_download_api import DirectCohortDownloadApi
1113from ..cohort .cohort_loader import CohortLoader
@@ -47,6 +49,13 @@ def __init__(self, api_key: str, config: LocalEvaluationConfig = None):
4749 instance = Amplitude (config .assignment_config .api_key , config .assignment_config )
4850 self .assignment_service = AssignmentService (instance , AssignmentFilter (
4951 config .assignment_config .cache_capacity ), config .assignment_config .send_evaluated_props )
52+
53+ # Exposure service is always instantiated, using deployment key if no api key provided
54+ exposure_config = self .config .exposure_config
55+ if not exposure_config .api_key :
56+ exposure_config .api_key = api_key
57+ exposure_instance = Amplitude (exposure_config .api_key , exposure_config )
58+ self .exposure_service = ExposureService (exposure_instance , ExposureFilter (exposure_config .cache_capacity ))
5059 self .logger = logging .getLogger ("Amplitude" )
5160 self .logger .addHandler (logging .StreamHandler ())
5261 if self .config .debug :
@@ -81,7 +90,8 @@ def start(self):
8190 """
8291 self .deployment_runner .start ()
8392
84- def evaluate_v2 (self , user : User , flag_keys : Set [str ] = None ) -> Dict [str , Variant ]:
93+ # TODO: python backwards compatibility for evaluate_v2 to be looked at again
94+ def evaluate_v2 (self , user : User , flag_keys : Set [str ] = None , options : EvaluateOptions = None ) -> Dict [str , Variant ]:
8595 """
8696 Locally evaluates flag variants for a user.
8797
@@ -91,16 +101,23 @@ def evaluate_v2(self, user: User, flag_keys: Set[str] = None) -> Dict[str, Varia
91101
92102 Parameters:
93103 user (User): The user to evaluate
94- flag_keys (List[str]): The flags to evaluate with the user. If empty, all flags are evaluated.
104+ flag_keys (Set[str]): The flags to evaluate with the user. If empty, all flags are evaluated.
105+ options (EvaluateOptions): Optional evaluation options.
95106
96107 Returns:
97108 The evaluated variants.
98109 """
110+ # Handle backwards compatibility: if options is None, create default
111+ if options is None :
112+ options = EvaluateOptions (flag_keys = flag_keys )
113+ # Use flag_keys from options if provided, otherwise fall back to parameter
114+ flag_keys_to_use = options .flag_keys if options .flag_keys is not None else flag_keys
115+
99116 flag_configs = self .flag_config_storage .get_flag_configs ()
100117 if flag_configs is None or len (flag_configs ) == 0 :
101118 return {}
102119 self .logger .debug (f"[Experiment] Evaluate: user={ user } - Flags: { flag_configs } " )
103- sorted_flags = topological_sort (flag_configs , flag_keys and list (flag_keys ))
120+ sorted_flags = topological_sort (flag_configs , flag_keys_to_use and list (flag_keys_to_use ))
104121 if not sorted_flags :
105122 return {}
106123
@@ -120,7 +137,10 @@ def evaluate_v2(self, user: User, flag_keys: Set[str] = None) -> Dict[str, Varia
120137 ) for k , v in result .items ()
121138 }
122139 self .logger .debug (f"[Experiment] Evaluate Result: { variants } " )
140+ if options .tracks_exposure is True :
141+ self .exposure_service .track (Exposure (user , variants ))
123142 if self .assignment_service is not None :
143+ # @deprecated Assignment tracking is deprecated. Use ExposureService with Exposure tracking instead.
124144 self .assignment_service .track (Assignment (user , variants ))
125145 return variants
126146
0 commit comments