Skip to content

Commit aab0aa4

Browse files
fixes for cli console logs
1 parent f766ac6 commit aab0aa4

File tree

5 files changed

+42
-44
lines changed

5 files changed

+42
-44
lines changed

codeflash/cli_cmds/console.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
setattr(
5353
logger,
5454
level,
55-
lambda msg, _real_fn=real_fn, _level=level, *args, **kwargs: enhanced_log(
55+
lambda msg, *args, _real_fn=real_fn, _level=level, **kwargs: enhanced_log(
5656
msg, _real_fn, _level, *args, **kwargs
5757
),
5858
)

codeflash/lsp/lsp_logger.py

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
from dataclasses import dataclass
4-
from typing import Any, Callable
4+
from typing import Any, Callable, Optional
55

66
from codeflash.lsp.helpers import is_LSP_enabled
77
from codeflash.lsp.lsp_message import LspTextMessage
@@ -10,9 +10,9 @@
1010
@dataclass
1111
class LspMessageTags:
1212
# always set default values for message tags
13-
not_lsp: bool = False # !lsp (prevent the message from being sent to the LSP)
14-
force_lsp: bool = False # lsp (you can use this to force a message to be sent to the LSP even if the level is not supported)
15-
loading: bool = False # loading (you can use this to indicate that the message is a loading message)
13+
not_lsp: bool = False # !lsp (prevent the message from being sent to the LSP)
14+
force_lsp: bool = False # lsp (you can use this to force a message to be sent to the LSP even if the level is not supported)
15+
loading: bool = False # loading (you can use this to indicate that the message is a loading message)
1616

1717
h1: bool = False # h1
1818
h2: bool = False # h2
@@ -32,14 +32,15 @@ def add_heading_tags(msg: str, tags: LspMessageTags) -> str:
3232
return msg
3333

3434

35-
def extract_tags(msg: str) -> tuple[LspMessageTags, str]:
35+
def extract_tags(msg: str) -> tuple[Optional[LspMessageTags], str]:
3636
if not isinstance(msg, str):
37-
return LspMessageTags(), msg
37+
return None, msg
3838

3939
parts = msg.split("|tags|")
4040
if len(parts) == 2:
4141
message_tags = LspMessageTags()
42-
tags = [tag.strip() for tag in parts[0].split(",")]
42+
# Use set for O(1) lookups and remove whitespace in a single pass
43+
tags = {tag.strip() for tag in parts[0].split(",")}
4344
if "!lsp" in tags:
4445
message_tags.not_lsp = True
4546
if "lsp" in tags:
@@ -56,7 +57,7 @@ def extract_tags(msg: str) -> tuple[LspMessageTags, str]:
5657
message_tags.h4 = True
5758
return message_tags, parts[1]
5859

59-
return LspMessageTags(), msg
60+
return None, msg
6061

6162

6263
supported_lsp_log_levels = ("info", "debug")
@@ -70,31 +71,23 @@ def enhanced_log(
7071
**kwargs: Any, # noqa: ANN401
7172
) -> None:
7273
lsp_enabled = is_LSP_enabled()
73-
if not lsp_enabled or not isinstance(msg, str):
74-
actual_log_fn(msg, *args, **kwargs)
75-
return
76-
77-
is_lsp_json_message = msg.startswith('{"type"')
78-
is_normal_text_message = not is_lsp_json_message
79-
80-
tags = LspMessageTags()
81-
clean_msg = msg
74+
tags, clean_msg = extract_tags(msg)
8275

83-
if is_normal_text_message:
84-
tags, clean_msg = extract_tags(msg)
85-
86-
# normal cli mode
87-
if not lsp_enabled:
76+
if not lsp_enabled or not isinstance(clean_msg, str):
8877
actual_log_fn(clean_msg, *args, **kwargs)
8978
return
9079

9180
#### LSP mode ####
81+
is_lsp_json_message = clean_msg.startswith('{"type"')
82+
is_normal_text_message = not is_lsp_json_message
83+
final_tags = tags if tags else LspMessageTags()
84+
9285
unsupported_level = level not in supported_lsp_log_levels
93-
if not tags.force_lsp and (tags.not_lsp or unsupported_level):
86+
if not final_tags.force_lsp and (final_tags.not_lsp or unsupported_level):
9487
return
9588

9689
if is_normal_text_message:
97-
clean_msg = add_heading_tags(clean_msg, tags)
98-
clean_msg = LspTextMessage(text=clean_msg, takes_time=tags.loading).serialize()
90+
clean_msg = add_heading_tags(clean_msg, final_tags)
91+
clean_msg = LspTextMessage(text=clean_msg, takes_time=final_tags.loading).serialize()
9992

10093
actual_log_fn(clean_msg, *args, **kwargs)

codeflash/optimization/function_optimizer.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -319,10 +319,9 @@ def generate_and_instrument_tests(
319319

320320
generated_tests: GeneratedTestsList
321321
optimizations_set: OptimizationSet
322-
generated_tests, function_to_concolic_tests, concolic_test_str, optimizations_set = generated_results.unwrap()
323-
count_tests = len(generated_tests.generated_tests)
324-
if concolic_test_str:
325-
count_tests += 1
322+
count_tests, generated_tests, function_to_concolic_tests, concolic_test_str, optimizations_set = (
323+
generated_results.unwrap()
324+
)
326325

327326
for i, generated_test in enumerate(generated_tests.generated_tests):
328327
with generated_test.behavior_file_path.open("w", encoding="utf8") as f:
@@ -789,7 +788,7 @@ def log_successful_optimization(
789788
f"Performance: {explanation.perf_improvement_line}",
790789
"",
791790
"#### Explanation\n",
792-
explanation.to_console_string(),
791+
explanation.__str__(),
793792
]
794793

795794
# TODO: display the tests
@@ -807,7 +806,7 @@ def log_successful_optimization(
807806
explanation_panel = Panel(
808807
f"⚡️ Optimization successful! 📄 {self.function_to_optimize.qualified_name} in {explanation.file_path}\n"
809808
f"📈 {explanation.perf_improvement_line}\n"
810-
f"Explanation: \n{explanation.to_console_string()}",
809+
f"Explanation: \n{explanation.__str__()}",
811810
title="Optimization Summary",
812811
border_style="green",
813812
)
@@ -1120,10 +1119,16 @@ def generate_tests_and_optimizations(
11201119
logger.warning(f"Failed to generate and instrument tests for {self.function_to_optimize.function_name}")
11211120
return Failure(f"/!\\ NO TESTS GENERATED for {self.function_to_optimize.function_name}")
11221121
function_to_concolic_tests, concolic_test_str = future_concolic_tests.result()
1123-
logger.info(f"Generated '{len(tests)}' tests for {self.function_to_optimize.function_name}")
1122+
1123+
count_tests = len(tests)
1124+
if concolic_test_str:
1125+
count_tests += 1
1126+
1127+
logger.info(f"Generated '{count_tests}' tests for {self.function_to_optimize.function_name}")
11241128
console.rule()
11251129
generated_tests = GeneratedTestsList(generated_tests=tests)
11261130
result = (
1131+
count_tests,
11271132
generated_tests,
11281133
function_to_concolic_tests,
11291134
concolic_test_str,
@@ -1622,7 +1627,7 @@ def run_optimized_candidate(
16221627
console.rule()
16231628
return Failure("Test results did not match the test results of the original code.")
16241629

1625-
logger.info(f"loading|tags|Running performance tests for candidate {optimization_candidate_index}. ⚡️")
1630+
logger.info(f"loading|tags|Running performance tests ⚡️ for candidate {optimization_candidate_index}.")
16261631

16271632
if test_framework == "pytest":
16281633
candidate_benchmarking_results, _ = self.run_and_parse_tests(

codeflash/optimization/optimizer.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,16 +237,16 @@ def discover_tests(
237237
) -> tuple[dict[str, set[FunctionCalledInTest]], int]:
238238
from codeflash.discovery.discover_unit_tests import discover_unit_tests
239239

240-
logger.info("loading|tags|Scanning project for tests to guide optimization.")
241240
console.rule()
242-
start_time = time.time()
243-
function_to_tests, num_discovered_tests, num_discovered_replay_tests = discover_unit_tests(
244-
self.test_cfg, file_to_funcs_to_optimize=file_to_funcs_to_optimize
245-
)
246-
console.rule()
247-
logger.info(
248-
f"Discovered {num_discovered_tests} existing unit tests and {num_discovered_replay_tests} replay tests in {(time.time() - start_time):.1f}s at {self.test_cfg.tests_root}"
249-
)
241+
with progress_bar("Scanning project for tests to guide optimization."):
242+
start_time = time.time()
243+
function_to_tests, num_discovered_tests, num_discovered_replay_tests = discover_unit_tests(
244+
self.test_cfg, file_to_funcs_to_optimize=file_to_funcs_to_optimize
245+
)
246+
console.rule()
247+
logger.info(
248+
f"Discovered {num_discovered_tests} existing unit tests and {num_discovered_replay_tests} replay tests in {(time.time() - start_time):.1f}s at {self.test_cfg.tests_root}"
249+
)
250250
console.rule()
251251
ph("cli-optimize-discovered-tests", {"num_tests": num_discovered_tests})
252252
return function_to_tests, num_discovered_tests

codeflash/result/explanation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def speedup_x(self) -> str:
4141
def speedup_pct(self) -> str:
4242
return f"{self.speedup * 100:,.0f}%"
4343

44-
def to_console_string(self) -> str:
44+
def __str__(self) -> str:
4545
# TODO: After doing the best optimization, remove the test cases that errored on the new code, because they might be failing because of syntax errors and such.
4646
# TODO: Sometimes the explanation says something similar to "This is the code that was optimized", remove such parts
4747
original_runtime_human = humanize_runtime(self.original_runtime_ns)

0 commit comments

Comments
 (0)