Skip to content

Commit 369d7b8

Browse files
authored
Merge branch 'main' into saga_misc_fixes_14nov
2 parents c48b79f + 4ca0a60 commit 369d7b8

File tree

9 files changed

+116
-8
lines changed

9 files changed

+116
-8
lines changed

codeflash/cli_cmds/cmd_init.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,23 @@ def ask_run_end_to_end_test(args: Namespace) -> None:
171171
run_end_to_end_test(args, file_path)
172172

173173

174-
def is_valid_pyproject_toml(pyproject_toml_path: Path) -> tuple[bool, dict[str, Any] | None, str]: # noqa: PLR0911
174+
def config_found(pyproject_toml_path: Union[str, Path]) -> tuple[bool, str]:
175+
pyproject_toml_path = Path(pyproject_toml_path)
176+
175177
if not pyproject_toml_path.exists():
176-
return False, None, f"Configuration file not found: {pyproject_toml_path}"
178+
return False, f"Configuration file not found: {pyproject_toml_path}"
179+
180+
if not pyproject_toml_path.is_file():
181+
return False, f"Configuration file is not a file: {pyproject_toml_path}"
182+
183+
if pyproject_toml_path.suffix != ".toml":
184+
return False, f"Configuration file is not a .toml file: {pyproject_toml_path}"
185+
186+
return True, ""
177187

188+
189+
def is_valid_pyproject_toml(pyproject_toml_path: Union[str, Path]) -> tuple[bool, dict[str, Any] | None, str]:
190+
pyproject_toml_path = Path(pyproject_toml_path)
178191
try:
179192
config, _ = parse_config_file(pyproject_toml_path)
180193
except Exception as e:
@@ -206,6 +219,10 @@ def should_modify_pyproject_toml() -> tuple[bool, dict[str, Any] | None]:
206219

207220
pyproject_toml_path = Path.cwd() / "pyproject.toml"
208221

222+
found, _ = config_found(pyproject_toml_path)
223+
if not found:
224+
return True, None
225+
209226
valid, config, _message = is_valid_pyproject_toml(pyproject_toml_path)
210227
if not valid:
211228
# needs to be re-configured

codeflash/code_utils/formatter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ def is_diff_line(line: str) -> bool:
9797

9898

9999
def format_generated_code(generated_test_source: str, formatter_cmds: list[str]) -> str:
100+
formatter_name = formatter_cmds[0].lower() if formatter_cmds else "disabled"
101+
if formatter_name == "disabled": # nothing to do if no formatter provided
102+
return re.sub(r"\n{2,}", "\n\n", generated_test_source)
100103
with tempfile.TemporaryDirectory() as test_dir_str:
101104
# try running formatter, if nothing changes (could be due to formatting failing or no actual formatting needed) return code with 2 or more newlines substituted with 2 newlines
102105
original_temp = Path(test_dir_str) / "original_temp.py"

codeflash/code_utils/git_worktree_utils.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import configparser
34
import subprocess
45
import tempfile
56
import time
@@ -18,14 +19,36 @@
1819

1920
def create_worktree_snapshot_commit(worktree_dir: Path, commit_message: str) -> None:
2021
repository = git.Repo(worktree_dir, search_parent_directories=True)
21-
with repository.config_writer() as cw:
22+
username = None
23+
no_username = False
24+
email = None
25+
no_email = False
26+
with repository.config_reader(config_level="repository") as cr:
27+
try:
28+
username = cr.get("user", "name")
29+
except configparser.NoSectionError:
30+
no_username = True
31+
try:
32+
email = cr.get("user", "email")
33+
except configparser.NoSectionError:
34+
no_email = True
35+
with repository.config_writer(config_level="repository") as cw:
2236
if not cw.has_option("user", "name"):
2337
cw.set_value("user", "name", "Codeflash Bot")
2438
if not cw.has_option("user", "email"):
2539
cw.set_value("user", "email", "bot@codeflash.ai")
2640

2741
repository.git.add(".")
2842
repository.git.commit("-m", commit_message, "--no-verify")
43+
with repository.config_writer(config_level="repository") as cw:
44+
if username:
45+
cw.set_value("user", "name", username)
46+
elif no_username:
47+
cw.remove_option("user", "name")
48+
if email:
49+
cw.set_value("user", "email", email)
50+
elif no_email:
51+
cw.remove_option("user", "email")
2952

3053

3154
def create_detached_worktree(module_root: Path) -> Optional[Path]:

codeflash/discovery/functions_to_optimize.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,10 @@ def is_git_repo(file_path: str) -> bool:
405405
def ignored_submodule_paths(module_root: str) -> list[str]:
406406
if is_git_repo(module_root):
407407
git_repo = git.Repo(module_root, search_parent_directories=True)
408-
return [Path(git_repo.working_tree_dir, submodule.path).resolve() for submodule in git_repo.submodules]
408+
try:
409+
return [Path(git_repo.working_tree_dir, submodule.path).resolve() for submodule in git_repo.submodules]
410+
except Exception as e:
411+
logger.warning(f"Error getting submodule paths: {e}")
409412
return []
410413

411414

codeflash/lsp/beta.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from codeflash.cli_cmds.cmd_init import (
1515
CommonSections,
1616
VsCodeSetupInfo,
17+
config_found,
1718
configure_pyproject_toml,
1819
create_empty_pyproject_toml,
1920
create_find_common_tags_file,
@@ -291,6 +292,10 @@ def init_project(params: ValidateProjectParams) -> dict[str, str]:
291292
"root": root,
292293
}
293294

295+
found, message = config_found(pyproject_toml_path)
296+
if not found:
297+
return {"status": "error", "message": message}
298+
294299
valid, config, reason = is_valid_pyproject_toml(pyproject_toml_path)
295300
if not valid:
296301
return {

codeflash/tracing/tracing_utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ def ignored_submodule_paths(module_root: str) -> list[Path]:
3838
if is_git_repo(module_root):
3939
git_repo = git.Repo(module_root, search_parent_directories=True)
4040
working_tree_dir = cast("Path", git_repo.working_tree_dir)
41-
return [Path(working_tree_dir, submodule.path).resolve() for submodule in git_repo.submodules]
41+
try:
42+
return [Path(working_tree_dir, submodule.path).resolve() for submodule in git_repo.submodules]
43+
except Exception as e:
44+
print(f"Failed to get submodule paths {e!s}") # no logger since used in the tracer
4245
return []
4346

4447

codeflash/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# These version placeholders will be replaced by uv-dynamic-versioning during build.
2-
__version__ = "0.18.3"
2+
__version__ = "0.18.4"

docs/docs.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,17 @@
2323
"pages": ["index"]
2424
},
2525
{
26-
2726
"group": "🚀 Quickstart",
2827
"pages": [
2928
"getting-started/local-installation"
30-
] },
29+
]
30+
},
31+
{
32+
"group": "🛠 IDE Extensions",
33+
"pages": [
34+
"editor-plugins/vscode"
35+
]
36+
},
3137
{
3238
"group": "⚡ Optimizing with Codeflash",
3339
"pages": [

docs/editor-plugins/vscode.mdx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# VS Code Extension & VSIX Installation
2+
3+
Bring Codeflash directly into your editor with the Visual Studio Code extension. The extension surfaces optimization suggestions inline, and keeps the CLI workflow close at hand with more visual experience in editor.
4+
5+
## Requirements
6+
7+
- VS Code 1.94.0 or later (Code, VS Code Desktop, Cursor, Windsurf and other VS Code–compatible editors supported)
8+
- Python 3.9+
9+
- Git repository initialized for your project
10+
- Codeflash CLI installed and initialized with `codeflash init` (Extension will also walkthrough with interactive onboarding)
11+
12+
## Install from the Marketplace
13+
14+
1. Open VS Code and head to the Extensions panel.
15+
2. Search for **“Codeflash”** or open the listing directly:<br />
16+
[Install from VS Code Marketplace →](https://marketplace.visualstudio.com/items?itemName=codeflash.codeflash)
17+
3. Click **Install** and reload VS Code when prompted.
18+
19+
That’s it! As soon as you open a Python file inside a project that has already run `codeflash init`, the extension analyses the codebase and starts surfacing optimization opportunities.
20+
21+
## Install via VSIX (Cursor, offline, or air‑gapped environments)
22+
23+
Some environments—Cursor, Windows without Marketplace access, or air-gapped machines—require installing from a VSIX package.
24+
25+
1. Download the latest VSIX build from Open VSX:<br />
26+
[Download VSIX →](https://open-vsx.org/extension/codeflash/codeflash)
27+
2. In VS Code, run the command palette (`Cmd/Ctrl + Shift + P`) and select **Extensions: Install from VSIX…**
28+
3. Choose the downloaded `codeflash-*.vsix` file and restart the editor.
29+
30+
## Initial Setup Checklist
31+
- The complete Setup flow is within extension to initialize codeflash LSP server
32+
33+
## Everyday Workflow
34+
35+
- **Inline suggestions:** Optimizable functions display a “optimize” hint above the function definition. And once optimized they will show a comment where you can click it to preview and apply improvements.
36+
- **Sidebar overview:** Use the Codeflash panel to review queued, inprogress, and completed optimizations.
37+
- **Targeted runs:** Trigger “Optimize Changed Functions” from the extension to focus on recent uncommited edits.
38+
- **Pair with CLI:** For batch workflows (`codeflash --all`), you can still run the CLI. The extension will pick up the results when you return to the editor.
39+
40+
## Troubleshooting
41+
42+
| Issue | Quick Fix |
43+
| ----- | --------- |
44+
| Using Cursor / custom VS Code build | Install via VSIX and restart the editor. |
45+
| Still stuck? | Reach out on [Discord](https://www.codeflash.ai/discord) or file an issue on [GitHub](https://github.com/codeflash-ai/codeflash/issues). |
46+
47+
With the extension in place, you can review, accept, or iterate on optimizations without leaving your editor—perfect for maintaining focus while keeping performance top of mind.
48+

0 commit comments

Comments
 (0)