diff --git a/configcatclient/rolloutevaluator.py b/configcatclient/rolloutevaluator.py index f233f26..a1e9c34 100644 --- a/configcatclient/rolloutevaluator.py +++ b/configcatclient/rolloutevaluator.py @@ -188,9 +188,21 @@ def _get_user_attribute_value_as_string_list(self, attribute_value): attribute_value_list = json.loads(attribute_value) else: attribute_value_list = attribute_value + + # Check if the result is a list if not isinstance(attribute_value_list, list): raise ValueError() + # Check if all items in the list are strings + for item in attribute_value_list: + # Handle unicode strings on Python 2.7 + if sys.version_info[0] == 2: + if not isinstance(attribute_value, (str, unicode)): # noqa: F821 + return attribute_value + else: + if not isinstance(item, str): + raise ValueError() + return attribute_value_list def _handle_invalid_user_attribute(self, comparison_attribute, comparator, comparison_value, key, validation_error): diff --git a/configcatclienttests/test_evaluationlog.py b/configcatclienttests/test_evaluationlog.py index 2a9c652..e22786b 100644 --- a/configcatclienttests/test_evaluationlog.py +++ b/configcatclienttests/test_evaluationlog.py @@ -26,52 +26,52 @@ def remove_unicode_prefix(string): class EvaluationLogTests(unittest.TestCase): def test_simple_value(self): - self.assertTrue(self._evaluation_log('data/evaluation/simple_value.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/simple_value.json')) def test_1_targeting_rule(self): - self.assertTrue(self._evaluation_log('data/evaluation/1_targeting_rule.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/1_targeting_rule.json')) def test_2_targeting_rules(self): - self.assertTrue(self._evaluation_log('data/evaluation/2_targeting_rules.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/2_targeting_rules.json')) def test_options_based_on_user_id(self): - self.assertTrue(self._evaluation_log('data/evaluation/options_based_on_user_id.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/options_based_on_user_id.json')) def test_options_based_on_custom_attr(self): - self.assertTrue(self._evaluation_log('data/evaluation/options_based_on_custom_attr.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/options_based_on_custom_attr.json')) def test_options_after_targeting_rule(self): - self.assertTrue(self._evaluation_log('data/evaluation/options_after_targeting_rule.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/options_after_targeting_rule.json')) def test_options_within_targeting_rule(self): - self.assertTrue(self._evaluation_log('data/evaluation/options_within_targeting_rule.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/options_within_targeting_rule.json')) def test_and_rules(self): - self.assertTrue(self._evaluation_log('data/evaluation/and_rules.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/and_rules.json')) def test_segment(self): - self.assertTrue(self._evaluation_log('data/evaluation/segment.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/segment.json')) def test_prerequisite_flag(self): - self.assertTrue(self._evaluation_log('data/evaluation/prerequisite_flag.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/prerequisite_flag.json')) def test_semver_validation(self): - self.assertTrue(self._evaluation_log('data/evaluation/semver_validation.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/semver_validation.json')) def test_epoch_date_validation(self): - self.assertTrue(self._evaluation_log('data/evaluation/epoch_date_validation.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/epoch_date_validation.json')) def test_number_validation(self): - self.assertTrue(self._evaluation_log('data/evaluation/number_validation.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/number_validation.json')) def test_comparators_validation(self): self.maxDiff = None - self.assertTrue(self._evaluation_log('data/evaluation/comparators.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/comparators.json')) def test_list_truncation_validation(self): - self.assertTrue(self._evaluation_log('data/evaluation/list_truncation.json')) + self.assertTrue(self._test_evaluation_log('data/evaluation/list_truncation.json')) - def _evaluation_log(self, file_path, test_filter=None, generate_expected_log=False): + def _test_evaluation_log(self, file_path, test_filter=None, generate_expected_log=False): script_dir = os.path.dirname(__file__) file_path = os.path.join(script_dir, file_path) self.assertTrue(os.path.isfile(file_path)) diff --git a/configcatclienttests/test_integration_configcatclient.py b/configcatclienttests/test_integration_configcatclient.py index 5bfcb75..70037fc 100644 --- a/configcatclienttests/test_integration_configcatclient.py +++ b/configcatclienttests/test_integration_configcatclient.py @@ -20,7 +20,7 @@ except ImportError: from mock import Mock, ANY -_SDK_KEY = 'PKDVCLf-Hq-h-kCzMp-L7Q/PaDVCFk9EpmD6sLpGLltTA' +_SDK_KEY = 'configcat-sdk-1/PKDVCLf-Hq-h-kCzMp-L7Q/1cGEJXUwYUGZCBOL-E2sOw' class DefaultTests(unittest.TestCase): diff --git a/configcatclienttests/test_lazyloadingcachepolicy.py b/configcatclienttests/test_lazyloadingcachepolicy.py index e09f88c..f1c6b42 100644 --- a/configcatclienttests/test_lazyloadingcachepolicy.py +++ b/configcatclienttests/test_lazyloadingcachepolicy.py @@ -186,7 +186,6 @@ def test_cache_TTL_respects_external_cache(self): response_mock.json.return_value = json.loads(config_json_string_remote) response_mock.text = config_json_string_remote response_mock.status_code = 200 - # response_mock.headers = {'ETag': 'etag'} config_json_string_local = TEST_JSON_FORMAT.format(value_type=SettingType.STRING, value='{"s": "test-local"}') config_cache = SingleValueConfigCache(ConfigEntry( diff --git a/configcatclienttests/test_specialcharacter.py b/configcatclienttests/test_specialcharacter.py new file mode 100644 index 0000000..4fe5ebe --- /dev/null +++ b/configcatclienttests/test_specialcharacter.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +import logging +import unittest + +import configcatclient +from configcatclient.user import User + +logging.basicConfig(level=logging.INFO) + +_SDK_KEY = 'configcat-sdk-1/PKDVCLf-Hq-h-kCzMp-L7Q/u28_1qNyZ0Wz-ldYHIU7-g' + + +class SpecialCharacterTests(unittest.TestCase): + def setUp(self): + self.client = configcatclient.get(_SDK_KEY) + + def tearDown(self): + self.client.close() + + def test_special_characters_works_cleartext(self): + actual = self.client.get_value("specialCharacters", "NOT_CAT", User('äöüÄÖÜçéèñışğ⢙✓😀')) + self.assertEqual(actual, 'äöüÄÖÜçéèñışğ⢙✓😀') + + def test_special_characters_works_hashed(self): + actual = self.client.get_value("specialCharactersHashed", "NOT_CAT", User('äöüÄÖÜçéèñışğ⢙✓😀')) + self.assertEqual(actual, 'äöüÄÖÜçéèñışğ⢙✓😀') + + +if __name__ == '__main__': + unittest.main() diff --git a/samples/consolesample/consolesample.py b/samples/consolesample/consolesample.py index aaf38f7..275cc00 100644 --- a/samples/consolesample/consolesample.py +++ b/samples/consolesample/consolesample.py @@ -13,7 +13,7 @@ if __name__ == '__main__': # Initialize the ConfigCatClient with an SDK Key. - client = configcatclient.get('PKDVCLf-Hq-h-kCzMp-L7Q/psuH7BGHoUmdONrzzUOY7A') + client = configcatclient.get('configcat-sdk-1/PKDVCLf-Hq-h-kCzMp-L7Q/AG6C1ngVb0CvM07un6JisQ') # In the project there is a 'keySampleText' setting with the following rules: # 1. If the User's country is Hungary, the value should be 'Dog' @@ -38,7 +38,7 @@ my_setting_value = client.get_value('keySampleText', 'default value', User('key')) print("'keySampleText' value from ConfigCat: " + str(my_setting_value)) - # 4. As we don't pass an User object to this call, this will print the setting's default value - 'Cat' + # 4. As we don't pass a User object to this call, this will print the setting's default value - 'Cat' my_setting_value = client.get_value('keySampleText', 'default value') print("'keySampleText' value from ConfigCat: " + str(my_setting_value)) diff --git a/samples/consolesample/consolesample2.py b/samples/consolesample/consolesample2.py index ee0baf8..c21c973 100644 --- a/samples/consolesample/consolesample2.py +++ b/samples/consolesample/consolesample2.py @@ -14,7 +14,7 @@ if __name__ == '__main__': # Initialize the ConfigCatClient with an SDK Key. client = configcatclient.get( - 'PKDVCLf-Hq-h-kCzMp-L7Q/HhOWfwVtZ0mb30i9wi17GQ') + 'configcat-sdk-1/PKDVCLf-Hq-h-kCzMp-L7Q/tiOvFw5gkky9LFu1Duuvzw') # Creating a user object to identify your user (optional). userObject = User('Some UserID', email='configcat@example.com', custom={