def enroll(self, experiment_name, alternatives, force_alternative=None): """ Enroll this user in the experiment if they are not already part of it. Returns the selected alternative force_alternative: Optionally force a user in an alternative at enrollment time """ chosen_alternative = conf.CONTROL_GROUP experiment = experiment_manager.get_experiment(experiment_name) if experiment: if experiment.is_displaying_alternatives(): if isinstance(alternatives, collections.Mapping): if conf.CONTROL_GROUP not in alternatives: experiment.ensure_alternative_exists(conf.CONTROL_GROUP, 1) for alternative, weight in alternatives.items(): experiment.ensure_alternative_exists(alternative, weight) else: alternatives_including_control = alternatives + [conf.CONTROL_GROUP] for alternative in alternatives_including_control: experiment.ensure_alternative_exists(alternative) assigned_alternative = self._get_enrollment(experiment) if assigned_alternative: chosen_alternative = assigned_alternative elif experiment.is_accepting_new_users(): if force_alternative: chosen_alternative = force_alternative else: chosen_alternative = experiment.random_alternative() self._set_enrollment(experiment, chosen_alternative) else: chosen_alternative = experiment.default_alternative return chosen_alternative
def confirm_human(self): self.session[conf.CONFIRM_HUMAN_SESSION_KEY] = True logger.info( json.dumps({ 'type': 'confirm_human', 'participant': self._participant_identifier() })) # Replay enrollments for enrollment in self._get_all_enrollments(): self.experiment_counter.increment_participant_count( enrollment.experiment, enrollment.alternative, self._participant_identifier()) # Replay goals if 'experiments_goals' in self.session: try: for experiment_name, alternative, goal_name, count in self.session[ 'experiments_goals']: experiment = experiment_manager.get_experiment( experiment_name) if experiment: self.experiment_counter.increment_goal_count( experiment, alternative, goal_name, self._participant_identifier(), count) except ValueError: pass # Values from older version finally: del self.session['experiments_goals']
def enroll(self, experiment_name, alternatives, force_alternative=None): """ Enroll this user in the experiment if they are not already part of it. Returns the selected alternative force_alternative: Optionally force a user in an alternative at enrollment time """ chosen_alternative = conf.CONTROL_GROUP experiment = experiment_manager.get_experiment(experiment_name) if experiment: if experiment.is_displaying_alternatives(): if isinstance(alternatives, collections.Mapping): if conf.CONTROL_GROUP not in alternatives: experiment.ensure_alternative_exists(conf.CONTROL_GROUP, 1) for alternative, weight in alternatives.items(): experiment.ensure_alternative_exists(alternative, weight) else: alternatives_including_control = alternatives + [conf.CONTROL_GROUP] for alternative in alternatives_including_control: experiment.ensure_alternative_exists(alternative) assigned_alternative = self._get_enrollment(experiment) if assigned_alternative: chosen_alternative = assigned_alternative elif experiment.is_accepting_new_users(): if force_alternative: chosen_alternative = force_alternative else: chosen_alternative = experiment.random_alternative() self._set_enrollment(experiment, chosen_alternative) else: chosen_alternative = experiment.default_alternative return chosen_alternative
def _get_all_enrollments(self): enrollments = self.session.get('experiments_enrollments', None) if enrollments: for experiment_name, data in list(enrollments.items()): alternative, _, enrollment_date, last_seen = _session_enrollment_latest_version(data) experiment = experiment_manager.get_experiment(experiment_name) if experiment: yield EnrollmentData(experiment, alternative, enrollment_date, last_seen)
def _get_all_enrollments(self): enrollments = self.session.get("experiments_enrollments", None) if enrollments: for experiment_name, data in enrollments.items(): alternative, _, enrollment_date, last_seen = _session_enrollment_latest_version(data) experiment = experiment_manager.get_experiment(experiment_name) if experiment: yield EnrollmentData(experiment, alternative, enrollment_date, last_seen)
def set_alternative(self, experiment_name, alternative): """Explicitly set the alternative the user is enrolled in for the specified experiment. This allows you to change a user between alternatives. The user and goal counts for the new alternative will be increment, but those for the old one will not be decremented. The user will be enrolled in the experiment even if the experiment would not normally accept this user.""" experiment = experiment_manager.get_experiment(experiment_name) if experiment: self._set_enrollment(experiment, alternative)
def set_alternative(self, experiment_name, alternative): """Explicitly set the alternative the user is enrolled in for the specified experiment. This allows you to change a user between alternatives. The user and goal counts for the new alternative will be increment, but those for the old one will not be decremented. The user will be enrolled in the experiment even if the experiment would not normally accept this user.""" experiment = experiment_manager.get_experiment(experiment_name) if experiment: self._set_enrollment(experiment, alternative)
def _evaluate_conditionals(self): """ Enroll current user in all experiments that are marked with `auto_enroll` and evaluate at least one of the conditionals positively. """ for name in self.experiment_names: experiment = experiment_manager.get_experiment(name, auto_create=False) active = experiment.is_enabled_by_conditionals(self.request) alternative = None if not active: self.disabled_experiments.append(experiment.name) alternative = experiment.default_alternative self._report(experiment, active, alternative)
def confirm_human(self): self.session[conf.CONFIRM_HUMAN_SESSION_KEY] = True logger.info(json.dumps({'type': 'confirm_human', 'participant': self._participant_identifier()})) # Replay enrollments for enrollment in self._get_all_enrollments(): self.experiment_counter.increment_participant_count(enrollment.experiment, enrollment.alternative, self._participant_identifier()) # Replay goals if 'experiments_goals' in self.session: try: for experiment_name, alternative, goal_name, count in self.session['experiments_goals']: experiment = experiment_manager.get_experiment(experiment_name) if experiment: self.experiment_counter.increment_goal_count(experiment, alternative, goal_name, self._participant_identifier(), count) except ValueError: pass # Values from older version finally: del self.session['experiments_goals']
def render(self, context): experiment = experiment_manager.get_experiment(self.experiment_name) if experiment: experiment.ensure_alternative_exists(self.alternative, self.weight) # Get User object if self.user_variable: auth_user = self.user_variable.resolve(context) user = participant(user=auth_user) else: request = context.get('request', None) user = participant(request) # Should we render? if user.is_enrolled(self.experiment_name, self.alternative): response = self.node_list.render(context) else: response = "" return response
def render(self, context): experiment = experiment_manager.get_experiment(self.experiment_name) if experiment: experiment.ensure_alternative_exists(self.alternative, self.weight) # Get User object if self.user_variable: auth_user = self.user_variable.resolve(context) user = participant(user=auth_user) else: request = context.get("request", None) user = participant(request) # Should we render? if user.is_enrolled(self.experiment_name, self.alternative): response = self.node_list.render(context) else: response = "" return response
def render_experiment(self, experiment_name, alternative, weight, user_variable, context, caller): """Callback to render {% experiment ... %} tags""" experiment = experiment_manager.get_experiment(experiment_name) if experiment: # create alternative on the fly (write it to DB) if not existing: experiment.ensure_alternative_exists(alternative, weight) # Get User object if user_variable: auth_user = context[user_variable] user = participant(user=auth_user) else: request = context.get('request') user = participant(request) # Should we render? if user.is_enrolled(experiment_name, alternative): return caller() else: return nodes.Markup() # empty node
def confirm_human(self): if self.user: return self.session[conf.CONFIRM_HUMAN_SESSION_KEY] = True logger.info( json.dumps({ 'type': 'confirm_human', 'participant': self._participant_identifier() })) # Replay enrollments for enrollment in self._get_all_enrollments(): self.experiment_counter.increment_participant_count( enrollment.experiment, enrollment.alternative, self._participant_identifier()) # Replay goals try: goals = self._redis.lrange(self._redis_goals_key, 0, -1) if goals: try: for data in goals: experiment_name, alternative, goal_name, count = json.loads( data) experiment = experiment_manager.get_experiment( experiment_name) if experiment: self.experiment_counter.increment_goal_count( experiment, alternative, goal_name, self._participant_identifier(), count) except ValueError: pass # Values from older version finally: self._redis.delete(self._redis_goals_key) except (ConnectionError, ResponseError): # Handle Redis failures gracefully pass
def enroll(self, experiment_name, alternatives, force_alternative=None): """ Enroll this user in the experiment if they are not already part of it. Returns the selected alternative force_alternative: Optionally force a user in an alternative at enrollment time """ chosen_alternative = conf.CONTROL_GROUP if experiment_name in self._get_disabled_experiment_names(): return chosen_alternative experiment = experiment_manager.get_experiment(experiment_name) if experiment: if not experiment.is_displaying_alternatives(): return experiment.default_alternative if not isinstance(alternatives, collections.Mapping): if any(':' in alt for alt in alternatives): parsed_alternatives = {} for alt in alternatives: try: name, weight = alt.split(':', 1) except ValueError: name, weight = alt, None else: weight = int(weight) parsed_alternatives[name] = weight alternatives = parsed_alternatives if isinstance(alternatives, collections.Mapping): if conf.CONTROL_GROUP not in alternatives: total_weight = sum( filter( alt.get('weight') for alt in alternatives.values())) average_weight = round(total_weight / len(alternatives)) experiment.ensure_alternative_exists( conf.CONTROL_GROUP, average_weight) for alternative, weight in alternatives.items(): experiment.ensure_alternative_exists(alternative, weight) else: alternatives_including_control = alternatives + [ conf.CONTROL_GROUP ] for alternative in alternatives_including_control: experiment.ensure_alternative_exists(alternative) assigned_alternative = self._get_enrollment(experiment) if assigned_alternative: chosen_alternative = assigned_alternative elif experiment.is_accepting_new_users(): if force_alternative: chosen_alternative = force_alternative else: chosen_alternative = experiment.random_alternative() self._set_enrollment(experiment, chosen_alternative) return chosen_alternative