11import json
22
33import hashlib
4+ import math
45import sys
56import semver
67
@@ -152,6 +153,19 @@ def _user_attribute_value_to_string(self, value):
152153 value = self ._get_user_attribute_value_as_seconds_since_epoch (value )
153154 elif isinstance (value , list ):
154155 value = self ._get_user_attribute_value_as_string_list (value )
156+ return json .dumps (value , ensure_ascii = False , separators = (',' , ':' )) # Convert the list to a JSON string
157+
158+ if isinstance (value , float ):
159+ if math .isnan (value ):
160+ return 'NaN'
161+ if value == float ('inf' ):
162+ return 'Infinity'
163+ if value == float ('-inf' ):
164+ return '-Infinity'
165+ if 'e' in str (value ):
166+ return str (value )
167+ if value .is_integer ():
168+ return str (int (value ))
155169
156170 return str (value )
157171
@@ -260,7 +274,15 @@ def _evaluate_percentage_options(self, percentage_options, context, percentage_r
260274 'Skipping %% options because the User.%s attribute is missing.' % user_attribute_name )
261275 return False , None , None , None
262276
263- hash_candidate = ('%s%s' % (key , self ._user_attribute_value_to_string (user_key ))).encode ('utf-8' )
277+ # Unicode fix on Python 2.7
278+ if sys .version_info [0 ] == 2 :
279+ try :
280+ hash_candidate = ('%s%s' % (key , self ._user_attribute_value_to_string (user_key ))).encode ('utf-8' )
281+ except Exception :
282+ hash_candidate = ('%s%s' % (key , self ._user_attribute_value_to_string (user_key ))).decode ('utf-8' ).encode (
283+ 'utf-8' )
284+ else :
285+ hash_candidate = ('%s%s' % (key , self ._user_attribute_value_to_string (user_key ))).encode ('utf-8' )
264286 hash_val = int (hashlib .sha1 (hash_candidate ).hexdigest ()[:7 ], 16 ) % 100
265287
266288 bucket = 0
@@ -317,7 +339,9 @@ def _evaluate_conditions(self, conditions, context, salt, config, log_builder, v
317339 result , error = self ._evaluate_segment_condition (segment_condition , context , salt , log_builder )
318340 if log_builder :
319341 if len (conditions ) > 1 :
320- log_builder .append (' => {}' .format ('true' if result else 'false' ))
342+ if error is None :
343+ log_builder .append (' ' )
344+ log_builder .append ('=> {}' .format ('true' if result else 'false' ))
321345 if not result :
322346 log_builder .append (', skipping the remaining AND conditions' )
323347 elif error is None :
@@ -328,6 +352,14 @@ def _evaluate_conditions(self, conditions, context, salt, config, log_builder, v
328352 break
329353 elif prerequisite_flag_condition is not None :
330354 result = self ._evaluate_prerequisite_flag_condition (prerequisite_flag_condition , context , config , log_builder )
355+ if log_builder :
356+ if len (conditions ) > 1 :
357+ log_builder .append (' => {}' .format ('true' if result else 'false' ))
358+ if not result :
359+ log_builder .append (', skipping the remaining AND conditions' )
360+ elif error is None :
361+ log_builder .new_line ()
362+
331363 if not result :
332364 condition_result = False
333365 break
@@ -363,13 +395,12 @@ def _evaluate_prerequisite_flag_condition(self, prerequisite_flag_condition, con
363395 prerequisite_flag_setting_type = settings [prerequisite_key ].get (SETTING_TYPE )
364396 prerequisite_comparison_value_type = get_value_type (prerequisite_flag_condition )
365397
398+ prerequisite_comparison_value = get_value (prerequisite_flag_condition , prerequisite_flag_setting_type )
399+
366400 # Type mismatch check
367401 if prerequisite_comparison_value_type != SettingType .to_type (prerequisite_flag_setting_type ):
368- raise ValueError ("Type mismatch between comparison value type %s and type %s of prerequisite flag '%s'" %
369- (prerequisite_comparison_value_type , SettingType .to_type (prerequisite_flag_setting_type ),
370- prerequisite_key ))
371-
372- prerequisite_comparison_value = get_value (prerequisite_flag_condition , prerequisite_flag_setting_type )
402+ raise ValueError ("Type mismatch between comparison value '%s' and prerequisite flag '%s'" %
403+ (prerequisite_comparison_value , prerequisite_key ))
373404
374405 prerequisite_condition = ("Flag '%s' %s '%s'" %
375406 (prerequisite_key , PREREQUISITE_COMPARATOR_TEXTS [prerequisite_comparator ],
@@ -410,7 +441,7 @@ def _evaluate_prerequisite_flag_condition(self, prerequisite_flag_condition, con
410441
411442 if log_builder :
412443 log_builder .append ('%s.' % ('true' if prerequisite_condition_result else 'false' ))
413- log_builder .decrease_indent ().new_line (')' ). new_line ()
444+ log_builder .decrease_indent ().new_line (')' )
414445
415446 return prerequisite_condition_result
416447
@@ -531,7 +562,7 @@ def _evaluate_user_condition(self, user_condition, context, context_salt, salt,
531562 return False , error
532563
533564 user_value = user .get_attribute (comparison_attribute )
534- if user_value is None or not user_value :
565+ if user_value is None or ( not user_value and not isinstance ( user_value , list )) :
535566 self .log .warning ('Cannot evaluate condition (%s) for setting \' %s\' '
536567 '(the User.%s attribute is missing). You should set the User.%s attribute in order to make '
537568 'targeting work properly. Read more: https://configcat.com/docs/advanced/user-object/' ,
0 commit comments