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
Example #2
0
    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']
Example #3
0
    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
Example #4
0
 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)
Example #6
0
    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)
Example #8
0
 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)
Example #9
0
    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']
Example #10
0
    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
Example #12
0
    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
Example #13
0
    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
Example #14
0
    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