From 6673021b1872b61ff5fb9a2b53d049f82564a07a Mon Sep 17 00:00:00 2001 From: ozayr-zaviar <uzairzaviar@gmail.com> Date: Wed, 22 Dec 2021 13:39:10 +0500 Subject: [PATCH 1/3] moved validate forced decision --- optimizely/decision_service.py | 68 +++++++++++++++++++++++++-- optimizely/optimizely.py | 3 +- optimizely/optimizely_user_context.py | 60 ----------------------- 3 files changed, 66 insertions(+), 65 deletions(-) diff --git a/optimizely/decision_service.py b/optimizely/decision_service.py index e3e3079b..a1dcc599 100644 --- a/optimizely/decision_service.py +++ b/optimizely/decision_service.py @@ -378,8 +378,8 @@ def get_variation_for_rollout(self, project_config, feature, user): # check forced decision first rule = rollout_rules[index] optimizely_decision_context = OptimizelyUserContext.OptimizelyDecisionContext(feature.key, rule.key) - forced_decision_variation, reasons_received = user.find_validated_forced_decision( - optimizely_decision_context) + forced_decision_variation, reasons_received = self.validated_forced_decision( + optimizely_decision_context, user) decide_reasons += reasons_received if forced_decision_variation: @@ -464,8 +464,8 @@ def get_variation_for_feature(self, project_config, feature, user_context, optio optimizely_decision_context = OptimizelyUserContext.OptimizelyDecisionContext(feature.key, experiment.key) - forced_decision_variation, reasons_received = user_context.find_validated_forced_decision( - optimizely_decision_context) + forced_decision_variation, reasons_received = self.validated_forced_decision( + optimizely_decision_context, user_context) decide_reasons += reasons_received if forced_decision_variation: @@ -489,3 +489,63 @@ def get_variation_for_feature(self, project_config, feature, user_context, optio if rollout_variation_reasons: decide_reasons += rollout_variation_reasons return variation, decide_reasons + + def validated_forced_decision(self, decision_context, user_context): + """ + Gets forced decisions based on flag key, rule key and variation. + + Args: + decision context: a decision context + user_context context: a user context + + Returns: + Variation of the forced decision. + """ + reasons = [] + + forced_decision = user_context.find_forced_decision(decision_context) + + flag_key = decision_context.flag_key + rule_key = decision_context.rule_key + + if forced_decision: + # we use config here so we can use get_flag_variation() function which is defined in project_config + # otherwise we would us user_context.client instead of config + config = user_context.client.config_manager.get_config() if user_context.client else None + if not config: + return None, reasons + variation = config.get_flag_variation(flag_key, 'key', forced_decision.variation_key) + if variation: + if rule_key: + user_has_forced_decision = enums.ForcedDecisionLogs \ + .USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED.format(forced_decision.variation_key, + flag_key, + rule_key, + user_context.user_id) + + else: + user_has_forced_decision = enums.ForcedDecisionLogs \ + .USER_HAS_FORCED_DECISION_WITHOUT_RULE_SPECIFIED.format(forced_decision.variation_key, + flag_key, + user_context.user_id) + + reasons.append(user_has_forced_decision) + user_context.logger.info(user_has_forced_decision) + + return variation, reasons + + else: + if rule_key: + user_has_forced_decision_but_invalid = enums.ForcedDecisionLogs \ + .USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID.format(flag_key, + rule_key, + user_context.user_id) + else: + user_has_forced_decision_but_invalid = enums.ForcedDecisionLogs \ + .USER_HAS_FORCED_DECISION_WITHOUT_RULE_SPECIFIED_BUT_INVALID.format(flag_key, + user_context.user_id) + + reasons.append(user_has_forced_decision_but_invalid) + user_context.logger.info(user_has_forced_decision_but_invalid) + + return None, reasons diff --git a/optimizely/optimizely.py b/optimizely/optimizely.py index ea68e92c..9efc9bf2 100644 --- a/optimizely/optimizely.py +++ b/optimizely/optimizely.py @@ -1036,7 +1036,8 @@ def _decide(self, user_context, key, decide_options=None): # Check forced decisions first optimizely_decision_context = OptimizelyUserContext.OptimizelyDecisionContext(flag_key=key, rule_key=rule_key) - forced_decision_response = user_context.find_validated_forced_decision(optimizely_decision_context) + forced_decision_response = self.decision_service.validated_forced_decision(optimizely_decision_context, + user_context) variation, decision_reasons = forced_decision_response reasons += decision_reasons diff --git a/optimizely/optimizely_user_context.py b/optimizely/optimizely_user_context.py index 1444fe33..d8a6afb1 100644 --- a/optimizely/optimizely_user_context.py +++ b/optimizely/optimizely_user_context.py @@ -16,8 +16,6 @@ import copy import threading -from .helpers import enums - class OptimizelyUserContext(object): """ @@ -225,61 +223,3 @@ def find_forced_decision(self, decision_context): # must allow None to be returned for the Flags only case return self.forced_decisions_map.get(decision_context) - - def find_validated_forced_decision(self, decision_context): - """ - Gets forced decisions based on flag key, rule key and variation. - - Args: - decision context: a decision context - - Returns: - Variation of the forced decision. - """ - reasons = [] - - forced_decision = self.find_forced_decision(decision_context) - - flag_key = decision_context.flag_key - rule_key = decision_context.rule_key - - if forced_decision: - # we use config here so we can use get_flag_variation() function which is defined in project_config - # otherwise we would us self.client instead of config - config = self.client.config_manager.get_config() if self.client else None - if not config: - return None, reasons - variation = config.get_flag_variation(flag_key, 'key', forced_decision.variation_key) - if variation: - if rule_key: - user_has_forced_decision = enums.ForcedDecisionLogs \ - .USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED.format(forced_decision.variation_key, - flag_key, - rule_key, - self.user_id) - - else: - user_has_forced_decision = enums.ForcedDecisionLogs \ - .USER_HAS_FORCED_DECISION_WITHOUT_RULE_SPECIFIED.format(forced_decision.variation_key, - flag_key, - self.user_id) - - reasons.append(user_has_forced_decision) - self.logger.info(user_has_forced_decision) - - return variation, reasons - - else: - if rule_key: - user_has_forced_decision_but_invalid = enums.ForcedDecisionLogs \ - .USER_HAS_FORCED_DECISION_WITH_RULE_SPECIFIED_BUT_INVALID.format(flag_key, - rule_key, - self.user_id) - else: - user_has_forced_decision_but_invalid = enums.ForcedDecisionLogs \ - .USER_HAS_FORCED_DECISION_WITHOUT_RULE_SPECIFIED_BUT_INVALID.format(flag_key, self.user_id) - - reasons.append(user_has_forced_decision_but_invalid) - self.logger.info(user_has_forced_decision_but_invalid) - - return None, reasons From 009974030e8eaca3ed7f8090a1ae8332e73ca325 Mon Sep 17 00:00:00 2001 From: ozayr-zaviar <uzairzaviar@gmail.com> Date: Tue, 4 Jan 2022 18:21:03 +0500 Subject: [PATCH 2/3] headers updated --- optimizely/decision_service.py | 2 +- optimizely/optimizely.py | 2 +- optimizely/optimizely_user_context.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/optimizely/decision_service.py b/optimizely/decision_service.py index a1dcc599..8f31f5f6 100644 --- a/optimizely/decision_service.py +++ b/optimizely/decision_service.py @@ -1,4 +1,4 @@ -# Copyright 2017-2021, Optimizely +# Copyright 2017-2022, Optimizely # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/optimizely/optimizely.py b/optimizely/optimizely.py index 9efc9bf2..5eeb592a 100644 --- a/optimizely/optimizely.py +++ b/optimizely/optimizely.py @@ -1,4 +1,4 @@ -# Copyright 2016-2021, Optimizely +# Copyright 2016-2022, Optimizely # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/optimizely/optimizely_user_context.py b/optimizely/optimizely_user_context.py index d8a6afb1..f096ced5 100644 --- a/optimizely/optimizely_user_context.py +++ b/optimizely/optimizely_user_context.py @@ -1,4 +1,4 @@ -# Copyright 2021, Optimizely and contributors +# Copyright 2021-2022, Optimizely and contributors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From e6d39af5d7d6eb4e92116eda7d03930e6fbdc401 Mon Sep 17 00:00:00 2001 From: ozayr-zaviar <uzairzaviar@gmail.com> Date: Thu, 6 Jan 2022 19:41:24 +0500 Subject: [PATCH 3/3] comments addressed --- optimizely/decision_service.py | 16 +++++++--------- optimizely/optimizely.py | 3 ++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/optimizely/decision_service.py b/optimizely/decision_service.py index 8f31f5f6..3aff4719 100644 --- a/optimizely/decision_service.py +++ b/optimizely/decision_service.py @@ -379,7 +379,7 @@ def get_variation_for_rollout(self, project_config, feature, user): rule = rollout_rules[index] optimizely_decision_context = OptimizelyUserContext.OptimizelyDecisionContext(feature.key, rule.key) forced_decision_variation, reasons_received = self.validated_forced_decision( - optimizely_decision_context, user) + project_config, optimizely_decision_context, user) decide_reasons += reasons_received if forced_decision_variation: @@ -465,7 +465,7 @@ def get_variation_for_feature(self, project_config, feature, user_context, optio experiment.key) forced_decision_variation, reasons_received = self.validated_forced_decision( - optimizely_decision_context, user_context) + project_config, optimizely_decision_context, user_context) decide_reasons += reasons_received if forced_decision_variation: @@ -490,11 +490,12 @@ def get_variation_for_feature(self, project_config, feature, user_context, optio decide_reasons += rollout_variation_reasons return variation, decide_reasons - def validated_forced_decision(self, decision_context, user_context): + def validated_forced_decision(self, project_config, decision_context, user_context): """ Gets forced decisions based on flag key, rule key and variation. Args: + project_config: a project config decision context: a decision context user_context context: a user context @@ -503,18 +504,15 @@ def validated_forced_decision(self, decision_context, user_context): """ reasons = [] - forced_decision = user_context.find_forced_decision(decision_context) + forced_decision = user_context.get_forced_decision(decision_context) flag_key = decision_context.flag_key rule_key = decision_context.rule_key if forced_decision: - # we use config here so we can use get_flag_variation() function which is defined in project_config - # otherwise we would us user_context.client instead of config - config = user_context.client.config_manager.get_config() if user_context.client else None - if not config: + if not project_config: return None, reasons - variation = config.get_flag_variation(flag_key, 'key', forced_decision.variation_key) + variation = project_config.get_flag_variation(flag_key, 'key', forced_decision.variation_key) if variation: if rule_key: user_has_forced_decision = enums.ForcedDecisionLogs \ diff --git a/optimizely/optimizely.py b/optimizely/optimizely.py index 5eeb592a..10464a72 100644 --- a/optimizely/optimizely.py +++ b/optimizely/optimizely.py @@ -1036,7 +1036,8 @@ def _decide(self, user_context, key, decide_options=None): # Check forced decisions first optimizely_decision_context = OptimizelyUserContext.OptimizelyDecisionContext(flag_key=key, rule_key=rule_key) - forced_decision_response = self.decision_service.validated_forced_decision(optimizely_decision_context, + forced_decision_response = self.decision_service.validated_forced_decision(config, + optimizely_decision_context, user_context) variation, decision_reasons = forced_decision_response reasons += decision_reasons