Skip to content

Commit c81147c

Browse files
Merge branch 'main' into misrasaurabh1-patch-1
2 parents dd492fc + 198595c commit c81147c

File tree

29 files changed

+345
-186
lines changed

29 files changed

+345
-186
lines changed

.github/workflows/codeflash-optimize.yaml

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: CodeFlash
22

33
on:
4-
pull_request_target:
4+
pull_request:
55
paths:
66
- '**' # Trigger for all paths
77

@@ -14,8 +14,6 @@ concurrency:
1414
jobs:
1515
optimize:
1616
name: Optimize new Python code
17-
# Dynamically determine if environment is needed only when workflow files change and contributor is external
18-
environment: ${{ (github.event_name == 'workflow_dispatch' || (contains(toJSON(github.event.pull_request.files.*.filename), '.github/workflows/') && github.event.pull_request.user.login != 'misrasaurabh1' && github.event.pull_request.user.login != 'KRRT7')) && 'external-trusted-contributors' || '' }}
1917
if: ${{ github.actor != 'codeflash-ai[bot]' }}
2018
runs-on: ubuntu-latest
2119
env:
@@ -28,31 +26,7 @@ jobs:
2826
- name: 🛎️ Checkout
2927
uses: actions/checkout@v4
3028
with:
31-
ref: ${{ github.event.pull_request.head.ref }}
32-
repository: ${{ github.event.pull_request.head.repo.full_name }}
3329
fetch-depth: 0
34-
- name: Validate PR
35-
run: |
36-
# Check for any workflow changes
37-
if git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" | grep -q "^.github/workflows/"; then
38-
echo "⚠️ Workflow changes detected."
39-
40-
# Get the PR author
41-
AUTHOR="${{ github.event.pull_request.user.login }}"
42-
echo "PR Author: $AUTHOR"
43-
44-
# Allowlist check
45-
if [[ "$AUTHOR" == "misrasaurabh1" || "$AUTHOR" == "KRRT7" ]]; then
46-
echo "✅ Authorized user ($AUTHOR). Proceeding."
47-
elif [[ "${{ github.event.pull_request.state }}" == "open" ]]; then
48-
echo "✅ PR is open. Proceeding with appropriate protections."
49-
else
50-
echo "⛔ Unauthorized user ($AUTHOR) attempting to modify workflows. Exiting."
51-
exit 1
52-
fi
53-
else
54-
echo "✅ No workflow file changes detected. Proceeding."
55-
fi
5630

5731
- name: 🐍 Set up Python 3.11 for CLI
5832
uses: astral-sh/setup-uv@v5

.github/workflows/end-to-end-test-init-optim.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
COLUMNS: 110
2121
MAX_RETRIES: 3
2222
RETRY_DELAY: 5
23-
EXPECTED_IMPROVEMENT_PCT: 300
23+
EXPECTED_IMPROVEMENT_PCT: 30
2424
CODEFLASH_END_TO_END: 1
2525
steps:
2626
- name: 🛎️ Checkout

code_to_optimize/code_directories/simple_tracer_e2e/workload.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33

44
def funcA(number):
5+
number = number if number < 1000 else 1000
56
k = 0
67
for i in range(number * 100):
78
k += i

codeflash/api/aiservice.py

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

3+
import time
4+
35
import json
46
import os
57
import platform
@@ -95,6 +97,7 @@ def optimize_python_code(
9597
- List[OptimizationCandidate]: A list of Optimization Candidates.
9698
9799
"""
100+
start_time = time.perf_counter()
98101
payload = {
99102
"source_code": source_code,
100103
"dependency_code": dependency_code,
@@ -118,6 +121,8 @@ def optimize_python_code(
118121
optimizations_json = response.json()["optimizations"]
119122
logger.info(f"Generated {len(optimizations_json)} candidates.")
120123
console.rule()
124+
end_time = time.perf_counter()
125+
logger.debug(f"Optimization took {end_time - start_time:.2f} seconds.")
121126
return [
122127
OptimizedCandidate(
123128
source_code=opt["source_code"],

codeflash/cli_cmds/cmd_init.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,13 +676,16 @@ def configure_pyproject_toml(setup_info: SetupInfo) -> None:
676676
)
677677
apologize_and_exit()
678678

679+
enable_telemetry = ask_for_telemetry()
680+
679681
codeflash_section = tomlkit.table()
680682
codeflash_section.add(tomlkit.comment("All paths are relative to this pyproject.toml's directory."))
681683
codeflash_section["module-root"] = setup_info.module_root
682684
codeflash_section["tests-root"] = setup_info.tests_root
683685
codeflash_section["test-framework"] = setup_info.test_framework
684686
codeflash_section["benchmarks-root"] = setup_info.benchmarks_root if setup_info.benchmarks_root else ""
685687
codeflash_section["ignore-paths"] = setup_info.ignore_paths
688+
codeflash_section["disable-telemetry"] = not enable_telemetry
686689
if setup_info.git_remote not in ["", "origin"]:
687690
codeflash_section["git-remote"] = setup_info.git_remote
688691
formatter = setup_info.formatter
@@ -934,3 +937,16 @@ def run_end_to_end_test(args: Namespace, bubble_sort_path: str, bubble_sort_test
934937
console.rule()
935938
Path(path).unlink(missing_ok=True)
936939
logger.info(f"🗑️ Deleted {path}")
940+
941+
942+
def ask_for_telemetry() -> bool:
943+
"""Prompt the user to enable or disable telemetry."""
944+
from rich.prompt import Confirm
945+
946+
enable_telemetry = Confirm.ask(
947+
"⚡️ Would you like to enable telemetry to help us improve the Codeflash experience?",
948+
default=True,
949+
show_default=True,
950+
)
951+
952+
return enable_telemetry

codeflash/code_utils/code_utils.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import ast
44
import os
5+
import shutil
56
import site
67
from functools import lru_cache
78
from pathlib import Path
@@ -118,4 +119,8 @@ def has_any_async_functions(code: str) -> bool:
118119

119120
def cleanup_paths(paths: list[Path]) -> None:
120121
for path in paths:
121-
path.unlink(missing_ok=True)
122+
if path and path.exists():
123+
if path.is_dir():
124+
shutil.rmtree(path, ignore_errors=True)
125+
else:
126+
path.unlink(missing_ok=True)

codeflash/code_utils/compat.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import sys
33
from pathlib import Path
44

5+
from platformdirs import user_config_dir
6+
57
# os-independent newline
68
# important for any user-facing output or files we write
79
# make sure to use this in f-strings e.g. f"some string{LF}"
@@ -12,3 +14,8 @@
1214
SAFE_SYS_EXECUTABLE: str = Path(sys.executable).as_posix()
1315

1416
IS_POSIX = os.name != "nt"
17+
18+
19+
codeflash_cache_dir = Path(user_config_dir(appname="codeflash", appauthor="codeflash-ai", ensure_exists=True))
20+
21+
codeflash_cache_db = codeflash_cache_dir / "codeflash_cache.db"

codeflash/code_utils/github_utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ def require_github_app_or_exit(owner: str, repo: str) -> None:
2626
f"Note: if you want to find optimizations without opening PRs, you can run Codeflash with the --no-pr flag.{LF}"
2727
)
2828
apologize_and_exit()
29+
30+
def github_pr_url(owner: str, repo: str, pr_number: str) -> str:
31+
return f"https://github.com/{owner}/{repo}/pull/{pr_number}"

codeflash/context/code_context_extractor.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ def extract_code_string_context_from_files(
217217
continue
218218
try:
219219
qualified_helper_function_names = {func.qualified_name for func in helper_function_sources}
220-
code_without_unused_defs = remove_unused_definitions_by_function_names(original_code, qualified_helper_function_names)
220+
code_without_unused_defs = remove_unused_definitions_by_function_names(
221+
original_code, qualified_helper_function_names
222+
)
221223
code_context = parse_code_and_prune_cst(
222224
code_without_unused_defs, code_context_type, set(), qualified_helper_function_names, remove_docstrings
223225
)
@@ -325,7 +327,9 @@ def extract_code_markdown_context_from_files(
325327
continue
326328
try:
327329
qualified_helper_function_names = {func.qualified_name for func in helper_function_sources}
328-
code_without_unused_defs = remove_unused_definitions_by_function_names(original_code, qualified_helper_function_names)
330+
code_without_unused_defs = remove_unused_definitions_by_function_names(
331+
original_code, qualified_helper_function_names
332+
)
329333
code_context = parse_code_and_prune_cst(
330334
code_without_unused_defs, code_context_type, set(), qualified_helper_function_names, remove_docstrings
331335
)
@@ -403,12 +407,8 @@ def get_function_sources_from_jedi(
403407
for name in names:
404408
try:
405409
definitions: list[Name] = name.goto(follow_imports=True, follow_builtin_imports=False)
406-
except Exception as e:
407-
try:
408-
logger.exception(f"Error while getting definition for {name.full_name}: {e}")
409-
except Exception as e:
410-
# name.full_name can also throw exceptions sometimes
411-
logger.exception(f"Error while getting definition: {e}")
410+
except Exception: # noqa: BLE001
411+
logger.debug(f"Error while getting definitions for {qualified_function_name}")
412412
definitions = []
413413
if definitions:
414414
# TODO: there can be multiple definitions, see how to handle such cases
@@ -424,7 +424,12 @@ def get_function_sources_from_jedi(
424424
and not belongs_to_function_qualified(definition, qualified_function_name)
425425
and definition.full_name.startswith(definition.module_name)
426426
# Avoid nested functions or classes. Only class.function is allowed
427-
and len((qualified_name := get_qualified_name(definition.module_name, definition.full_name)).split(".")) <= 2
427+
and len(
428+
(qualified_name := get_qualified_name(definition.module_name, definition.full_name)).split(
429+
"."
430+
)
431+
)
432+
<= 2
428433
):
429434
function_source = FunctionSource(
430435
file_path=definition_path,

0 commit comments

Comments
 (0)