@@ -108,6 +108,12 @@ def __init__(self, datafile, logger, error_handler):
108
108
109
109
self .parsing_succeeded = True
110
110
111
+ # Map of user IDs to another map of experiments to variations.
112
+ # This contains all the forced variations set by the user
113
+ # by calling set_forced_variation (it is not the same as the
114
+ # whitelisting forcedVariations data structure).
115
+ self .forced_variation_map = {}
116
+
111
117
@staticmethod
112
118
def _generate_key_map (list , key , entity_class ):
113
119
""" Helper method to generate map from key to entity object for given list of dicts.
@@ -456,3 +462,106 @@ def get_variable_for_feature(self, feature_key, variable_key):
456
462
return None
457
463
458
464
return feature .variables .get (variable_key )
465
+
466
+ def set_forced_variation (self , experiment_key , user_id , variation_key ):
467
+ """ Sets users to a map of experiments to forced variations.
468
+
469
+ Args:
470
+ experiment_key: Key for experiment.
471
+ user_id: The user ID.
472
+ variation_key: Key for variation. If None, then clear the existing experiment-to-variation mapping.
473
+
474
+ Returns:
475
+ A boolean value that indicates if the set completed successfully.
476
+ """
477
+ if not user_id :
478
+ self .logger .log (enums .LogLevels .DEBUG , 'User ID is invalid.' )
479
+ return False
480
+
481
+ experiment = self .get_experiment_from_key (experiment_key )
482
+ if not experiment :
483
+ # The invalid experiment key will be logged inside this call.
484
+ return False
485
+
486
+ experiment_id = experiment .id
487
+ if not variation_key :
488
+ if user_id in self .forced_variation_map :
489
+ experiment_to_variation_map = self .forced_variation_map .get (user_id )
490
+ if experiment_id in experiment_to_variation_map :
491
+ del (self .forced_variation_map [user_id ][experiment_id ])
492
+ self .logger .log (enums .LogLevels .DEBUG ,
493
+ 'Variation mapped to experiment "%s" has been removed for user "%s".'
494
+ % (experiment_key , user_id ))
495
+ else :
496
+ self .logger .log (enums .LogLevels .DEBUG ,
497
+ 'Nothing to remove. Variation mapped to experiment "%s" for user "%s" does not exist.'
498
+ % (experiment_key , user_id ))
499
+ else :
500
+ self .logger .log (enums .LogLevels .DEBUG ,
501
+ 'Nothing to remove. User "%s" does not exist in the forced variation map.' % user_id )
502
+ return True
503
+
504
+ forced_variation = self .get_variation_from_key (experiment_key , variation_key )
505
+ if not forced_variation :
506
+ # The invalid variation key will be logged inside this call.
507
+ return False
508
+
509
+ variation_id = forced_variation .id
510
+
511
+ if user_id not in self .forced_variation_map :
512
+ self .forced_variation_map [user_id ] = {experiment_id : variation_id }
513
+ else :
514
+ self .forced_variation_map [user_id ][experiment_id ] = variation_id
515
+
516
+ self .logger .log (enums .LogLevels .DEBUG ,
517
+ 'Set variation "%s" for experiment "%s" and user "%s" in the forced variation map.'
518
+ % (variation_id , experiment_id , user_id ))
519
+ return True
520
+
521
+ def get_forced_variation (self , experiment_key , user_id ):
522
+ """ Gets the forced variation key for the given user and experiment.
523
+
524
+ Args:
525
+ experiment_key: Key for experiment.
526
+ user_id: The user ID.
527
+
528
+ Returns:
529
+ The variation which the given user and experiment should be forced into.
530
+ """
531
+ if not user_id :
532
+ self .logger .log (enums .LogLevels .DEBUG , 'User ID is invalid.' )
533
+ return None
534
+
535
+ if user_id not in self .forced_variation_map :
536
+ self .logger .log (enums .LogLevels .DEBUG , 'User "%s" is not in the forced variation map.' % user_id )
537
+ return None
538
+
539
+ experiment = self .get_experiment_from_key (experiment_key )
540
+ if not experiment :
541
+ # The invalid experiment key will be logged inside this call.
542
+ return None
543
+
544
+ experiment_to_variation_map = self .forced_variation_map .get (user_id )
545
+
546
+ if not experiment_to_variation_map :
547
+ self .logger .log (enums .LogLevels .DEBUG ,
548
+ 'No experiment "%s" mapped to user "%s" in the forced variation map.'
549
+ % (experiment_key , user_id ))
550
+ return None
551
+
552
+ variation_id = experiment_to_variation_map .get (experiment .id )
553
+ if variation_id is None :
554
+ self .logger .log (enums .LogLevels .DEBUG ,
555
+ 'No variation mapped to experiment "%s" in the forced variation map.'
556
+ % experiment_key )
557
+ return None
558
+
559
+ variation = self .get_variation_from_id (experiment_key , variation_id )
560
+ if not variation :
561
+ # The invalid variation ID will be logged inside this call.
562
+ return None
563
+
564
+ self .logger .log (enums .LogLevels .DEBUG ,
565
+ 'Variation "%s" is mapped to experiment "%s" and user "%s" in the forced variation map'
566
+ % (variation .key , experiment_key , user_id ))
567
+ return variation
0 commit comments