Skip to content

Commit 9cbe1ef

Browse files
committed
Added prepare state to test implementation
1 parent 0c2fc69 commit 9cbe1ef

9 files changed

Lines changed: 282 additions & 9 deletions

codeplain_REST_api.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,42 @@ def prepare_implementation(
173173

174174
return self.post_request(endpoint_url, headers, payload, run_state)
175175

176+
def prepare_conformance_implementation(
177+
self,
178+
frid: str,
179+
functional_requirement_id: str,
180+
plain_source_tree: dict,
181+
linked_resources: dict,
182+
existing_files_content: dict,
183+
memory_files_content: dict,
184+
module_name: str,
185+
required_modules: dict,
186+
conformance_tests_folder_name: str,
187+
conformance_tests_json: dict,
188+
all_acceptance_tests: list[str],
189+
run_state: RunState,
190+
prepare_conformance_implementation_script: str,
191+
) -> dict:
192+
endpoint_url = f"{self.api_url}/prepare_conformance_implementation"
193+
headers = {"X-API-Key": self.api_key, "Content-Type": "application/json"}
194+
195+
payload = {
196+
"frid": frid,
197+
"functional_requirement_id": functional_requirement_id,
198+
"plain_source_tree": plain_source_tree,
199+
"linked_resources": linked_resources,
200+
"existing_files_content": existing_files_content,
201+
"memory_files_content": memory_files_content,
202+
"module_name": module_name,
203+
"required_modules": required_modules,
204+
"conformance_tests_folder_name": conformance_tests_folder_name,
205+
"conformance_tests_json": conformance_tests_json,
206+
"all_acceptance_tests": all_acceptance_tests,
207+
"prepare_conformance_implementation_script": prepare_conformance_implementation_script,
208+
}
209+
210+
return self.post_request(endpoint_url, headers, payload, run_state)
211+
176212
def render_functional_requirement(
177213
self,
178214
frid: str,
@@ -325,6 +361,7 @@ def render_conformance_tests(
325361
conformance_tests_json,
326362
all_acceptance_tests,
327363
run_state: RunState,
364+
conformance_test_fix_information: Optional[str] = None,
328365
):
329366
endpoint_url = f"{self.api_url}/render_conformance_tests"
330367
headers = {"X-API-Key": self.api_key, "Content-Type": "application/json"}
@@ -343,6 +380,9 @@ def render_conformance_tests(
343380
"all_acceptance_tests": all_acceptance_tests,
344381
}
345382

383+
if conformance_test_fix_information is not None:
384+
payload["conformance_test_fix_information"] = conformance_test_fix_information
385+
346386
response = self.post_request(endpoint_url, headers, payload, run_state)
347387
return response["patched_response_files"], response["conformance_tests_plan_summary_string"]
348388

@@ -476,6 +516,7 @@ def render_acceptance_tests(
476516
required_modules,
477517
acceptance_test,
478518
run_state: RunState,
519+
conformance_test_fix_information: Optional[str] = None,
479520
):
480521
"""
481522
Renders acceptance tests based on the provided parameters.
@@ -493,6 +534,8 @@ def render_acceptance_tests(
493534
required_modules (dict): A dictionary where the keys represent module names
494535
and the values are lists of functionalities implemented in those modules.
495536
acceptance_test (dict): A dictionary containing acceptance test information.
537+
conformance_test_fix_information (str, optional): Additional information produced by the
538+
prepare_conformance_test_fix_script.
496539
497540
Returns:
498541
dict: The rendered acceptance tests.
@@ -515,6 +558,9 @@ def render_acceptance_tests(
515558
"acceptance_test": acceptance_test,
516559
}
517560

561+
if conformance_test_fix_information is not None:
562+
payload["conformance_test_fix_information"] = conformance_test_fix_information
563+
518564
return self.post_request(endpoint_url, headers, payload, run_state)
519565

520566
def analyze_rendering(
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from typing import Any
2+
3+
import plain_spec
4+
import render_machine.render_utils as render_utils
5+
from memory_management import MemoryManager
6+
from render_machine.actions.base_action import BaseAction
7+
from render_machine.implementation_code_helpers import ImplementationCodeHelpers
8+
from render_machine.render_context import RenderContext
9+
from render_machine.render_types import RenderError
10+
11+
12+
class PrepareConformanceImplementationInformation(BaseAction):
13+
SUCCESSFUL_OUTCOME = "conformance_implementation_information_prepared"
14+
FAILED_OUTCOME = "conformance_implementation_information_preparation_failed"
15+
16+
def execute(self, render_context: RenderContext, _previous_action_payload: Any | None):
17+
_, existing_files_content = ImplementationCodeHelpers.fetch_existing_files(render_context.build_folder)
18+
_, memory_files_content = MemoryManager.fetch_memory_files(render_context.memory_manager.memory_folder)
19+
20+
with open(render_context.prepare_conformance_test_fix_script, "r", encoding="utf-8") as f:
21+
prepare_conformance_implementation_script_content = f.read()
22+
23+
# Check if conformance tests folder exists yet
24+
if render_context.conformance_tests_running_context.current_conformance_tests_exist():
25+
conformance_tests_folder_name = (
26+
render_context.conformance_tests_running_context.get_current_conformance_test_folder_name()
27+
)
28+
else:
29+
# Folder will be generated later by RenderConformanceTests action
30+
conformance_tests_folder_name = ""
31+
32+
# Determine which acceptance tests to include based on phase
33+
# Phase 0 = rendering conformance tests (include all acceptance tests)
34+
# Phase > 0 = rendering specific acceptance test (include only that one)
35+
if render_context.conformance_tests_running_context.conformance_test_phase_index == 0:
36+
# Preparing for conformance tests rendering - include all acceptance tests
37+
all_acceptance_tests = render_context.frid_context.specifications.get(plain_spec.ACCEPTANCE_TESTS, [])
38+
else:
39+
# Preparing for acceptance test rendering - include only the current one
40+
acceptance_test = render_context.conformance_tests_running_context.get_current_acceptance_test()
41+
all_acceptance_tests = [acceptance_test] if acceptance_test else []
42+
43+
api_response = render_context.codeplain_api.prepare_conformance_implementation(
44+
frid=render_context.frid_context.frid,
45+
functional_requirement_id=render_context.conformance_tests_running_context.current_testing_frid,
46+
plain_source_tree=render_context.plain_source_tree,
47+
linked_resources=render_context.frid_context.linked_resources,
48+
existing_files_content=existing_files_content,
49+
memory_files_content=memory_files_content,
50+
module_name=render_context.module_name,
51+
required_modules=render_context.get_required_modules_functionalities(),
52+
conformance_tests_folder_name=conformance_tests_folder_name,
53+
conformance_tests_json=render_context.conformance_tests_running_context.get_conformance_tests_json(
54+
render_context.conformance_tests_running_context.current_testing_module_name
55+
),
56+
all_acceptance_tests=all_acceptance_tests,
57+
run_state=render_context.run_state,
58+
prepare_conformance_implementation_script=prepare_conformance_implementation_script_content,
59+
)
60+
instructions = api_response.get("instructions", "")
61+
62+
exit_code, conformance_implementation_information, script_output_path = render_utils.execute_script(
63+
render_context.prepare_conformance_test_fix_script,
64+
[instructions],
65+
render_context.verbose,
66+
"Prepare Conformance Implementation Information",
67+
timeout=render_context.test_script_timeout,
68+
stop_event=render_context.stop_event,
69+
)
70+
71+
if exit_code == 0 or exit_code == render_utils.TIMEOUT_ERROR_EXIT_CODE:
72+
render_context.conformance_tests_running_context.conformance_implementation_information = (
73+
conformance_implementation_information
74+
)
75+
render_context.script_execution_history.latest_prepare_conformance_implementation_output_path = (
76+
script_output_path
77+
)
78+
render_context.script_execution_history.should_update_script_outputs = True
79+
return self.SUCCESSFUL_OUTCOME, None
80+
81+
return (
82+
self.FAILED_OUTCOME,
83+
RenderError.encode(
84+
message="Prepare conformance implementation information failed. Please check the prepare_conformance_test_fix_script.",
85+
error_type="PREPARE_CONFORMANCE_IMPLEMENTATION_ERROR",
86+
exit_code=exit_code,
87+
script=render_context.prepare_conformance_test_fix_script,
88+
).to_payload(),
89+
)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from typing import Any
2+
3+
import render_machine.render_utils as render_utils
4+
from memory_management import MemoryManager
5+
from plain2code_console import console
6+
from plain2code_exceptions import InternalClientError
7+
from render_machine.actions.base_action import BaseAction
8+
from render_machine.implementation_code_helpers import ImplementationCodeHelpers
9+
from render_machine.render_context import RenderContext
10+
from render_machine.render_types import RenderError
11+
12+
13+
class PrepareConformanceTestFix(BaseAction):
14+
SUCCESSFUL_OUTCOME = "conformance_test_fix_prepared"
15+
FAILED_OUTCOME = "conformance_test_fix_preparation_failed"
16+
17+
def execute(self, render_context: RenderContext, previous_action_payload: Any | None):
18+
if render_context.verbose:
19+
console.info(
20+
f"Running prepare_conformance_test_fix_script for FRID "
21+
f"{render_context.conformance_tests_running_context.current_testing_frid}."
22+
)
23+
24+
if not previous_action_payload or not previous_action_payload.get("previous_conformance_tests_issue"):
25+
raise InternalClientError("Previous action payload does not contain previous conformance tests issue.")
26+
previous_conformance_tests_issue = previous_action_payload["previous_conformance_tests_issue"]
27+
28+
_, existing_files_content = ImplementationCodeHelpers.fetch_existing_files(render_context.build_folder)
29+
_, memory_files_content = MemoryManager.fetch_memory_files(render_context.memory_manager.memory_folder)
30+
(
31+
_,
32+
existing_conformance_test_files_content,
33+
) = render_context.conformance_tests.fetch_existing_conformance_test_files(
34+
render_context.module_name,
35+
render_context.required_modules,
36+
render_context.conformance_tests_running_context.current_testing_module_name,
37+
render_context.conformance_tests_running_context.get_current_conformance_test_folder_name(),
38+
)
39+
previous_frid_code_diff = ImplementationCodeHelpers.get_code_diff(
40+
render_context.build_folder, render_context.plain_source_tree, render_context.frid_context.frid
41+
)
42+
43+
with open(render_context.prepare_conformance_test_fix_script, "r", encoding="utf-8") as f:
44+
script_content = f.read()
45+
46+
api_response = render_context.codeplain_api.prepare_conformance_test_fix(
47+
frid=render_context.frid_context.frid,
48+
functional_requirement_id=render_context.conformance_tests_running_context.current_testing_frid,
49+
plain_source_tree=render_context.plain_source_tree,
50+
linked_resources=render_context.frid_context.linked_resources,
51+
existing_files_content=existing_files_content,
52+
memory_files_content=memory_files_content,
53+
module_name=render_context.module_name,
54+
conformance_tests_module_name=(
55+
render_context.conformance_tests_running_context.current_testing_module_name
56+
),
57+
required_modules=render_context.get_required_modules_functionalities(),
58+
code_diff=previous_frid_code_diff,
59+
conformance_tests_files=existing_conformance_test_files_content,
60+
acceptance_tests=render_context.conformance_tests_running_context.get_current_acceptance_tests(),
61+
conformance_tests_issue=previous_conformance_tests_issue,
62+
implementation_fix_count=render_context.conformance_tests_running_context.fix_attempts,
63+
conformance_tests_folder_name=(
64+
render_context.conformance_tests_running_context.get_current_conformance_test_folder_name()
65+
),
66+
current_testing_frid_high_level_implementation_plan=(
67+
render_context.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan
68+
),
69+
run_state=render_context.run_state,
70+
prepare_conformance_test_fix_script=script_content,
71+
)
72+
73+
instructions = api_response.get("instructions", "")
74+
75+
exit_code, conformance_test_fix_information, script_output_path = render_utils.execute_script(
76+
render_context.prepare_conformance_test_fix_script,
77+
[instructions],
78+
render_context.verbose,
79+
"Prepare Conformance Test Fix",
80+
timeout=render_context.test_script_timeout,
81+
stop_event=render_context.stop_event,
82+
)
83+
84+
if exit_code == 0 or exit_code == render_utils.TIMEOUT_ERROR_EXIT_CODE:
85+
render_context.conformance_tests_running_context.conformance_test_fix_information = (
86+
conformance_test_fix_information
87+
)
88+
render_context.script_execution_history.latest_prepare_conformance_test_fix_output_path = script_output_path
89+
render_context.script_execution_history.should_update_script_outputs = True
90+
return (
91+
self.SUCCESSFUL_OUTCOME,
92+
{"previous_conformance_tests_issue": previous_conformance_tests_issue},
93+
)
94+
95+
return (
96+
self.FAILED_OUTCOME,
97+
RenderError.encode(
98+
message="Prepare conformance test fix failed. Please check the prepare_conformance_test_fix_script.",
99+
error_type="PREPARE_CONFORMANCE_TEST_FIX_ERROR",
100+
exit_code=exit_code,
101+
script=render_context.prepare_conformance_test_fix_script,
102+
).to_payload(),
103+
)

render_machine/actions/render_conformance_tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ def _render_conformance_tests(self, render_context: RenderContext):
114114
),
115115
all_acceptance_tests,
116116
run_state=render_context.run_state,
117+
conformance_test_fix_information=render_context.conformance_tests_running_context.conformance_implementation_information,
117118
)
118119

119120
render_context.conformance_tests_running_context.current_testing_frid_high_level_implementation_plan = (
@@ -166,6 +167,7 @@ def _render_acceptance_test(self, render_context: RenderContext):
166167
render_context.get_required_modules_functionalities(),
167168
acceptance_test,
168169
run_state=render_context.run_state,
170+
conformance_test_fix_information=render_context.conformance_tests_running_context.conformance_implementation_information,
169171
)
170172
conformance_tests_folder_name = (
171173
render_context.conformance_tests_running_context.get_current_conformance_test_folder_name()

render_machine/render_context.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ def start_prepare_conformance_test_fix(self):
354354
if self.prepare_conformance_test_fix_script is None:
355355
self.machine.dispatch(triggers.MARK_CONFORMANCE_TEST_FIX_PREPARED)
356356

357+
def start_prepare_conformance_implementation_information(self):
358+
if self.prepare_conformance_test_fix_script is None:
359+
self.machine.dispatch(triggers.MARK_CONFORMANCE_IMPLEMENTATION_INFORMATION_PREPARED)
360+
357361
def start_testing_environment_preparation(self):
358362
if (
359363
self.prepare_environment_script is None
@@ -400,6 +404,10 @@ def start_conformance_tests_for_frid(self):
400404
self.conformance_tests_running_context.current_testing_module_name == self.module_name
401405
and self.conformance_tests_running_context.current_testing_frid == self.frid_context.frid
402406
):
407+
if self.conformance_tests_running_context.regression_run_started:
408+
# Regression cycle complete — all required modules and previous FRIDs re-verified
409+
self.machine.dispatch(triggers.MARK_ALL_CONFORMANCE_TESTS_PASSED)
410+
return
403411
if not self.frid_context.specifications.get(
404412
plain_spec.ACCEPTANCE_TESTS
405413
) or self.conformance_tests_running_context.conformance_test_phase_index == len(
@@ -415,14 +423,14 @@ def start_conformance_tests_for_frid(self):
415423
None
416424
)
417425

418-
self.conformance_tests_running_context.conformance_test_phase_index += 1
419-
current_acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][
420-
: self.conformance_tests_running_context.conformance_test_phase_index
421-
]
422-
self.conformance_tests_running_context.get_conformance_tests_json(
423-
self.conformance_tests_running_context.current_testing_module_name
424-
)[self.frid_context.frid][plain_spec.ACCEPTANCE_TESTS] = current_acceptance_tests
425-
return
426+
self.conformance_tests_running_context.conformance_test_phase_index += 1
427+
current_acceptance_tests = self.frid_context.specifications[plain_spec.ACCEPTANCE_TESTS][
428+
: self.conformance_tests_running_context.conformance_test_phase_index
429+
]
430+
self.conformance_tests_running_context.get_conformance_tests_json(
431+
self.conformance_tests_running_context.current_testing_module_name
432+
)[self.frid_context.frid][plain_spec.ACCEPTANCE_TESTS] = current_acceptance_tests
433+
return
426434

427435
if self.conformance_tests_running_context.current_testing_frid is None:
428436
self.conformance_tests_running_context = self.get_first_conformance_tests_running_context()

render_machine/render_types.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ def __init__(
4343
self.conformance_test_phase_index = conformance_test_phase_index
4444
self.should_prepare_testing_environment = should_prepare_testing_environment
4545

46+
self.regression_run_started: bool = False
4647
# will be propagated only when:
4748
# - current_testing_frid == frid noqa: E800
4849
# - conformance_test_phase_index == 0 (conformance tests phase)
4950
self.regenerating_conformance_tests: bool = False
5051
self.current_testing_frid_high_level_implementation_plan: Optional[str] = None
52+
self.conformance_implementation_information: Optional[str] = None
5153
self.previous_conformance_tests_issue_old: Optional[str] = None
5254
self.previous_conformance_tests_issue_frid: Optional[str] = None
5355
self.previous_conformance_tests_issue_module: Optional[str] = None
@@ -111,6 +113,7 @@ class ScriptExecutionHistory:
111113
latest_testing_environment_output_path: Optional[str] = None
112114
latest_prepare_implementation_output_path: Optional[str] = None
113115
latest_prepare_conformance_test_fix_output_path: Optional[str] = None
116+
latest_prepare_conformance_implementation_output_path: Optional[str] = None
114117
should_update_script_outputs: bool = False
115118

116119

0 commit comments

Comments
 (0)