diff --git a/CHANGELOG.md b/CHANGELOG.md index 760c7cfc..c2810ac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,17 @@ # Optimizely Python SDK Changelog +## 3.4.2 +June 11th, 2020 + +### Bug Fixes: +* Adjusted log level for audience evaluation logs. ([#267](https://github.com/optimizely/python-sdk/pull/267)) + ## 3.4.1 March 19th, 2020 ### Bug Fixes: * Updated `jsonschema` to address [installation issue](https://github.com/optimizely/python-sdk/issues/232). - ## 3.4.0 January 27th, 2020 diff --git a/optimizely/entities.py b/optimizely/entities.py index 75c73845..3d98c9e3 100644 --- a/optimizely/entities.py +++ b/optimizely/entities.py @@ -1,4 +1,4 @@ -# Copyright 2016-2018, Optimizely +# Copyright 2016-2020, 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 @@ -67,7 +67,7 @@ def __init__( self.groupId = groupId self.groupPolicy = groupPolicy - def getAudienceConditionsOrIds(self): + def get_audience_conditions_or_ids(self): """ Returns audienceConditions if present, otherwise audienceIds. """ return self.audienceConditions if self.audienceConditions is not None else self.audienceIds diff --git a/optimizely/helpers/audience.py b/optimizely/helpers/audience.py index 0e822436..7dd82526 100644 --- a/optimizely/helpers/audience.py +++ b/optimizely/helpers/audience.py @@ -1,4 +1,4 @@ -# Copyright 2016, 2018-2019, Optimizely +# Copyright 2016, 2018-2020, 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 @@ -32,8 +32,7 @@ def is_user_in_experiment(config, experiment, attributes, logger): Boolean representing if user satisfies audience conditions for any of the audiences or not. """ - audience_conditions = experiment.getAudienceConditionsOrIds() - + audience_conditions = experiment.get_audience_conditions_or_ids() logger.debug(audience_logs.EVALUATING_AUDIENCES_COMBINED.format(experiment.key, json.dumps(audience_conditions))) # Return True in case there are no audiences @@ -45,35 +44,32 @@ def is_user_in_experiment(config, experiment, attributes, logger): if attributes is None: attributes = {} - def evaluate_custom_attr(audienceId, index): - audience = config.get_audience(audienceId) + def evaluate_custom_attr(audience_id, index): + audience = config.get_audience(audience_id) custom_attr_condition_evaluator = condition_helper.CustomAttributeConditionEvaluator( audience.conditionList, attributes, logger ) return custom_attr_condition_evaluator.evaluate(index) - def evaluate_audience(audienceId): - audience = config.get_audience(audienceId) + def evaluate_audience(audience_id): + audience = config.get_audience(audience_id) if audience is None: return None - logger.debug(audience_logs.EVALUATING_AUDIENCE.format(audienceId, audience.conditions)) + logger.debug(audience_logs.EVALUATING_AUDIENCE.format(audience_id, audience.conditions)) result = condition_tree_evaluator.evaluate( - audience.conditionStructure, lambda index: evaluate_custom_attr(audienceId, index), + audience.conditionStructure, lambda index: evaluate_custom_attr(audience_id, index), ) result_str = str(result).upper() if result is not None else 'UNKNOWN' - logger.info(audience_logs.AUDIENCE_EVALUATION_RESULT.format(audienceId, result_str)) + logger.debug(audience_logs.AUDIENCE_EVALUATION_RESULT.format(audience_id, result_str)) return result eval_result = condition_tree_evaluator.evaluate(audience_conditions, evaluate_audience) - eval_result = eval_result or False - logger.info(audience_logs.AUDIENCE_EVALUATION_RESULT_COMBINED.format(experiment.key, str(eval_result).upper())) - return eval_result diff --git a/tests/helpers_tests/test_audience.py b/tests/helpers_tests/test_audience.py index 2beaf2cd..d0d4e3dd 100644 --- a/tests/helpers_tests/test_audience.py +++ b/tests/helpers_tests/test_audience.py @@ -1,4 +1,4 @@ -# Copyright 2016-2019, Optimizely +# Copyright 2016-2020, 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 @@ -140,7 +140,7 @@ def test_is_user_in_experiment__returns_False__when_condition_tree_evaluator_ret ) ) - def test_is_user_in_experiment__evaluates_audienceIds(self): + def test_is_user_in_experiment__evaluates_audience_ids(self): """ Test that is_user_in_experiment correctly evaluates audience Ids and calls custom attribute evaluator for leaf nodes. """ @@ -241,7 +241,7 @@ def test_is_user_in_experiment__with_no_audience(self): ] ) - def test_is_user_in_experiment__evaluates_audienceIds(self): + def test_is_user_in_experiment__evaluates_audience_ids(self): user_attributes = {'test_attribute': 'test_value_1'} experiment = self.project_config.get_experiment_from_key('test_experiment') experiment.audienceIds = ['11154', '11159'] @@ -256,8 +256,8 @@ def test_is_user_in_experiment__evaluates_audienceIds(self): self.project_config, experiment, user_attributes, self.mock_client_logger, ) - self.assertEqual(3, self.mock_client_logger.debug.call_count) - self.assertEqual(3, self.mock_client_logger.info.call_count) + self.assertEqual(5, self.mock_client_logger.debug.call_count) + self.assertEqual(1, self.mock_client_logger.info.call_count) self.mock_client_logger.assert_has_calls( [ @@ -265,11 +265,11 @@ def test_is_user_in_experiment__evaluates_audienceIds(self): mock.call.debug( 'Starting to evaluate audience "11154" with conditions: ' + audience_11154.conditions + '.' ), - mock.call.info('Audience "11154" evaluated to UNKNOWN.'), + mock.call.debug('Audience "11154" evaluated to UNKNOWN.'), mock.call.debug( 'Starting to evaluate audience "11159" with conditions: ' + audience_11159.conditions + '.' ), - mock.call.info('Audience "11159" evaluated to UNKNOWN.'), + mock.call.debug('Audience "11159" evaluated to UNKNOWN.'), mock.call.info('Audiences for experiment "test_experiment" collectively evaluated to FALSE.'), ] ) @@ -292,8 +292,8 @@ def test_is_user_in_experiment__evaluates_audience_conditions(self): ): audience.is_user_in_experiment(project_config, experiment, {}, self.mock_client_logger) - self.assertEqual(4, self.mock_client_logger.debug.call_count) - self.assertEqual(4, self.mock_client_logger.info.call_count) + self.assertEqual(7, self.mock_client_logger.debug.call_count) + self.assertEqual(1, self.mock_client_logger.info.call_count) self.mock_client_logger.assert_has_calls( [ @@ -306,17 +306,17 @@ def test_is_user_in_experiment__evaluates_audience_conditions(self): 'Starting to evaluate audience "3468206642" with ' 'conditions: ' + audience_3468206642.conditions + '.' ), - mock.call.info('Audience "3468206642" evaluated to FALSE.'), + mock.call.debug('Audience "3468206642" evaluated to FALSE.'), mock.call.debug( 'Starting to evaluate audience "3988293898" with ' 'conditions: ' + audience_3988293898.conditions + '.' ), - mock.call.info('Audience "3988293898" evaluated to UNKNOWN.'), + mock.call.debug('Audience "3988293898" evaluated to UNKNOWN.'), mock.call.debug( 'Starting to evaluate audience "3988293899" with ' 'conditions: ' + audience_3988293899.conditions + '.' ), - mock.call.info('Audience "3988293899" evaluated to TRUE.'), + mock.call.debug('Audience "3988293899" evaluated to TRUE.'), mock.call.info( 'Audiences for experiment "audience_combinations_experiment" collectively evaluated to TRUE.' ),