@@ -18,13 +18,13 @@ def test_not_operator_basic(self):
1818 # Test with boolean literals - correctly returns booleans
1919 assert evaluate ("!true" ) is False
2020 assert evaluate ("!false" ) is True
21-
21+
2222 def test_not_operator_with_numbers (self ):
2323 """Test NOT operator with numeric values."""
2424 # Zero is falsy
2525 assert evaluate ("!0" ) is True
2626 assert evaluate ("!0.0" ) is True
27-
27+
2828 # Non-zero numbers are truthy
2929 assert evaluate ("!1" ) is False
3030 assert evaluate ("!42" ) is False
@@ -36,7 +36,7 @@ def test_not_operator_with_strings(self):
3636 # Empty string is falsy
3737 assert evaluate ("!''" ) is True
3838 assert evaluate ('!""' ) is True
39-
39+
4040 # Non-empty strings are truthy
4141 assert evaluate ("!'hello'" ) is False
4242 assert evaluate ("!'0'" ) is False # String "0" is truthy
@@ -51,7 +51,7 @@ def test_not_operator_with_collections(self):
5151 # Empty collections are falsy
5252 assert evaluate ("![]" ) is True
5353 assert evaluate ("!{}" ) is True
54-
54+
5555 # Non-empty collections are truthy
5656 assert evaluate ("![1, 2]" ) is False
5757 assert evaluate ("!{'key': 'value'}" ) is False
@@ -60,29 +60,29 @@ def test_double_not_operator_parser_bug(self):
6060 """Test double NOT (!!) operator - documents upstream parser bug."""
6161 # UPSTREAM BUG: The !! syntax is parsed incorrectly and behaves like single !
6262 # This is a known issue in the cel-interpreter crate
63- assert evaluate ("!!true" ) is False # BUG: Should be True, behaves like !true
64- assert evaluate ("!!false" ) is True # BUG: Should be False, behaves like !false
65- assert evaluate ("!!0" ) is True # BUG: Should be False, behaves like !0
66- assert evaluate ("!!1" ) is False # BUG: Should be True, behaves like !1
67- assert evaluate ("!!''" ) is True # BUG: Should be False, behaves like !''
68- assert evaluate ("!!'hello'" ) is False # BUG: Should be True, behaves like !'hello'
69-
63+ assert evaluate ("!!true" ) is False # BUG: Should be True, behaves like !true
64+ assert evaluate ("!!false" ) is True # BUG: Should be False, behaves like !false
65+ assert evaluate ("!!0" ) is True # BUG: Should be False, behaves like !0
66+ assert evaluate ("!!1" ) is False # BUG: Should be True, behaves like !1
67+ assert evaluate ("!!''" ) is True # BUG: Should be False, behaves like !''
68+ assert evaluate ("!!'hello'" ) is False # BUG: Should be True, behaves like !'hello'
69+
7070 # WORKAROUND: Use parentheses for correct double NOT behavior
71- assert evaluate ("!(!true)" ) is True # Correct: NOT(NOT(true)) = True
71+ assert evaluate ("!(!true)" ) is True # Correct: NOT(NOT(true)) = True
7272 assert evaluate ("!(!false)" ) is False # Correct: NOT(NOT(false)) = False
73- assert evaluate ("!(!0)" ) is False # Correct: NOT(NOT(0)) = False
74- assert evaluate ("!(!1)" ) is True # Correct: NOT(NOT(1)) = True
75- assert evaluate ("!(!(''))" )is False # Correct: NOT(NOT('')) = False
76- assert evaluate ("!(!('hello'))" ) is True # Correct: NOT(NOT('hello')) = True
73+ assert evaluate ("!(!0)" ) is False # Correct: NOT(NOT(0)) = False
74+ assert evaluate ("!(!1)" ) is True # Correct: NOT(NOT(1)) = True
75+ assert evaluate ("!(!(''))" ) is False # Correct: NOT(NOT('')) = False
76+ assert evaluate ("!(!('hello'))" ) is True # Correct: NOT(NOT('hello')) = True
7777
7878 def test_bool_function_unavailable (self ):
7979 """Test that bool() function is not available."""
8080 with pytest .raises (RuntimeError , match = "Undefined variable or function: 'bool'" ):
8181 evaluate ("bool(true)" )
82-
82+
8383 with pytest .raises (RuntimeError , match = "Undefined variable or function: 'bool'" ):
8484 evaluate ("bool(0)" )
85-
85+
8686 with pytest .raises (RuntimeError , match = "Undefined variable or function: 'bool'" ):
8787 evaluate ("bool('')" )
8888
@@ -96,29 +96,29 @@ def test_logical_and_truthiness(self):
9696 assert evaluate ("null && true" ) is False
9797 assert evaluate ("[] && true" ) is False
9898 assert evaluate ("{} && true" ) is False
99-
99+
100100 # Truthy values in AND return True when both operands are truthy
101101 assert evaluate ("1 && true" ) is True
102102 assert evaluate ("true && 1" ) is True
103- assert evaluate ("'hello' && true" ) is True
103+ assert evaluate ("'hello' && true" ) is True
104104 assert evaluate ("true && 'hello'" ) is True
105105
106106 def test_logical_or_truthiness (self ):
107107 """Test truthiness evaluation in logical OR operations."""
108108 # OR operator shows behavioral difference from CEL spec - returns original values
109109 # Falsy values in OR
110- assert evaluate ("0 || false" ) is False # Both falsy -> False
111- assert evaluate ("false || 0" ) == 0 # Returns second operand when first is falsy
112- assert evaluate ("'' || false" ) is False # Both falsy -> False
113- assert evaluate ("null || false" ) is False # Both falsy -> False
114-
110+ assert evaluate ("0 || false" ) is False # Both falsy -> False
111+ assert evaluate ("false || 0" ) == 0 # Returns second operand when first is falsy
112+ assert evaluate ("'' || false" ) is False # Both falsy -> False
113+ assert evaluate ("null || false" ) is False # Both falsy -> False
114+
115115 # Truthy values in OR - demonstrates the documented behavioral difference
116116 # CEL spec: should return boolean true/false
117117 # This implementation: returns original truthy value (JavaScript-like)
118- assert evaluate ("1 || false" ) == 1 # Returns original int, not boolean
119- assert evaluate ("42 || false" ) == 42 # Returns original int, not boolean
118+ assert evaluate ("1 || false" ) == 1 # Returns original int, not boolean
119+ assert evaluate ("42 || false" ) == 42 # Returns original int, not boolean
120120 assert evaluate ("'hello' || false" ) == "hello" # Returns string, not boolean
121- assert evaluate ("[1, 2] || false" ) == [1 , 2 ] # Returns list, not boolean
121+ assert evaluate ("[1, 2] || false" ) == [1 , 2 ] # Returns list, not boolean
122122
123123 def test_ternary_operator_truthiness (self ):
124124 """Test truthiness evaluation in ternary conditional expressions."""
@@ -129,7 +129,7 @@ def test_ternary_operator_truthiness(self):
129129 assert evaluate ("null ? 'truthy' : 'falsy'" ) == "falsy"
130130 assert evaluate ("[] ? 'truthy' : 'falsy'" ) == "falsy"
131131 assert evaluate ("{} ? 'truthy' : 'falsy'" ) == "falsy"
132-
132+
133133 # Truthy values
134134 assert evaluate ("1 ? 'truthy' : 'falsy'" ) == "truthy"
135135 assert evaluate ("true ? 'truthy' : 'falsy'" ) == "truthy"
@@ -141,26 +141,30 @@ def test_boolean_coercion_consistency(self):
141141 """Test consistency of boolean coercion across different contexts."""
142142 # Test that the same value has consistent truthiness
143143 test_values = [
144- (0 , False ), # Zero is falsy
145- (1 , True ), # One is truthy
146- ('' , False ), # Empty string is falsy
147- (' hello' , True ), # Non-empty string is truthy
148- ([], False ), # Empty list is falsy
149- ([1 ], True ), # Non-empty list is truthy
150- ({}, False ), # Empty map is falsy
151- ({'a' : 1 }, True ) # Non-empty map is truthy
144+ (0 , False ), # Zero is falsy
145+ (1 , True ), # One is truthy
146+ ("" , False ), # Empty string is falsy
147+ (" hello" , True ), # Non-empty string is truthy
148+ ([], False ), # Empty list is falsy
149+ ([1 ], True ), # Non-empty list is truthy
150+ ({}, False ), # Empty map is falsy
151+ ({"a" : 1 }, True ), # Non-empty map is truthy
152152 ]
153-
153+
154154 for value , is_truthy in test_values :
155155 # NOT operator returns proper booleans
156156 not_result = evaluate ("!x" , {"x" : value })
157157 expected_not = False if is_truthy else True
158- assert not_result == expected_not , f"!{ value } should be { expected_not } , got { not_result } "
159-
158+ assert not_result == expected_not , (
159+ f"!{ value } should be { expected_not } , got { not_result } "
160+ )
161+
160162 # Ternary operator
161163 ternary_result = evaluate ("x ? 'T' : 'F'" , {"x" : value })
162- expected_ternary = 'T' if is_truthy else 'F'
163- assert ternary_result == expected_ternary , f"{ value } ? 'T' : 'F' should be { expected_ternary } "
164+ expected_ternary = "T" if is_truthy else "F"
165+ assert ternary_result == expected_ternary , (
166+ f"{ value } ? 'T' : 'F' should be { expected_ternary } "
167+ )
164168
165169 def test_comparison_operators_return_booleans (self ):
166170 """Test that comparison operators properly return boolean values."""
@@ -171,7 +175,7 @@ def test_comparison_operators_return_booleans(self):
171175 assert evaluate ("2 > 1" ) is True
172176 assert evaluate ("1 <= 1" ) is True
173177 assert evaluate ("1 >= 1" ) is True
174-
178+
175179 assert evaluate ("1 == 2" ) is False
176180 assert evaluate ("1 != 1" ) is False
177181 assert evaluate ("2 < 1" ) is False
@@ -189,20 +193,24 @@ def test_mixed_boolean_expressions(self):
189193 "empty_list" : [],
190194 "non_empty_list" : [1 , 2 , 3 ],
191195 "is_valid" : True ,
192- "is_invalid" : False
196+ "is_invalid" : False ,
193197 }
194-
198+
195199 # Complex AND/OR with mixed types
196200 assert evaluate ("positive && non_empty_string" , context ) is True # AND returns boolean
197- assert evaluate ("zero || positive" , context ) == 42 # OR returns original truthy value
198- assert evaluate ("empty_string || 'default'" , context ) == "default" # OR returns original value
199-
201+ assert evaluate ("zero || positive" , context ) == 42 # OR returns original truthy value
202+ assert (
203+ evaluate ("empty_string || 'default'" , context ) == "default"
204+ ) # OR returns original value
205+
200206 # Mixed with comparisons
201207 assert evaluate ("positive > 0 && non_empty_string" , context ) is True # AND returns boolean
202- assert evaluate ("zero == 0 || is_invalid" , context ) is True # OR with boolean
203-
208+ assert evaluate ("zero == 0 || is_invalid" , context ) is True # OR with boolean
209+
204210 # Complex ternary expressions
205- assert evaluate ("positive ? (empty_string || 'fallback') : 'negative'" , context ) == "fallback"
211+ assert (
212+ evaluate ("positive ? (empty_string || 'fallback') : 'negative'" , context ) == "fallback"
213+ )
206214
207215 def test_boolean_context_with_variables (self ):
208216 """Test boolean coercion with context variables."""
@@ -211,38 +219,38 @@ def test_boolean_context_with_variables(self):
211219 "settings" : {},
212220 "items" : [1 , 2 , 3 ],
213221 "empty_items" : [],
214- "config" : {"debug" : True }
222+ "config" : {"debug" : True },
215223 }
216-
224+
217225 # Object truthiness
218226 assert evaluate ("user ? 'has_user' : 'no_user'" , context ) == "has_user"
219227 assert evaluate ("settings ? 'has_settings' : 'no_settings'" , context ) == "no_settings"
220-
228+
221229 # List truthiness
222230 assert evaluate ("items ? 'has_items' : 'no_items'" , context ) == "has_items"
223231 assert evaluate ("empty_items ? 'has_items' : 'no_items'" , context ) == "no_items"
224-
232+
225233 # Nested access with boolean logic
226- assert evaluate ("user && user.age > 18" , context ) == True
227- assert evaluate ("!settings || config.debug" , context ) == True
234+ assert evaluate ("user && user.age > 18" , context )
235+ assert evaluate ("!settings || config.debug" , context )
228236
229237 def test_documented_behavioral_differences (self ):
230238 """Test and document the known behavioral differences from CEL spec."""
231239 # This test documents the behavioral differences mentioned in cel-compliance.md
232-
240+
233241 # OR operator returns original values instead of booleans
234242 # CEL spec: 42 || false should return true (boolean)
235243 # This implementation: returns 42 (original value)
236244 result = evaluate ("42 || false" )
237245 assert result == 42 # JavaScript-like behavior, not CEL spec
238-
246+
239247 result = evaluate ("0 || 'default'" )
240248 assert result == "default" # Returns original string, not boolean
241-
249+
242250 # AND operator behaves differently - returns boolean values
243251 result = evaluate ("'hello' && 42" )
244252 assert result is True # Returns boolean True when both operands are truthy
245-
253+
246254 result = evaluate ("0 && 'unreachable'" )
247255 assert result is False # Returns boolean False when first operand is falsy
248256
@@ -251,15 +259,15 @@ def test_edge_cases_and_special_values(self):
251259 # Unicode strings
252260 assert evaluate ("'🌍' ? 'truthy' : 'falsy'" ) == "truthy"
253261 assert evaluate ("!''" ) == 1 # Empty string is falsy
254-
262+
255263 # Large numbers
256264 assert evaluate ("!9999999999" ) == 0
257265 assert evaluate ("!0.0000001" ) == 0
258-
266+
259267 # Negative numbers
260268 assert evaluate ("!-1" ) == 0
261269 assert evaluate ("!-42" ) == 0
262-
270+
263271 # Floating point edge cases
264272 assert evaluate ("!0.0" ) == 1
265- assert evaluate ("!-0.0" ) == 1
273+ assert evaluate ("!-0.0" ) == 1
0 commit comments