Skip to content

Commit b6b47ff

Browse files
committed
Unify PYTHONPATH setup into make_env_with_project_root helper
Replace duplicated PYTHONPATH-prepending boilerplate across 6 call sites with a single helper in shell_utils. Also adds the missing PYTHONPATH to the concolic test validation subprocess.
1 parent 544fd7a commit b6b47ff

6 files changed

Lines changed: 23 additions & 36 deletions

File tree

codeflash/benchmarking/trace_benchmarks.py

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

3-
import os
43
import re
54
import subprocess
65
from pathlib import Path
76

87
from codeflash.cli_cmds.console import logger
98
from codeflash.code_utils.compat import SAFE_SYS_EXECUTABLE
10-
from codeflash.code_utils.shell_utils import get_cross_platform_subprocess_run_args
9+
from codeflash.code_utils.shell_utils import get_cross_platform_subprocess_run_args, make_env_with_project_root
1110

1211

1312
def trace_benchmarks_pytest(
1413
benchmarks_root: Path, tests_root: Path, project_root: Path, trace_file: Path, timeout: int = 300
1514
) -> None:
16-
benchmark_env = os.environ.copy()
17-
if "PYTHONPATH" not in benchmark_env:
18-
benchmark_env["PYTHONPATH"] = str(project_root)
19-
else:
20-
benchmark_env["PYTHONPATH"] += os.pathsep + str(project_root)
15+
benchmark_env = make_env_with_project_root(project_root)
2116
run_args = get_cross_platform_subprocess_run_args(
2217
cwd=project_root, env=benchmark_env, timeout=timeout, check=False, text=True, capture_output=True
2318
)

codeflash/code_utils/concolic_utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import sentry_sdk
1010

1111
from codeflash.code_utils.compat import SAFE_SYS_EXECUTABLE, codeflash_temp_dir
12+
from codeflash.code_utils.shell_utils import make_env_with_project_root
1213

1314
# Known CrossHair limitations that produce invalid Python syntax in generated tests:
1415
# - "<locals>" - higher-order functions returning nested functions
@@ -37,6 +38,7 @@ def is_valid_concolic_test(test_code: str, project_root: Optional[str] = None) -
3738
text=True,
3839
cwd=project_root,
3940
timeout=10,
41+
env=make_env_with_project_root(project_root) if project_root else None,
4042
)
4143
except (subprocess.TimeoutExpired, Exception):
4244
return False

codeflash/code_utils/shell_utils.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,18 @@ def save_api_key_to_rc(api_key: str) -> Result[str, str]:
238238
)
239239

240240

241+
def make_env_with_project_root(project_root: Path | str) -> dict[str, str]:
242+
"""Return a copy of os.environ with project_root prepended to PYTHONPATH."""
243+
env = os.environ.copy()
244+
project_root_str = str(project_root)
245+
pythonpath = env.get("PYTHONPATH", "")
246+
if pythonpath:
247+
env["PYTHONPATH"] = f"{project_root_str}{os.pathsep}{pythonpath}"
248+
else:
249+
env["PYTHONPATH"] = project_root_str
250+
return env
251+
252+
241253
def get_cross_platform_subprocess_run_args(
242254
cwd: Path | str | None = None,
243255
env: Mapping[str, str] | None = None,

codeflash/optimization/function_optimizer.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
from codeflash.code_utils.git_utils import git_root_dir
7070
from codeflash.code_utils.instrument_existing_tests import inject_profiling_into_existing_test
7171
from codeflash.code_utils.line_profile_utils import add_decorator_imports, contains_jit_decorator
72+
from codeflash.code_utils.shell_utils import make_env_with_project_root
7273
from codeflash.code_utils.static_analysis import get_first_top_level_function_or_method_ast
7374
from codeflash.code_utils.time_utils import humanize_runtime
7475
from codeflash.context import code_context_extractor
@@ -2821,14 +2822,10 @@ def cleanup_generated_files(self) -> None:
28212822
def get_test_env(
28222823
self, codeflash_loop_index: int, codeflash_test_iteration: int, codeflash_tracer_disable: int = 1
28232824
) -> dict:
2824-
test_env = os.environ.copy()
2825+
test_env = make_env_with_project_root(self.args.project_root)
28252826
test_env["CODEFLASH_TEST_ITERATION"] = str(codeflash_test_iteration)
28262827
test_env["CODEFLASH_TRACER_DISABLE"] = str(codeflash_tracer_disable)
28272828
test_env["CODEFLASH_LOOP_INDEX"] = str(codeflash_loop_index)
2828-
if "PYTHONPATH" not in test_env:
2829-
test_env["PYTHONPATH"] = str(self.args.project_root)
2830-
else:
2831-
test_env["PYTHONPATH"] += os.pathsep + str(self.args.project_root)
28322829
return test_env
28332830

28342831
def line_profiler_step(

codeflash/tracer.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from __future__ import annotations
1313

1414
import json
15-
import os
1615
import pickle
1716
import subprocess
1817
import sys
@@ -26,6 +25,7 @@
2625
from codeflash.code_utils.compat import SAFE_SYS_EXECUTABLE
2726
from codeflash.code_utils.config_consts import EffortLevel
2827
from codeflash.code_utils.config_parser import parse_config_file
28+
from codeflash.code_utils.shell_utils import make_env_with_project_root
2929
from codeflash.tracing.pytest_parallelization import pytest_split
3030

3131
if TYPE_CHECKING:
@@ -131,13 +131,7 @@ def main(args: Namespace | None = None) -> ArgumentParser:
131131
else:
132132
updated_sys_argv.append(elem)
133133
args_dict["command"] = " ".join(updated_sys_argv)
134-
env = os.environ.copy()
135-
pythonpath = env.get("PYTHONPATH", "")
136-
project_root_str = str(project_root)
137-
if pythonpath:
138-
env["PYTHONPATH"] = f"{project_root_str}{os.pathsep}{pythonpath}"
139-
else:
140-
env["PYTHONPATH"] = project_root_str
134+
env = make_env_with_project_root(project_root)
141135
# Disable JIT compilation to ensure tracing captures all function calls
142136
env["NUMBA_DISABLE_JIT"] = str(1)
143137
env["TORCHDYNAMO_DISABLE"] = str(1)
@@ -174,14 +168,7 @@ def main(args: Namespace | None = None) -> ArgumentParser:
174168
args_dict["result_pickle_file_path"] = str(result_pickle_file_path)
175169
args_dict["command"] = " ".join(sys.argv)
176170

177-
env = os.environ.copy()
178-
# Add project root to PYTHONPATH so imports work correctly
179-
pythonpath = env.get("PYTHONPATH", "")
180-
project_root_str = str(project_root)
181-
if pythonpath:
182-
env["PYTHONPATH"] = f"{project_root_str}{os.pathsep}{pythonpath}"
183-
else:
184-
env["PYTHONPATH"] = project_root_str
171+
env = make_env_with_project_root(project_root)
185172
# Disable JIT compilation to ensure tracing captures all function calls
186173
env["NUMBA_DISABLE_JIT"] = str(1)
187174
env["TORCHDYNAMO_DISABLE"] = str(1)

codeflash/verification/concolic_testing.py

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

33
import ast
4-
import os
54
import subprocess
65
import tempfile
76
import time
@@ -11,6 +10,7 @@
1110
from codeflash.cli_cmds.console import console, logger
1211
from codeflash.code_utils.compat import SAFE_SYS_EXECUTABLE
1312
from codeflash.code_utils.concolic_utils import clean_concolic_tests, is_valid_concolic_test
13+
from codeflash.code_utils.shell_utils import make_env_with_project_root
1414
from codeflash.code_utils.static_analysis import has_typed_parameters
1515
from codeflash.discovery.discover_unit_tests import discover_unit_tests
1616
from codeflash.languages import is_python
@@ -64,13 +64,7 @@ def generate_concolic_tests(
6464
logger.info("Generating concolic opcode coverage tests for the original code…")
6565
console.rule()
6666
try:
67-
env = os.environ.copy()
68-
pythonpath = env.get("PYTHONPATH", "")
69-
project_root_str = str(args.project_root)
70-
if pythonpath:
71-
env["PYTHONPATH"] = f"{project_root_str}{os.pathsep}{pythonpath}"
72-
else:
73-
env["PYTHONPATH"] = project_root_str
67+
env = make_env_with_project_root(args.project_root)
7468
cover_result = subprocess.run(
7569
[
7670
SAFE_SYS_EXECUTABLE,

0 commit comments

Comments
 (0)