@@ -90,7 +90,9 @@ def test_final_var_answer(self):
9090 text = "Check the variable:\n FINAL_VAR(result)"
9191 # Create a mock environment that returns the variable value
9292 mock_env = Mock ()
93- mock_env .execute_code .return_value = REPLResult (stdout = "42" , stderr = "" , locals = {})
93+ mock_env .execute_code .return_value = REPLResult (
94+ stdout = "42" , stderr = "" , locals = {}
95+ )
9496 result = find_final_answer (text , environment = mock_env )
9597 assert result == "42"
9698 # Verify execute_code was called with the correct code
@@ -128,6 +130,33 @@ def test_final_with_whitespace(self):
128130 result = find_final_answer (text )
129131 assert result == "answer with spaces"
130132
133+ def test_final_with_nested_parentheses_greedy_matching (self ):
134+ """Test that greedy matching captures content with nested parentheses correctly.
135+ Greedy matching (.*) matches to the last closing parenthesis, correctly handling
136+ nested parentheses in FINAL() content. Non-greedy (.*?) would incorrectly stop
137+ at the first closing parenthesis, breaking functions, tuples, and nested structures.
138+ """
139+ # Function call with nested parentheses
140+ text = "FINAL(func(arg1, arg2))"
141+ result = find_final_answer (text )
142+ assert result == "func(arg1, arg2)"
143+
144+ # List and tuple with multiple closing parentheses
145+ text = "FINAL([1, 2, 3], (4, 5))"
146+ result = find_final_answer (text )
147+ assert result == "[1, 2, 3], (4, 5)"
148+
149+ # Complex nested dictionary
150+ text = "FINAL({'key': 'value', 'nested': {'a': 1, 'b': 2}})"
151+ result = find_final_answer (text )
152+ assert "'key': 'value'" in result
153+ assert "'nested':" in result
154+
155+ # Multiple function calls with nested parentheses
156+ text = "FINAL(calculate(10, 20) + process(data))"
157+ result = find_final_answer (text )
158+ assert result == "calculate(10, 20) + process(data)"
159+
131160 def test_final_and_final_var_parsing (self ):
132161 """Test that both FINAL and FINAL_VAR patterns are parsed correctly."""
133162 # Test FINAL with various content types
@@ -170,7 +199,9 @@ def test_final_and_final_var_parsing(self):
170199 def test_final_var_takes_precedence_over_final (self ):
171200 """Test that FINAL_VAR is checked first and takes precedence over FINAL."""
172201 mock_env = Mock ()
173- mock_env .execute_code .return_value = REPLResult (stdout = "var_value" , stderr = "" , locals = {})
202+ mock_env .execute_code .return_value = REPLResult (
203+ stdout = "var_value" , stderr = "" , locals = {}
204+ )
174205
175206 # If both appear, FINAL_VAR should be found first (checked first in the function)
176207 text = "FINAL_VAR(result)\n FINAL(direct_answer)"
@@ -213,7 +244,9 @@ def test_final_var_retrieves_actual_variables_from_environment(self):
213244 # Test retrieving list variable
214245 text = "FINAL_VAR(answer)"
215246 result = find_final_answer (text , environment = env )
216- assert result == "[1, 2, 3, 4, 5]" , f"Expected '[1, 2, 3, 4, 5]', got '{ result } '"
247+ assert (
248+ result == "[1, 2, 3, 4, 5]"
249+ ), f"Expected '[1, 2, 3, 4, 5]', got '{ result } '"
217250
218251 # Test retrieving computed variable
219252 text = "FINAL_VAR(computed)"
0 commit comments