Skip to content

Commit

Permalink
fix(exact_evaluator): Treat ints and floats as same type
Browse files Browse the repository at this point in the history
  • Loading branch information
oakbani committed Nov 6, 2018
1 parent 3c8f6f0 commit b519b34
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 14 deletions.
46 changes: 32 additions & 14 deletions optimizely/helpers/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import math
import numbers

from six import string_types, PY2
from six import string_types


class ConditionOperatorTypes(object):
Expand Down Expand Up @@ -193,6 +193,35 @@ def is_value_valid_for_exact_conditions(self, value):

return False

def are_values_same_type(self, first_val, second_val):
""" Method to verify that both values belong to same type. Float and integer are
considered as same type.
Args:
first_val: Value to validate
second_Val: Value to validate
Returns:
Boolean: True if both values belong to same type. Otherwise False
"""

first_val_type = type(first_val)
second_val_type = type(second_val)

# use isinstance to accomodate Python 2 unicode and str types
if isinstance(first_val, string_types) and isinstance(second_val, string_types):
return True

# Compare types if one of the values is bool because bool is a subclass on Integer
if isinstance(first_val, bool) or isinstance(second_val, bool):
return first_val_type == second_val_type

# Treat ints and floats as same type
if isinstance(first_val, (numbers.Integral, float)) and isinstance(second_val, (numbers.Integral, float)):
return True

return False

def exact_evaluator(self, index):
""" Evaluate the given exact match condition for the user attributes
Expand All @@ -208,23 +237,12 @@ def exact_evaluator(self, index):
- if there is a mismatch between the user attribute type and the condition value type
"""
condition_value = self.condition_data[index][1]
if PY2 and isinstance(condition_value, unicode):
# str and unicode are used interchangeably in python 2.
# encode it to str to avoid type mismatch
condition_value = condition_value.encode()

condition_value_type = type(condition_value)

user_value = self.attributes.get(self.condition_data[index][0])
if PY2 and isinstance(user_value, unicode):
user_value = user_value.encode()

user_value_type = type(user_value)

if not self.is_value_valid_for_exact_conditions(condition_value) or \
not self.is_value_valid_for_exact_conditions(user_value) or \
condition_value_type != user_value_type:
return None
not self.are_values_same_type(condition_value, user_value):
return None

return condition_value == user_value

Expand Down
18 changes: 18 additions & 0 deletions tests/helpers_tests/test_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,12 @@ def test_exact_number__returns_true__when_user_provided_value_is_equal_to_condit

self.assertStrictTrue(evaluator.evaluate(0))

evaluator = condition_helper.CustomAttributeConditionEvaluator(
self.exact_number_condition_list, {'lasers_count': 9000.0}
)

self.assertStrictTrue(evaluator.evaluate(0))

def test_exact_number__returns_false__when_user_provided_value_is_not_equal_to_condition_value(self):

evaluator = condition_helper.CustomAttributeConditionEvaluator(
Expand Down Expand Up @@ -525,6 +531,12 @@ def test_greater_than__returns_true__when_user_value_greater_than_condition_valu

self.assertStrictTrue(evaluator.evaluate(0))

evaluator = condition_helper.CustomAttributeConditionEvaluator(
self.gt_condition_list, {'meters_travelled': 49}
)

self.assertStrictTrue(evaluator.evaluate(0))

def test_greater_than__returns_false__when_user_value_not_greater_than_condition_value(self):

evaluator = condition_helper.CustomAttributeConditionEvaluator(
Expand Down Expand Up @@ -559,6 +571,12 @@ def test_less_than__returns_true__when_user_value_less_than_condition_value(self

self.assertStrictTrue(evaluator.evaluate(0))

evaluator = condition_helper.CustomAttributeConditionEvaluator(
self.lt_condition_list, {'meters_travelled': 48}
)

self.assertStrictTrue(evaluator.evaluate(0))

def test_less_than__returns_false__when_user_value_not_less_than_condition_value(self):

evaluator = condition_helper.CustomAttributeConditionEvaluator(
Expand Down

0 comments on commit b519b34

Please sign in to comment.