@@ -287,6 +287,97 @@ def _get_feature_variable_for_type(
287
287
)
288
288
return actual_value
289
289
290
+ def _get_all_feature_variables_for_type (
291
+ self , project_config , feature_key , user_id , attributes ,
292
+ ):
293
+ """ Helper method to determine value for all variables attached to a feature flag.
294
+
295
+ Args:
296
+ project_config: Instance of ProjectConfig.
297
+ feature_key: Key of the feature whose variable's value is being accessed.
298
+ user_id: ID for user.
299
+ attributes: Dict representing user attributes.
300
+
301
+ Returns:
302
+ Dictionary of all variables. None if:
303
+ - Feature key is invalid.
304
+ """
305
+ if not validator .is_non_empty_string (feature_key ):
306
+ self .logger .error (enums .Errors .INVALID_INPUT .format ('feature_key' ))
307
+ return None
308
+
309
+ if not isinstance (user_id , string_types ):
310
+ self .logger .error (enums .Errors .INVALID_INPUT .format ('user_id' ))
311
+ return None
312
+
313
+ if not self ._validate_user_inputs (attributes ):
314
+ return None
315
+
316
+ feature_flag = project_config .get_feature_from_key (feature_key )
317
+ if not feature_flag :
318
+ return None
319
+
320
+ feature_enabled = False
321
+ source_info = {}
322
+
323
+ decision = self .decision_service .get_variation_for_feature (project_config , feature_flag , user_id , attributes )
324
+ if decision .variation :
325
+
326
+ feature_enabled = decision .variation .featureEnabled
327
+ if feature_enabled :
328
+ self .logger .info (
329
+ 'Feature "%s" for variation "%s" is enabled.' % (feature_key , decision .variation .key )
330
+ )
331
+ else :
332
+ self .logger .info (
333
+ 'Feature "%s" for variation "%s" is not enabled.' % (feature_key , decision .variation .key )
334
+ )
335
+ else :
336
+ self .logger .info (
337
+ 'User "%s" is not in any variation or rollout rule. '
338
+ 'Returning default value for all variables of feature flag "%s".' % (user_id , feature_key )
339
+ )
340
+
341
+ all_variables = {}
342
+ for variable_key in feature_flag .variables :
343
+ variable = project_config .get_variable_for_feature (feature_key , variable_key )
344
+ variable_value = variable .defaultValue
345
+ if feature_enabled :
346
+ variable_value = project_config .get_variable_value_for_variation (variable , decision .variation )
347
+ self .logger .debug (
348
+ 'Got variable value "%s" for variable "%s" of feature flag "%s".'
349
+ % (variable_value , variable_key , feature_key )
350
+ )
351
+
352
+ try :
353
+ actual_value = project_config .get_typecast_value (variable_value , variable .type )
354
+ except :
355
+ self .logger .error ('Unable to cast value. Returning None.' )
356
+ actual_value = None
357
+
358
+ all_variables [variable_key ] = actual_value
359
+
360
+ if decision .source == enums .DecisionSources .FEATURE_TEST :
361
+ source_info = {
362
+ 'experiment_key' : decision .experiment .key ,
363
+ 'variation_key' : decision .variation .key ,
364
+ }
365
+
366
+ self .notification_center .send_notifications (
367
+ enums .NotificationTypes .DECISION ,
368
+ enums .DecisionNotificationTypes .ALL_FEATURE_VARIABLES ,
369
+ user_id ,
370
+ attributes or {},
371
+ {
372
+ 'feature_key' : feature_key ,
373
+ 'feature_enabled' : feature_enabled ,
374
+ 'variable_values' : all_variables ,
375
+ 'source' : decision .source ,
376
+ 'source_info' : source_info ,
377
+ },
378
+ )
379
+ return all_variables
380
+
290
381
def activate (self , experiment_key , user_id , attributes = None ):
291
382
""" Buckets visitor and sends impression event to Optimizely.
292
383
@@ -672,6 +763,54 @@ def get_feature_variable_string(self, feature_key, variable_key, user_id, attrib
672
763
project_config , feature_key , variable_key , variable_type , user_id , attributes ,
673
764
)
674
765
766
+ def get_feature_variable_json (self , feature_key , variable_key , user_id , attributes = None ):
767
+ """ Returns value for a certain JSON variable attached to a feature.
768
+
769
+ Args:
770
+ feature_key: Key of the feature whose variable's value is being accessed.
771
+ variable_key: Key of the variable whose value is to be accessed.
772
+ user_id: ID for user.
773
+ attributes: Dict representing user attributes.
774
+
775
+ Returns:
776
+ Dictionary object of the variable. None if:
777
+ - Feature key is invalid.
778
+ - Variable key is invalid.
779
+ - Mismatch with type of variable.
780
+ """
781
+
782
+ variable_type = entities .Variable .Type .JSON
783
+ project_config = self .config_manager .get_config ()
784
+ if not project_config :
785
+ self .logger .error (enums .Errors .INVALID_PROJECT_CONFIG .format ('get_feature_variable_json' ))
786
+ return None
787
+
788
+ return self ._get_feature_variable_for_type (
789
+ project_config , feature_key , variable_key , variable_type , user_id , attributes ,
790
+ )
791
+
792
+ def get_all_feature_variables (self , feature_key , user_id , attributes = None ):
793
+ """ Returns dictionary of all variables and their corresponding values in the context of a feature.
794
+
795
+ Args:
796
+ feature_key: Key of the feature whose variable's value is being accessed.
797
+ user_id: ID for user.
798
+ attributes: Dict representing user attributes.
799
+
800
+ Returns:
801
+ Dictionary mapping variable key to variable value. None if:
802
+ - Feature key is invalid.
803
+ """
804
+
805
+ project_config = self .config_manager .get_config ()
806
+ if not project_config :
807
+ self .logger .error (enums .Errors .INVALID_PROJECT_CONFIG .format ('get_all_feature_variables' ))
808
+ return None
809
+
810
+ return self ._get_all_feature_variables_for_type (
811
+ project_config , feature_key , user_id , attributes ,
812
+ )
813
+
675
814
def set_forced_variation (self , experiment_key , user_id , variation_key ):
676
815
""" Force a user into a variation for a given experiment.
677
816
0 commit comments