55from .config_value_unwrapper import ConfigValueUnwrapper
66from .context import Context
77from ._internal_logging import InternalLogger
8+ from .simple_criterion_evaluators import (
9+ NumericOperators ,
10+ StringOperators ,
11+ DateOperators ,
12+ SemverOperators ,
13+ RegexMatchOperators ,
14+ )
815import prefab_pb2 as Prefab
916import google
1017
@@ -123,67 +130,42 @@ def all_criteria_match(self, conditional_value, props):
123130
124131 def evaluate_criterion (self , criterion , properties ):
125132 value_from_properties = properties .get (criterion .property_name )
133+ deepest_value = ConfigValueUnwrapper .deepest_value (
134+ criterion .value_to_match , self .config , properties
135+ )
126136
127137 if criterion .operator in [OPS .LOOKUP_KEY_IN , OPS .PROP_IS_ONE_OF ]:
128- return self .matches (criterion , value_from_properties , properties )
138+ return self .one_of (criterion , value_from_properties , properties )
129139 if criterion .operator in [OPS .LOOKUP_KEY_NOT_IN , OPS .PROP_IS_NOT_ONE_OF ]:
130- return not self .matches (criterion , value_from_properties , properties )
140+ return not self .one_of (criterion , value_from_properties , properties )
131141 if criterion .operator == OPS .IN_SEG :
132142 return self .in_segment (criterion , properties )
133143 if criterion .operator == OPS .NOT_IN_SEG :
134144 return not self .in_segment (criterion , properties )
135- if criterion .operator in [
136- OPS .PROP_ENDS_WITH_ONE_OF ,
137- OPS .PROP_DOES_NOT_END_WITH_ONE_OF ,
138- ]:
139- negative = criterion .operator == OPS .PROP_DOES_NOT_END_WITH_ONE_OF
140- if value_from_properties is None :
141- return self .negate (negative , False )
142- return self .negate (
143- negative ,
144- any (
145- [
146- str (value_from_properties ).endswith (ending )
147- for ending in criterion .value_to_match .string_list .values
148- ]
149- ),
150- )
151- if criterion .operator in [
152- OPS .PROP_STARTS_WITH_ONE_OF ,
153- OPS .PROP_DOES_NOT_START_WITH_ONE_OF ,
154- ]:
155- negative = criterion .operator == OPS .PROP_DOES_NOT_START_WITH_ONE_OF
156- if value_from_properties is None :
157- return self .negate (negative , False )
158- return self .negate (
159- negative ,
160- any (
161- [
162- str (value_from_properties ).startswith (beginning )
163- for beginning in criterion .value_to_match .string_list .values
164- ]
165- ),
166- )
167- if criterion .operator in [
168- OPS .PROP_CONTAINS_ONE_OF ,
169- OPS .PROP_DOES_NOT_CONTAIN_ONE_OF ,
170- ]:
171- negative = criterion .operator == OPS .PROP_DOES_NOT_CONTAIN_ONE_OF
172- if value_from_properties is None :
173- return self .negate (negative , False )
174- return self .negate (
175- negative ,
176- any (
177- [
178- string in str (value_from_properties )
179- for string in criterion .value_to_match .string_list .values
180- ]
181- ),
145+ if criterion .operator in StringOperators .SUPPORTED_OPERATORS :
146+ return StringOperators .evaluate (
147+ value_from_properties , criterion .operator , deepest_value .unwrap ()
182148 )
183149 if criterion .operator == OPS .HIERARCHICAL_MATCH :
184150 return value_from_properties .startswith (criterion .value_to_match .string )
185151 if criterion .operator == OPS .ALWAYS_TRUE :
186152 return True
153+ if criterion .operator in DateOperators .SUPPORTED_OPERATORS :
154+ return DateOperators .evaluate (
155+ value_from_properties , criterion .operator , deepest_value .unwrap ()
156+ )
157+ if criterion .operator in NumericOperators .SUPPORTED_OPERATORS :
158+ return NumericOperators .evaluate (
159+ value_from_properties , criterion .operator , deepest_value .unwrap ()
160+ )
161+ if criterion .operator in RegexMatchOperators .SUPPORTED_OPERATORS :
162+ return RegexMatchOperators .evaluate (
163+ value_from_properties , criterion .operator , deepest_value .unwrap ()
164+ )
165+ if criterion .operator in SemverOperators .SUPPORTED_OPERATORS :
166+ return SemverOperators .evaluate (
167+ value_from_properties , criterion .operator , deepest_value .unwrap ()
168+ )
187169
188170 logger .info (f"Unknown criterion operator { criterion .operator } " )
189171 return False
@@ -192,15 +174,23 @@ def evaluate_criterion(self, criterion, properties):
192174 def negate (negate , value ):
193175 return not value if negate else value
194176
195- def matches (self , criterion , value , properties ):
177+ @staticmethod
178+ def _ensure_list (value ):
179+ return (
180+ value
181+ if isinstance (value , (list , google ._upb ._message .RepeatedScalarContainer ))
182+ else [value ]
183+ )
184+
185+ def one_of (self , criterion , value , properties ):
196186 criterion_value_or_values = ConfigValueUnwrapper .deepest_value (
197- criterion .value_to_match , self .config . key , properties
187+ criterion .value_to_match , self .config , properties
198188 ).unwrap ()
199- if isinstance (
200- criterion_value_or_values , google . _upb . _message . RepeatedScalarContainer
201- ) or isinstance ( criterion_value_or_values , list ):
202- return str ( value ) in criterion_value_or_values
203- return value == criterion_value_or_values
189+
190+ criterion_values = self . _ensure_list ( criterion_value_or_values )
191+ values = self . _ensure_list ( value )
192+
193+ return any ( str ( v1 ) == str ( v2 ) for v1 in criterion_values for v2 in values )
204194
205195 def in_segment (self , criterion , properties ):
206196 return (
0 commit comments