Skip to content

Commit b9e0721

Browse files
committed
UI changes.
1 parent 3707913 commit b9e0721

6 files changed

Lines changed: 151 additions & 222 deletions

File tree

module_renderer.py

Lines changed: 13 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22
import os
33
import threading
44

5-
import git_utils
6-
import plain_file
7-
import plain_spec
85
from event_bus import EventBus
96
from memory_management import MemoryManager
10-
from partial_rendering import PartialRenderChoice
7+
from partial_rendering import RenderChoice
118
from plain2code_console import console
129
from plain2code_events import RenderCompleted, RenderFailed
13-
from plain2code_exceptions import MissingPreviousFunctionalitiesError
1410
from plain2code_state import RunState
1511
from plain_modules import PlainModule
1612
from render_machine.code_renderer import CodeRenderer
@@ -24,7 +20,7 @@ def __init__(
2420
self,
2521
codeplainAPI,
2622
plain_module: PlainModule,
27-
partial_render_choice: PartialRenderChoice | None,
23+
render_choice: RenderChoice | None,
2824
render_range: list[str] | None,
2925
args: argparse.Namespace,
3026
run_state: RunState,
@@ -34,126 +30,14 @@ def __init__(
3430
):
3531
self.codeplainAPI = codeplainAPI
3632
self.plain_module = plain_module
37-
self.partial_render_choice = partial_render_choice
33+
self.render_choice = render_choice
3834
self.render_range = render_range
3935
self.args = args
4036
self.run_state = run_state
4137
self.event_bus = event_bus
4238
self.stop_event = stop_event
4339
self.enter_pause_event = enter_pause_event
4440

45-
def _ensure_module_folders_exist(self, module_name: str, first_render_frid: str) -> tuple[str, str]:
46-
"""
47-
Ensure that build and conformance test folders exist for the module.
48-
49-
Args:
50-
module_name: Name of the module being rendered
51-
first_render_frid: The first FRID in the render range
52-
53-
Returns:
54-
tuple[str, str]: (build_folder_path, conformance_tests_path)
55-
56-
Raises:
57-
MissingPreviousFridCommitsError: If any required folders are missing
58-
"""
59-
build_folder_path = os.path.join(self.args.build_folder, module_name)
60-
conformance_tests_path = os.path.join(self.args.conformance_tests_folder, module_name)
61-
62-
if not os.path.exists(build_folder_path):
63-
raise MissingPreviousFunctionalitiesError(
64-
"Error rendering plain code: "
65-
f"Cannot start rendering from functionality {first_render_frid} for module '{module_name}' because the source code folder does not exist.\n\n"
66-
f"To fix this, please render the module from the beginning by running:\n"
67-
f" codeplain {module_name}{plain_file.PLAIN_SOURCE_FILE_EXTENSION}\n"
68-
)
69-
70-
if not os.path.exists(conformance_tests_path) and self.args.render_conformance_tests:
71-
raise MissingPreviousFunctionalitiesError(
72-
"Error rendering plain code: "
73-
f"Cannot start rendering from functionality {first_render_frid} for module '{module_name}' because the conformance tests folder does not exist.\n\n"
74-
f"To fix this, please render the module from the beginning by running:\n"
75-
f" codeplain {module_name}{plain_file.PLAIN_SOURCE_FILE_EXTENSION}\n"
76-
)
77-
78-
return build_folder_path, conformance_tests_path
79-
80-
def _ensure_frid_commit_exists(
81-
self,
82-
frid: str,
83-
module_name: str,
84-
build_folder_path: str,
85-
conformance_tests_path: str,
86-
first_render_frid: str,
87-
) -> None:
88-
"""
89-
Ensure commit exists for a single FRID in both repositories.
90-
91-
Args:
92-
frid: The FRID to check
93-
module_name: Name of the module
94-
build_folder_path: Path to the build folder
95-
conformance_tests_path: Path to the conformance tests folder
96-
first_render_frid: The first FRID in the render range (for error messages)
97-
98-
Raises:
99-
MissingPreviousFridCommitsError: If the commit is missing
100-
"""
101-
# Check in build folder
102-
if not git_utils.has_commit_for_frid(build_folder_path, frid, module_name):
103-
raise MissingPreviousFunctionalitiesError(
104-
"Error rendering plain code: "
105-
f"Cannot start rendering from functionality {first_render_frid} for module '{module_name}' because the implementation of the previous functionality ({frid}) hasn't been completed yet.\n\n"
106-
f"To fix this, please render the missing functionality ({frid}) first by running:\n"
107-
f" codeplain {module_name}{plain_file.PLAIN_SOURCE_FILE_EXTENSION} --render-from {frid}\n"
108-
)
109-
110-
# Check in conformance tests folder (only if conformance tests are enabled)
111-
if self.args.render_conformance_tests:
112-
if not git_utils.has_commit_for_frid(conformance_tests_path, frid, module_name):
113-
raise MissingPreviousFunctionalitiesError(
114-
"Error rendering plain code: "
115-
f"Cannot start rendering from functionality {first_render_frid} for module '{module_name}' because the conformance tests for the previous functionality ({frid}) haven't been completed yet.\n\n"
116-
f"To fix this, please render the missing functionality ({frid}) first by running:\n"
117-
f" codeplain {module_name}{plain_file.PLAIN_SOURCE_FILE_EXTENSION} --render-from {frid}\n"
118-
)
119-
120-
def _ensure_previous_frid_commits_exist(
121-
self, module_name: str, plain_source: dict, render_range: list[str]
122-
) -> None:
123-
"""
124-
Ensure that all FRID commits before the render_range exist.
125-
126-
This is a precondition check that must pass before rendering can proceed.
127-
Raises an exception if any previous FRID commits are missing.
128-
129-
Args:
130-
module_name: Name of the module being rendered
131-
plain_source: The plain source tree
132-
render_range: List of FRIDs to render
133-
134-
Raises:
135-
MissingPreviousFridCommitsError: If any previous FRID commits are missing
136-
"""
137-
first_render_frid = render_range[0]
138-
139-
# Get all FRIDs that should have been rendered before this one
140-
previous_frids = plain_spec.get_frids_before(plain_source, first_render_frid)
141-
if not previous_frids:
142-
return
143-
144-
# Ensure the module folders exist
145-
build_folder_path, conformance_tests_path = self._ensure_module_folders_exist(module_name, first_render_frid)
146-
147-
# Verify commits exist for all previous FRIDs
148-
for prev_frid in previous_frids:
149-
self._ensure_frid_commit_exists(
150-
prev_frid,
151-
module_name,
152-
build_folder_path,
153-
conformance_tests_path,
154-
first_render_frid,
155-
)
156-
15741
def _build_render_context_for_module(
15842
self,
15943
plain_module: PlainModule,
@@ -192,20 +76,20 @@ def _render_module(
19276
Returns:
19377
tuple[bool, bool]: (Whether the module was rendered and whether the rendering failed)
19478
"""
195-
is_partial_render_choice_module = (
196-
self.partial_render_choice is not None
197-
and self.partial_render_choice.module is not None
198-
and self.partial_render_choice.module.module_name == plain_module.module_name
79+
is_render_choice_module = (
80+
self.render_choice is not None
81+
and self.render_choice.module is not None
82+
and self.render_choice.module.module_name == plain_module.module_name
19983
)
20084

201-
if is_partial_render_choice_module:
202-
render_range = self.partial_render_choice.render_range
85+
if is_render_choice_module:
86+
render_range = self.render_choice.render_range
20387

20488
if render_range is not None:
20589
plain_module.ensure_previous_frid_commits_exist(render_range, self.args.render_conformance_tests)
20690

20791
has_any_required_module_changed = False
208-
if not self.args.render_machine_graph and plain_module.required_modules and not is_partial_render_choice_module:
92+
if not self.args.render_machine_graph and plain_module.required_modules and not is_render_choice_module:
20993
console.debug(f"Analyzing required modules of module {plain_module.module_name}...")
21094
for required_module in plain_module.required_modules:
21195
has_module_changed, rendering_failed = self._render_module(
@@ -226,7 +110,7 @@ def _render_module(
226110
and not has_any_required_module_changed
227111
and not plain_module.has_plain_spec_changed()
228112
and not plain_module.has_required_modules_code_changed()
229-
and not is_partial_render_choice_module
113+
and not is_render_choice_module
230114
):
231115
return False, False
232116

@@ -264,11 +148,11 @@ def _render_module(
264148
return True, False
265149

266150
def render_module(self) -> None:
267-
if self.partial_render_choice is not None and self.partial_render_choice.wipe_later_modules:
151+
if self.render_choice is not None and self.render_choice.wipe_later_modules:
268152
later_module = False
269153
all_modules = self.plain_module.all_required_modules + [self.plain_module]
270154
for module in all_modules:
271-
if module.module_name == self.partial_render_choice.module.module_name:
155+
if module.module_name == self.render_choice.module.module_name:
272156
later_module = True
273157
continue
274158

partial_rendering.py

Lines changed: 66 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77

88

99
@dataclass
10-
class PartialRender:
10+
class PlainModuleRenderState:
1111
last_render_module: PlainModule
1212
last_render_frid: str | None
1313
change: PlainModule | None = None
1414
change_type: Literal["spec_change", "code_change"] | None = None
1515

1616

1717
@dataclass
18-
class PartialRenderChoice:
18+
class RenderChoice:
1919
module: PlainModule | None = None
2020
render_range: list[str] | None = None
21-
msg: str | None = None
2221
wipe_later_modules: bool = False
23-
is_desctructive: bool = False
22+
is_destructive: bool = False
23+
choice_type: str | None = None
2424

2525

2626
def spec_change(plain_module: PlainModule) -> PlainModule | None:
@@ -70,7 +70,7 @@ def module_comes_before_or_equal(
7070
raise ValueError(f"Module {module1.module_name} and {module2.module_name} not found in {all_required_modules}")
7171

7272

73-
def detect_partial_rendering(plain_module: PlainModule) -> PartialRender | None:
73+
def get_plain_module_render_state(plain_module: PlainModule) -> PlainModuleRenderState | None:
7474
sc = spec_change(plain_module)
7575
cc = code_change(plain_module)
7676
all_required_modules = plain_module.all_required_modules
@@ -92,7 +92,7 @@ def detect_partial_rendering(plain_module: PlainModule) -> PartialRender | None:
9292
)
9393
module = found_module
9494

95-
pr = PartialRender(
95+
pr = PlainModuleRenderState(
9696
last_render_module=module,
9797
last_render_frid=last_rendered_frid,
9898
change=None,
@@ -116,91 +116,109 @@ def detect_partial_rendering(plain_module: PlainModule) -> PartialRender | None:
116116
return pr
117117

118118

119-
def get_choices(
119+
def get_all_affected_modules_from_change(
120120
plain_module: PlainModule,
121-
partial_render: PartialRender,
121+
plain_module_render_state: PlainModuleRenderState,
122+
) -> list[PlainModule]:
123+
all_affected_modules = list[PlainModule]()
124+
125+
if plain_module_render_state.change_type == "spec_change":
126+
start_module = plain_module_render_state.change
127+
elif plain_module_render_state.change_type == "code_change":
128+
if plain_module_render_state.change.is_module_fully_rendered():
129+
start_module = plain_module.get_next_module(plain_module_render_state.change.module_name)
130+
else:
131+
start_module = plain_module_render_state.change
132+
else:
133+
raise ValueError(f"Unknown change type: {plain_module_render_state.change_type}")
134+
135+
affected_module = False
136+
all_modules = plain_module.all_required_modules + [plain_module]
137+
for module in all_modules:
138+
if module.module_name == start_module.module_name:
139+
affected_module = True
140+
141+
if affected_module:
142+
all_affected_modules.append(module)
143+
144+
return all_affected_modules
145+
146+
147+
def get_render_choices(
148+
plain_module: PlainModule,
149+
plain_module_render_state: PlainModuleRenderState,
122150
force_render: bool = False,
123-
) -> dict[str, PartialRenderChoice]:
124-
choices = dict[str, PartialRenderChoice]()
151+
) -> dict[str, RenderChoice]:
152+
choices = dict[str, RenderChoice]()
125153
choice_idx = 1
126154

127-
if partial_render.last_render_module.is_initial_module():
128-
choices[str(choice_idx)] = PartialRenderChoice(
129-
module=partial_render.last_render_module,
155+
if plain_module_render_state.last_render_module.is_initial_module():
156+
choices[str(choice_idx)] = RenderChoice(
157+
module=plain_module_render_state.last_render_module,
130158
render_range=None,
131-
msg=f"Start from module [#5593FF]{partial_render.last_render_module.module_name}[/]",
159+
choice_type="module_start",
132160
wipe_later_modules=True,
133-
is_desctructive=False,
161+
is_destructive=False,
134162
)
135163
choice_idx += 1
136164

137-
elif not partial_render.last_render_module.is_module_fully_rendered():
138-
if not partial_render.last_render_frid:
165+
elif not plain_module_render_state.last_render_module.is_module_fully_rendered():
166+
if not plain_module_render_state.last_render_frid:
139167
raise ValueError("Last render FRID is not set for a non-initial module")
140168

141169
next_frid, next_module = plain_module.get_next_frid(
142-
partial_render.last_render_frid, partial_render.last_render_module.module_name
170+
plain_module_render_state.last_render_frid, plain_module_render_state.last_render_module.module_name
143171
)
144172
render_range = plain_spec.get_render_range_from(next_frid, next_module.plain_source)
145-
msg = "Continue from"
146-
if next_frid != plain_spec.get_first_frid(next_module.plain_source):
147-
msg += f" functionality [#5593FF]{next_frid}[/]"
148-
else:
149-
msg += f" module [#5593FF]{next_module.module_name}[/]"
150173

151-
choices[str(choice_idx)] = PartialRenderChoice(
174+
choices[str(choice_idx)] = RenderChoice(
152175
module=next_module,
153176
render_range=render_range if not force_render else None,
154177
wipe_later_modules=force_render,
155-
msg=msg,
178+
choice_type="continue_from_frid",
156179
)
157180
choice_idx += 1
158181

159182
else:
160-
next_module = plain_module.get_next_module(partial_render.last_render_module.module_name)
183+
next_module = plain_module.get_next_module(plain_module_render_state.last_render_module.module_name)
161184
if next_module is None:
162-
next_module = partial_render.last_render_module
185+
next_module = plain_module_render_state.last_render_module
163186

164-
choices[str(choice_idx)] = PartialRenderChoice(
187+
choices[str(choice_idx)] = RenderChoice(
165188
module=next_module,
166189
render_range=None,
167-
msg=f"Start from module [#5593FF]{next_module.module_name}[/]",
168-
is_desctructive=partial_render.last_render_module.module_name == plain_module.module_name,
190+
is_destructive=plain_module_render_state.last_render_module.module_name == plain_module.module_name,
191+
choice_type="module_start",
169192
)
170193
choice_idx += 1
171194

172-
if partial_render.change:
173-
all_affected_modules = list[str]()
174-
affected_module = False
175-
for module in plain_module.all_required_modules:
176-
if module.module_name == partial_render.change.module_name:
177-
affected_module = True
178-
if affected_module:
179-
all_affected_modules.append(module.module_name)
195+
if plain_module_render_state.change:
196+
all_affected_modules = get_all_affected_modules_from_change(plain_module, plain_module_render_state)
180197

181198
if len(all_affected_modules) > 0:
182-
choices[str(choice_idx)] = PartialRenderChoice(
183-
module=partial_render.change,
199+
choices[str(choice_idx)] = RenderChoice(
200+
module=all_affected_modules[0],
184201
render_range=None,
185-
msg=f"Re-render all affected modules ([#5593FF]{', '.join(all_affected_modules)}[/])",
202+
choice_type="rerender_affected",
186203
wipe_later_modules=True,
187-
is_desctructive=True,
204+
is_destructive=True,
188205
)
189206
choice_idx += 1
190207

191208
if len(plain_module.all_required_modules) > 0:
192209
first_module = plain_module.all_required_modules[0]
193-
if first_module.module_name != partial_render.last_render_module.module_name and (
194-
partial_render.change is not None and first_module.module_name != partial_render.change.module_name
210+
if first_module.module_name != plain_module_render_state.last_render_module.module_name and (
211+
plain_module_render_state.change is not None
212+
and first_module.module_name != plain_module_render_state.change.module_name
195213
):
196-
choices[str(choice_idx)] = PartialRenderChoice(
214+
choices[str(choice_idx)] = RenderChoice(
197215
module=first_module,
198216
render_range=None,
199-
msg=f"Re-render from first module ([#5593FF]{first_module.module_name}[/])",
217+
choice_type="rerender_from_first",
200218
wipe_later_modules=True,
201-
is_desctructive=True,
219+
is_destructive=True,
202220
)
203221
choice_idx += 1
204222

205-
choices[str(choice_idx)] = PartialRenderChoice(module=None, render_range=None, msg="Quit")
223+
choices[str(choice_idx)] = RenderChoice(module=None, render_range=None, choice_type="quit")
206224
return choices

0 commit comments

Comments
 (0)