Skip to content

Commit 511afbe

Browse files
Add color param to console log methods so file logs stay plain text
1 parent f672dd6 commit 511afbe

13 files changed

Lines changed: 206 additions & 51 deletions

‎codeplain_REST_api.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from requests.exceptions import ConnectionError, RequestException, Timeout
66

77
import plain2code_exceptions
8+
from plain2code_console import RETRY_COLOR
89
from plain2code_state import RunState
910

1011
MAX_RETRIES = 4
@@ -68,8 +69,9 @@ def _handle_retry_logic(
6869
if attempt < num_retries:
6970
if not silent:
7071
self.console.debug(
71-
f"[#FFB454]↻ {connection_error_type} on attempt {attempt + 1}/{num_retries + 1}: {error}. "
72-
f"Retrying in {retry_delay} seconds...[/#FFB454]"
72+
f"↻ {connection_error_type} on attempt {attempt + 1}/{num_retries + 1}: {error}. "
73+
f"Retrying in {retry_delay} seconds...",
74+
color=RETRY_COLOR,
7375
)
7476
time.sleep(retry_delay)
7577
# Exponential backoff

‎plain2code_console.py‎

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111

1212
logger = logging.getLogger(plain2code_logger.LOGGER_NAME)
1313

14+
# Colors for log messages, applied by the terminal and the TUI via the "color"
15+
# parameter of the console methods. The file log always receives plain text.
16+
RETRY_COLOR = "#FFB454" # Amber
17+
SUCCESS_COLOR = "#79FC96" # Green
18+
MUTED_COLOR = "#888888" # Grey
19+
1420

1521
class Plain2CodeConsole(Console):
1622
INFO_STYLE = Style()
@@ -33,30 +39,37 @@ def __init__(self):
3339
logger.debug(f"Exception: {e}")
3440
self.llm_encoding = None
3541

36-
def info(self, *args, **kwargs):
37-
logger.info(" ".join(map(str, args)))
38-
super().print(*args, **kwargs, style=self.INFO_STYLE)
42+
def info(self, *args, color=None, **kwargs):
43+
self._log_and_print(logging.INFO, self.INFO_STYLE, args, color, kwargs)
3944

40-
def warning(self, *args, **kwargs):
41-
logger.warning(" ".join(map(str, args)))
42-
super().print(*args, **kwargs, style=self.WARNING_STYLE)
45+
def warning(self, *args, color=None, **kwargs):
46+
self._log_and_print(logging.WARNING, self.WARNING_STYLE, args, color, kwargs)
4347

44-
def error(self, *args, **kwargs):
45-
logger.error(" ".join(map(str, args)))
46-
super().print(*args, **kwargs, style=self.ERROR_STYLE)
48+
def error(self, *args, color=None, **kwargs):
49+
self._log_and_print(logging.ERROR, self.ERROR_STYLE, args, color, kwargs)
4750

48-
def input(self, *args, **kwargs):
51+
def input(self, *args, color=None, **kwargs):
4952
# We also log input as info so it shows in the toggled view
50-
logger.info(" ".join(map(str, args)))
51-
super().print(*args, **kwargs, style=self.INPUT_STYLE)
53+
self._log_and_print(logging.INFO, self.INPUT_STYLE, args, color, kwargs)
54+
55+
def output(self, *args, color=None, **kwargs):
56+
self._log_and_print(logging.INFO, self.OUTPUT_STYLE, args, color, kwargs)
5257

53-
def output(self, *args, **kwargs):
54-
logger.info(" ".join(map(str, args)))
55-
super().print(*args, **kwargs, style=self.OUTPUT_STYLE)
58+
def debug(self, *args, color=None, **kwargs):
59+
self._log_and_print(logging.DEBUG, self.DEBUG_STYLE, args, color, kwargs)
5660

57-
def debug(self, *args, **kwargs):
58-
logger.debug(" ".join(map(str, args)))
59-
super().print(*args, **kwargs, style=self.DEBUG_STYLE)
61+
def _log_and_print(self, level, base_style, args, color, kwargs):
62+
"""Log the plain message text, then print it styled to the terminal.
63+
64+
The optional color is applied by the terminal (via style) and forwarded to
65+
the TUI as the "log_color" record attribute; the file log stays plain text.
66+
"""
67+
logger.log(level, " ".join(map(str, args)), extra={"log_color": color})
68+
style = base_style + Style(color=color) if color else base_style
69+
# Log messages must render exactly as logged: don't interpret square brackets
70+
# in interpolated content (error texts, file names) as Rich markup.
71+
kwargs.setdefault("markup", False)
72+
super().print(*args, **kwargs, style=style)
6073

6174
def print_list(self, items, style=None):
6275
for item in items:
@@ -130,9 +143,7 @@ def print_resources(self, resources_list, linked_resources):
130143
for resource_name in resources_list:
131144
if resource_name["target"] in linked_resources:
132145
file_tokens = self._count_tokens(linked_resources[resource_name["target"]])
133-
self.debug(
134-
f"- {resource_name['text']} [#4169E1]({resource_name['target']}, {file_tokens} tokens)[/#4169E1]"
135-
)
146+
self.debug(f"- {resource_name['text']} ({resource_name['target']}, {file_tokens} tokens)")
136147

137148
self.input()
138149

‎plain2code_events.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class LogMessageEmitted(BaseEvent):
4444
level: str # e.g., "INFO", "DEBUG", "ERROR"
4545
message: str # The actual log message
4646
timestamp: str # Formatted timestamp
47+
log_color: Optional[str] = None # Color for the message (e.g. "#FFB454"); the file log stays plain text
4748

4849

4950
@dataclass

‎plain2code_logger.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def emit(self, record):
8888
level=record.levelname,
8989
message=record.getMessage(),
9090
timestamp=timestamp,
91+
log_color=getattr(record, "log_color", None),
9192
)
9293
self.event_bus.publish(event)
9394
except RuntimeError:

‎render_machine/actions/create_dist.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any
22

33
import file_utils
4-
from plain2code_console import console
4+
from plain2code_console import SUCCESS_COLOR, console
55
from render_machine.actions.base_action import BaseAction
66
from render_machine.render_context import RenderContext
77

@@ -21,6 +21,6 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any |
2121
render_context.conformance_tests.get_module_conformance_tests_folder(render_context.module_name),
2222
render_context.conformance_tests_dest,
2323
)
24-
console.info(f"[#79FC96]Render of module {render_context.module_name} completed successfully.[/#79FC96]")
24+
console.info(f"✓ Render of module {render_context.module_name} completed successfully.", color=SUCCESS_COLOR)
2525

2626
return self.SUCCESSFUL_OUTCOME, None

‎render_machine/actions/exit_with_error.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any |
2020

2121
if render_context.frid_context is not None:
2222
console.info(
23-
f"To continue rendering from the last successfully rendered functionality, provide the [red]--render-from {render_context.frid_context.frid}[/red] flag."
23+
f"To continue rendering from the last successfully rendered functionality, "
24+
f"provide the --render-from {render_context.frid_context.frid} flag."
2425
)
2526

2627
if render_context.run_state.render_id is not None:

‎render_machine/actions/fix_conformance_test.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import file_utils
55
import plain_spec
66
from memory_management import MemoryManager
7-
from plain2code_console import console
7+
from plain2code_console import RETRY_COLOR, console
88
from plain2code_exceptions import InternalClientError
99
from render_machine.actions.base_action import BaseAction
1010
from render_machine.implementation_code_helpers import ImplementationCodeHelpers
@@ -144,7 +144,9 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any |
144144
render_context.conformance_tests_running_context.conflicting_module_name = current_testing_module_name
145145
render_context.conformance_tests_running_context.conflicting_frid = current_testing_frid
146146
console.info(
147-
f"[#FFB454]Potential conflicting functionalities detected while fixing conformance tests for functionality {current_testing_frid} in module {current_testing_module_name}.[/#FFB454]"
147+
f"↻ Potential conflicting functionalities detected while fixing conformance tests "
148+
f"for functionality {current_testing_frid} in module {current_testing_module_name}.",
149+
color=RETRY_COLOR,
148150
)
149151

150152
if issue_reason_code == self.ISSUE_REASON_CODE_CONFORMANCE_TESTS:

‎render_machine/actions/render_functional_requirement.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import file_utils
44
import render_machine.render_utils as render_utils
55
from memory_management import MemoryManager
6-
from plain2code_console import console
6+
from plain2code_console import RETRY_COLOR, console
77
from plain2code_exceptions import FunctionalRequirementTooComplex
88
from render_machine.actions.base_action import BaseAction
99
from render_machine.implementation_code_helpers import ImplementationCodeHelpers
@@ -28,8 +28,9 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any |
2828

2929
if render_context.frid_context.functional_requirement_render_attempts > 1:
3030
console.info(
31-
f"[#FFB454]↻ Unittests could not be fixed after rendering the functionality. "
32-
f"Restarting rendering functionality {render_context.frid_context.frid} from scratch.[/#FFB454]"
31+
f"↻ Unittests could not be fixed after rendering the functionality. "
32+
f"Restarting rendering functionality {render_context.frid_context.frid} from scratch.",
33+
color=RETRY_COLOR,
3334
)
3435

3536
render_utils.revert_changes_for_frid(render_context)

‎render_machine/render_context.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import plain_spec
88
from codeplain_REST_api import CodeplainAPI
99
from event_bus import EventBus
10-
from plain2code_console import console
10+
from plain2code_console import RETRY_COLOR, console
1111
from plain2code_events import RenderContextSnapshot
1212
from plain2code_state import RunState
1313
from plain_modules import PlainModule
@@ -283,9 +283,10 @@ def _on_unit_test_limit_exceeded_in_conformance_tests(self):
283283
self.dispatch_error(error_msg)
284284
else:
285285
console.info(
286-
f"[#FFB454]↻ Failed to adjust the unit tests after implementation code was updated while fixing the "
286+
f"↻ Failed to adjust the unit tests after implementation code was updated while fixing the "
287287
f"conformance tests for functionality {self.frid_context.frid}. "
288-
f"Restarting rendering the functionality {self.frid_context.frid} from scratch.[/#FFB454]"
288+
f"Restarting rendering the functionality {self.frid_context.frid} from scratch.",
289+
color=RETRY_COLOR,
289290
)
290291
self.machine.dispatch(triggers.RESTART_FRID_PROCESSING)
291292

‎render_machine/render_utils.py‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import file_utils
1515
import git_utils
1616
import plain_spec
17-
from plain2code_console import console
17+
from plain2code_console import MUTED_COLOR, RETRY_COLOR, SUCCESS_COLOR, console
1818
from plain2code_exceptions import RenderCancelledError
1919

2020
SCRIPT_EXECUTION_TIMEOUT = 120
@@ -178,24 +178,30 @@ def _drain_stdout() -> None:
178178
temp_file.write(f"{script_type} script {script} successfully passed.\n")
179179
temp_file.write(f"{script_type} script execution time: {elapsed_time:.2f} seconds.\n")
180180

181-
console.debug(f"[#888888]{script_type} script output stored in: {temp_file_path.strip()}[/#888888]")
181+
console.debug(f"{script_type} script output stored in: {temp_file_path.strip()}", color=MUTED_COLOR)
182182

183183
if proc.returncode != 0:
184184
if frid is not None:
185185
console.info(
186-
f"[#FFB454]↻ The {script_type} script for functionality ID {frid} of module {module} has failed. Initiating the patching mode to automatically correct the discrepancies.[/#FFB454]"
186+
f"↻ The {script_type} script for functionality ID {frid} of module {module} has failed. "
187+
f"Initiating the patching mode to automatically correct the discrepancies.",
188+
color=RETRY_COLOR,
187189
)
188190
else:
189191
console.info(
190-
f"[#FFB454]↻ The {script_type} script has failed. Initiating the patching mode to automatically correct the discrepancies.[/#FFB454]"
192+
f"↻ The {script_type} script has failed. "
193+
f"Initiating the patching mode to automatically correct the discrepancies.",
194+
color=RETRY_COLOR,
191195
)
192196
else:
193197
if frid is not None:
194198
console.info(
195-
f"[#79FC96]The {script_type} script for functionality ID {frid} of module {module} has passed successfully.[/#79FC96]"
199+
f"✓ The {script_type} script for functionality ID {frid} of module {module} "
200+
f"has passed successfully.",
201+
color=SUCCESS_COLOR,
196202
)
197203
else:
198-
console.info(f"[#79FC96]All {script_type} scripts have passed successfully.[/#79FC96]")
204+
console.info(f"✓ All {script_type} scripts have passed successfully.", color=SUCCESS_COLOR)
199205

200206
return proc.returncode, sanitized_script_output, temp_file_path
201207

0 commit comments

Comments
 (0)