Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
b058dee
perf: disable Sentry subprocess instrumentation and tracing
KRRT7 Feb 19, 2026
b19e1bd
perf: replace backtracking regexes with character-class patterns in p…
KRRT7 Feb 19, 2026
67ee734
perf: remove redundant project_root_path.resolve() from hot path
KRRT7 Feb 19, 2026
377083a
style: auto-fix ruff formatting in parse_test_output.py
github-actions[bot] Feb 19, 2026
486f6b8
fix: use disabled_integrations to exclude StdlibIntegration
KRRT7 Feb 19, 2026
8995279
style: add return type annotations to test methods
github-actions[bot] Feb 19, 2026
4742585
perf: remove remaining redundant .resolve() calls on pre-resolved paths
KRRT7 Feb 19, 2026
27937d4
Merge branch 'narrow-sentry-stdlib-integration' of https://github.com…
KRRT7 Feb 19, 2026
dc9c60a
perf: remove remaining redundant .resolve() calls on pre-resolved paths
KRRT7 Feb 19, 2026
ac096d9
style: auto-fix line length formatting in functions_to_optimize.py
github-actions[bot] Feb 19, 2026
e285908
fix: resolve tests_project_root at inject_profiling entry point
KRRT7 Feb 19, 2026
b3fd6bf
fix: resolve both sides of path comparisons for Windows 8.3 name cons…
KRRT7 Feb 19, 2026
a726b46
fix: guard against None definition_path from Jedi
KRRT7 Feb 19, 2026
5efa1ee
style: remove unused os import in code_context_extractor
github-actions[bot] Feb 19, 2026
74246e6
fix: resolve function_to_optimize.file_path for Windows 8.3 name cons…
github-actions[bot] Feb 19, 2026
3cdf710
fix: use dataclasses.replace() for frozen FunctionToOptimize path res…
github-actions[bot] Feb 19, 2026
8f65c9f
fix: resolve paths in revert_unused_helper_functions for Windows 8.3 …
github-actions[bot] Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions codeflash/cli_cmds/init_javascript.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def determine_js_package_manager(project_root: Path) -> JsPackageManager:
"""
# Search from project_root up to filesystem root for lock files
# This supports monorepo setups where lock file is at workspace root
current_dir = project_root.resolve()
current_dir = project_root
while current_dir != current_dir.parent:
if (current_dir / "bun.lockb").exists() or (current_dir / "bun.lock").exists():
return JsPackageManager.BUN
Expand Down Expand Up @@ -161,7 +161,7 @@ def find_node_modules_with_package(project_root: Path, package_name: str) -> Pat
Path to the node_modules directory containing the package, or None if not found.

"""
current_dir = project_root.resolve()
current_dir = project_root
while current_dir != current_dir.parent:
node_modules = current_dir / "node_modules"
if node_modules.exists():
Expand Down
1 change: 1 addition & 0 deletions codeflash/code_utils/instrument_existing_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ def inject_profiling_into_existing_test(
tests_project_root: Path,
mode: TestingMode = TestingMode.BEHAVIOR,
) -> tuple[bool, str | None]:
tests_project_root = tests_project_root.resolve()
if function_to_optimize.is_async:
return inject_async_profiling_into_existing_test(
test_path, call_positions, function_to_optimize, tests_project_root, mode
Expand Down
4 changes: 2 additions & 2 deletions codeflash/discovery/discover_unit_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ class TestFunction:
class TestsCache:
SCHEMA_VERSION = 1 # Increment this when schema changes

def __init__(self, project_root_path: str | Path) -> None:
self.project_root_path = Path(project_root_path).resolve().as_posix()
def __init__(self, project_root_path: Path) -> None:
self.project_root_path = project_root_path.resolve().as_posix()
self.connection = sqlite3.connect(codeflash_cache_db)
self.cur = self.connection.cursor()

Expand Down
8 changes: 6 additions & 2 deletions codeflash/discovery/functions_to_optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ def filter_functions(
*,
disable_logs: bool = False,
) -> tuple[dict[Path, list[FunctionToOptimize]], int]:
resolved_project_root = project_root.resolve()
filtered_modified_functions: dict[str, list[FunctionToOptimize]] = {}
blocklist_funcs = get_blocklisted_functions()
logger.debug(f"Blocklisted functions: {blocklist_funcs}")
Expand Down Expand Up @@ -912,7 +913,7 @@ def is_test_file(file_path_normalized: str) -> bool:
lang_support = get_language_support(Path(file_path))
if lang_support.language == Language.PYTHON:
try:
ast.parse(f"import {module_name_from_file_path(Path(file_path), project_root)}")
ast.parse(f"import {module_name_from_file_path(Path(file_path), resolved_project_root)}")
except SyntaxError:
malformed_paths_count += 1
continue
Expand All @@ -934,7 +935,10 @@ def is_test_file(file_path_normalized: str) -> bool:
if previous_checkpoint_functions:
functions_tmp = []
for function in _functions:
if function.qualified_name_with_modules_from_root(project_root) in previous_checkpoint_functions:
if (
function.qualified_name_with_modules_from_root(resolved_project_root)
in previous_checkpoint_functions
):
previous_checkpoint_functions_removed_count += 1
continue
functions_tmp.append(function)
Expand Down
3 changes: 1 addition & 2 deletions codeflash/languages/javascript/import_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ def __init__(self, project_root: Path) -> None:
project_root: Root directory of the project.

"""
# Resolve to real path to handle macOS symlinks like /var -> /private/var
self.project_root = project_root.resolve()
self.project_root = project_root
self._resolution_cache: dict[tuple[Path, str], Path | None] = {}

def resolve_import(self, import_info: ImportInfo, source_file: Path) -> ResolvedImport | None:
Expand Down
11 changes: 9 additions & 2 deletions codeflash/languages/python/context/code_context_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import ast
import hashlib
import os
from collections import defaultdict
from itertools import chain
from pathlib import Path
Expand Down Expand Up @@ -512,6 +511,10 @@ def get_function_sources_from_jedi(
# TODO: there can be multiple definitions, see how to handle such cases
definition = definitions[0]
definition_path = definition.module_path
if definition_path is not None:
rel = safe_relative_to(definition_path, project_root_path)
if not rel.is_absolute():
definition_path = project_root_path / rel

# The definition is part of this project and not defined within the original function
is_valid_definition = (
Expand Down Expand Up @@ -936,7 +939,11 @@ def is_project_path(module_path: Path | None, project_root_path: Path) -> bool:
# site-packages must be checked first because .venv/site-packages is under project root
if path_belongs_to_site_packages(module_path):
return False
return str(module_path).startswith(str(project_root_path) + os.sep)
try:
module_path.resolve().relative_to(project_root_path.resolve())
return True
except ValueError:
return False


def _is_project_module(module_name: str, project_root_path: Path) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,17 +587,20 @@ def revert_unused_helper_functions(

logger.debug(f"Reverting {len(unused_helpers)} unused helper function(s) to original definitions")

# Resolve all path keys for consistent comparison (Windows 8.3 short names may differ from Jedi-resolved paths)
resolved_original_helper_code = {p.resolve(): code for p, code in original_helper_code.items()}

# Group unused helpers by file path
unused_helpers_by_file = defaultdict(list)
for helper in unused_helpers:
unused_helpers_by_file[helper.file_path].append(helper)
unused_helpers_by_file[helper.file_path.resolve()].append(helper)

# For each file, revert the unused helper functions to their original definitions
for file_path, helpers_in_file in unused_helpers_by_file.items():
if file_path in original_helper_code:
if file_path in resolved_original_helper_code:
try:
# Get original code for this file
original_code = original_helper_code[file_path]
original_code = resolved_original_helper_code[file_path]

# Use the code replacer to selectively revert only the unused helper functions
helper_names = [helper.qualified_name for helper in helpers_in_file]
Expand Down
8 changes: 6 additions & 2 deletions codeflash/optimization/function_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ast
import concurrent.futures
import dataclasses
import logging
import os
import queue
Expand Down Expand Up @@ -443,9 +444,12 @@ def __init__(
args: Namespace | None = None,
replay_tests_dir: Path | None = None,
) -> None:
self.project_root = test_cfg.project_root_path
self.project_root = test_cfg.project_root_path.resolve()
self.test_cfg = test_cfg
self.aiservice_client = aiservice_client if aiservice_client else AiServiceClient()
resolved_file_path = function_to_optimize.file_path.resolve()
if resolved_file_path != function_to_optimize.file_path:
function_to_optimize = dataclasses.replace(function_to_optimize, file_path=resolved_file_path)
self.function_to_optimize = function_to_optimize
self.function_to_optimize_source_code = (
function_to_optimize_source_code
Expand Down Expand Up @@ -1451,7 +1455,7 @@ def reformat_code_and_helpers(
optimized_code = ""
if optimized_context is not None:
file_to_code_context = optimized_context.file_to_path()
optimized_code = file_to_code_context.get(str(path.relative_to(self.project_root)), "")
optimized_code = file_to_code_context.get(str(path.resolve().relative_to(self.project_root)), "")

new_code = format_code(
self.args.formatter_cmds, path, optimized_code=optimized_code, check_diff=True, exit_on_failure=False
Expand Down
4 changes: 2 additions & 2 deletions codeflash/result/create_pr.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ def existing_tests_source_for(
tests_dir_name = test_cfg.tests_project_rootdir.name
if file_path.startswith((tests_dir_name + os.sep, tests_dir_name + "/")):
# Module path includes "tests." - use project root parent
instrumented_abs_path = (test_cfg.tests_project_rootdir.parent / file_path).resolve()
instrumented_abs_path = test_cfg.tests_project_rootdir.parent / file_path
else:
# Module path doesn't include tests dir - use tests root directly
instrumented_abs_path = (test_cfg.tests_project_rootdir / file_path).resolve()
instrumented_abs_path = test_cfg.tests_project_rootdir / file_path
logger.debug(f"[PR-DEBUG] Looking up: {instrumented_abs_path}")
logger.debug(f"[PR-DEBUG] Available keys: {list(instrumented_to_original.keys())[:3]}")
# Try to map instrumented path to original path
Expand Down
11 changes: 4 additions & 7 deletions codeflash/telemetry/sentry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
from sentry_sdk.integrations.stdlib import StdlibIntegration


def init_sentry(*, enabled: bool = False, exclude_errors: bool = False) -> None:
Expand All @@ -16,12 +17,8 @@ def init_sentry(*, enabled: bool = False, exclude_errors: bool = False) -> None:
sentry_sdk.init(
dsn="https://4b9a1902f9361b48c04376df6483bc96@o4506833230561280.ingest.sentry.io/4506833262477312",
integrations=[sentry_logging],
# Set traces_sample_rate to 1.0 to capture 100%
# of transactions for performance monitoring.
traces_sample_rate=1.0,
# Set profiles_sample_rate to 1.0 to profile 100%
# of sampled transactions.
# We recommend adjusting this value in production.
profiles_sample_rate=1.0,
disabled_integrations=[StdlibIntegration],
traces_sample_rate=0,
profiles_sample_rate=0,
ignore_errors=[KeyboardInterrupt],
)
23 changes: 19 additions & 4 deletions codeflash/verification/parse_test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,24 @@ def parse_func(file_path: Path) -> XMLParser:
return parse(file_path, xml_parser)


matches_re_start = re.compile(r"!\$######(.*?):(.*?)([^\.:]*?):(.*?):(.*?):(.*?)######\$!\n")
matches_re_end = re.compile(r"!######(.*?):(.*?)([^\.:]*?):(.*?):(.*?):(.*?)######!")
matches_re_start = re.compile(
r"!\$######([^:]*)" # group 1: module path
r":((?:[^:.]*\.)*)" # group 2: class prefix with trailing dot, or empty
r"([^.:]*)" # group 3: test function name
r":([^:]*)" # group 4: function being tested
r":([^:]*)" # group 5: loop index
r":([^#]*)" # group 6: iteration id
r"######\$!\n"
)
matches_re_end = re.compile(
r"!######([^:]*)" # group 1: module path
r":((?:[^:.]*\.)*)" # group 2: class prefix with trailing dot, or empty
r"([^.:]*)" # group 3: test function name
r":([^:]*)" # group 4: function being tested
r":([^:]*)" # group 5: loop index
r":([^#]*)" # group 6: iteration_id or iteration_id:runtime
r"######!"
)


start_pattern = re.compile(r"!\$######([^:]*):([^:]*):([^:]*):([^:]*):([^:]+)######\$!")
Expand Down Expand Up @@ -893,7 +909,6 @@ def merge_test_results(
return merged_test_results


FAILURES_HEADER_RE = re.compile(r"=+ FAILURES =+")
TEST_HEADER_RE = re.compile(r"_{3,}\s*(.*?)\s*_{3,}$")


Expand All @@ -903,7 +918,7 @@ def parse_test_failures_from_stdout(stdout: str) -> dict[str, str]:
start = end = None

for i, line in enumerate(lines):
if FAILURES_HEADER_RE.search(line.strip()):
if "= FAILURES =" in line:
start = i
break

Expand Down
4 changes: 4 additions & 0 deletions codeflash/verification/verification_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ class TestConfig:
_language: Optional[str] = None # Language identifier for multi-language support
js_project_root: Optional[Path] = None # JavaScript project root (directory containing package.json)

def __post_init__(self) -> None:
self.project_root_path = self.project_root_path.resolve()
self.tests_project_rootdir = self.tests_project_rootdir.resolve()

@property
def test_framework(self) -> str:
"""Returns the appropriate test framework based on language.
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ warn_unreachable = true
install_types = true
plugins = ["pydantic.mypy"]

exclude = ["tests/", "code_to_optimize/", "pie_test_set/", "experiments/"]

[[tool.mypy.overrides]]
module = ["jedi", "jedi.api.classes", "inquirer", "inquirer.themes", "numba"]
ignore_missing_imports = true
Expand Down
Loading