Skip to content

Commit b1ec824

Browse files
committed
refactor: delegate PythonSupport context methods to canonical pipeline
Replace duplicate implementations in extract_code_context() and find_helper_functions() with calls to get_code_optimization_context() and get_function_sources_from_jedi() from the canonical context module.
1 parent 547c02e commit b1ec824

1 file changed

Lines changed: 35 additions & 103 deletions

File tree

codeflash/languages/python/support.py

Lines changed: 35 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -171,127 +171,59 @@ def discover_tests(
171171
# === Code Analysis ===
172172

173173
def extract_code_context(self, function: FunctionToOptimize, project_root: Path, module_root: Path) -> CodeContext:
174-
"""Extract function code and its dependencies.
174+
"""Extract function code and its dependencies via the canonical context pipeline."""
175+
from codeflash.languages.python.context.code_context_extractor import get_code_optimization_context
175176

176-
Uses jedi and libcst for Python code analysis.
177-
178-
Args:
179-
function: The function to extract context for.
180-
project_root: Root of the project.
181-
module_root: Root of the module containing the function.
182-
183-
Returns:
184-
CodeContext with target code and dependencies.
185-
186-
"""
187177
try:
188-
source = function.file_path.read_text()
178+
result = get_code_optimization_context(function, project_root)
189179
except Exception as e:
190-
logger.exception("Failed to read %s: %s", function.file_path, e)
180+
logger.warning("Failed to extract code context for %s: %s", function.function_name, e)
191181
return CodeContext(target_code="", target_file=function.file_path, language=Language.PYTHON)
192182

193-
# Extract the function source
194-
lines = source.splitlines(keepends=True)
195-
if function.starting_line and function.ending_line:
196-
target_lines = lines[function.starting_line - 1 : function.ending_line]
197-
target_code = "".join(target_lines)
198-
else:
199-
target_code = ""
200-
201-
# Find helper functions
202-
helpers = self.find_helper_functions(function, project_root)
203-
204-
# Extract imports
205-
import_lines = []
206-
for line in lines:
207-
stripped = line.strip()
208-
if stripped.startswith(("import ", "from ")):
209-
import_lines.append(stripped)
210-
elif stripped and not stripped.startswith("#"):
211-
# Stop at first non-import, non-comment line
212-
break
183+
helpers = [
184+
HelperFunction(
185+
name=fs.only_function_name,
186+
qualified_name=fs.qualified_name,
187+
file_path=fs.file_path,
188+
source_code=fs.source_code,
189+
start_line=fs.jedi_definition.line if fs.jedi_definition else 1,
190+
end_line=fs.jedi_definition.line if fs.jedi_definition else 1,
191+
)
192+
for fs in result.helper_functions
193+
]
213194

214195
return CodeContext(
215-
target_code=target_code,
196+
target_code=result.read_writable_code.markdown,
216197
target_file=function.file_path,
217198
helper_functions=helpers,
218-
read_only_context="",
219-
imports=import_lines,
199+
read_only_context=result.read_only_context_code,
200+
imports=[],
220201
language=Language.PYTHON,
221202
)
222203

223204
def find_helper_functions(self, function: FunctionToOptimize, project_root: Path) -> list[HelperFunction]:
224-
"""Find helper functions called by the target function.
225-
226-
Uses jedi for Python code analysis.
227-
228-
Args:
229-
function: The target function to analyze.
230-
project_root: Root of the project.
231-
232-
Returns:
233-
List of HelperFunction objects.
234-
235-
"""
236-
helpers: list[HelperFunction] = []
205+
"""Find helper functions called by the target function via the canonical jedi pipeline."""
206+
from codeflash.languages.python.context.code_context_extractor import get_function_sources_from_jedi
237207

238208
try:
239-
import jedi
240-
241-
from codeflash.code_utils.code_utils import get_qualified_name, path_belongs_to_site_packages
242-
from codeflash.optimization.function_context import belongs_to_function_qualified
243-
244-
script = jedi.Script(path=function.file_path, project=jedi.Project(path=project_root))
245-
file_refs = script.get_names(all_scopes=True, definitions=False, references=True)
246-
247-
qualified_name = function.qualified_name
248-
249-
for ref in file_refs:
250-
if not ref.full_name or not belongs_to_function_qualified(ref, qualified_name):
251-
continue
252-
253-
try:
254-
definitions = ref.goto(follow_imports=True, follow_builtin_imports=False)
255-
except Exception:
256-
continue
257-
258-
for definition in definitions:
259-
definition_path = definition.module_path
260-
if definition_path is None:
261-
continue
262-
263-
# Check if it's a valid helper (in project, not in target function)
264-
is_valid = (
265-
str(definition_path).startswith(str(project_root))
266-
and not path_belongs_to_site_packages(definition_path)
267-
and definition.full_name
268-
and not belongs_to_function_qualified(definition, qualified_name)
269-
and definition.type == "function"
270-
)
271-
272-
if is_valid:
273-
helper_qualified_name = get_qualified_name(definition.module_name, definition.full_name)
274-
# Get source code
275-
try:
276-
helper_source = definition.get_line_code()
277-
except Exception:
278-
helper_source = ""
279-
280-
helpers.append(
281-
HelperFunction(
282-
name=definition.name,
283-
qualified_name=helper_qualified_name,
284-
file_path=definition_path,
285-
source_code=helper_source,
286-
start_line=definition.line or 1,
287-
end_line=definition.line or 1,
288-
)
289-
)
290-
209+
_dict, sources = get_function_sources_from_jedi(
210+
{function.file_path: {function.qualified_name}}, project_root
211+
)
291212
except Exception as e:
292213
logger.warning("Failed to find helpers for %s: %s", function.function_name, e)
214+
return []
293215

294-
return helpers
216+
return [
217+
HelperFunction(
218+
name=fs.only_function_name,
219+
qualified_name=fs.qualified_name,
220+
file_path=fs.file_path,
221+
source_code=fs.source_code,
222+
start_line=fs.jedi_definition.line if fs.jedi_definition else 1,
223+
end_line=fs.jedi_definition.line if fs.jedi_definition else 1,
224+
)
225+
for fs in sources
226+
]
295227

296228
def find_references(
297229
self, function: FunctionToOptimize, project_root: Path, tests_root: Path | None = None, max_files: int = 500

0 commit comments

Comments
 (0)