1515import libcst as cst
1616from pydantic .dataclasses import dataclass
1717
18- from codeflash .api .cfapi import get_blocklisted_functions , make_cfapi_request , is_function_being_optimized_again
18+ from codeflash .api .cfapi import get_blocklisted_functions , is_function_being_optimized_again
1919from codeflash .cli_cmds .console import DEBUG_MODE , console , logger
2020from codeflash .code_utils .code_utils import (
2121 is_class_defined_in_file ,
@@ -153,14 +153,14 @@ def get_code_context_hash(self) -> str:
153153 to uniquely identify the function for optimization tracking.
154154 """
155155 try :
156- with open (self .file_path , 'r' , encoding = ' utf-8' ) as f :
156+ with open (self .file_path , encoding = " utf-8" ) as f :
157157 file_content = f .read ()
158158
159159 # Extract the function's code content
160160 lines = file_content .splitlines ()
161161 if self .starting_line is not None and self .ending_line is not None :
162162 # Use line numbers if available (1-indexed to 0-indexed)
163- function_content = ' \n ' .join (lines [self .starting_line - 1 : self .ending_line ])
163+ function_content = " \n " .join (lines [self .starting_line - 1 : self .ending_line ])
164164 else :
165165 # Fallback: use the entire file content if line numbers aren't available
166166 function_content = file_content
@@ -172,19 +172,20 @@ def get_code_context_hash(self) -> str:
172172 context_parts = [
173173 str (self .file_path .name ), # Just filename for portability
174174 self .qualified_name ,
175- function_content .strip ()
175+ function_content .strip (),
176176 ]
177177
178- context_string = ' \n ---\n ' .join (context_parts )
178+ context_string = " \n ---\n " .join (context_parts )
179179
180180 # Generate SHA-256 hash
181- return hashlib .sha256 (context_string .encode (' utf-8' )).hexdigest ()
181+ return hashlib .sha256 (context_string .encode (" utf-8" )).hexdigest ()
182182
183- except ( OSError , IOError ) as e :
183+ except OSError as e :
184184 logger .warning (f"Could not read file { self .file_path } for hashing: { e } " )
185185 # Fallback hash using available metadata
186186 fallback_string = f"{ self .file_path .name } :{ self .qualified_name } "
187- return hashlib .sha256 (fallback_string .encode ('utf-8' )).hexdigest ()
187+ return hashlib .sha256 (fallback_string .encode ("utf-8" )).hexdigest ()
188+
188189
189190def get_functions_to_optimize (
190191 optimize_all : str | None ,
@@ -228,7 +229,7 @@ def get_functions_to_optimize(
228229 found_function = None
229230 for fn in functions .get (file , []):
230231 if only_function_name == fn .function_name and (
231- class_name is None or class_name == fn .top_level_parent_name
232+ class_name is None or class_name == fn .top_level_parent_name
232233 ):
233234 found_function = fn
234235 if found_function is None :
@@ -307,7 +308,7 @@ def find_all_functions_in_file(file_path: Path) -> dict[Path, list[FunctionToOpt
307308
308309
309310def get_all_replay_test_functions (
310- replay_test : Path , test_cfg : TestConfig , project_root_path : Path
311+ replay_test : Path , test_cfg : TestConfig , project_root_path : Path
311312) -> dict [Path , list [FunctionToOptimize ]]:
312313 function_tests = discover_unit_tests (test_cfg , discover_only_these_tests = [replay_test ])
313314 # Get the absolute file paths for each function, excluding class name if present
@@ -322,7 +323,7 @@ def get_all_replay_test_functions(
322323 class_name = (
323324 module_path_parts [- 1 ]
324325 if module_path_parts
325- and is_class_defined_in_file (
326+ and is_class_defined_in_file (
326327 module_path_parts [- 1 ], Path (project_root_path , * module_path_parts [:- 1 ]).with_suffix (".py" )
327328 )
328329 else None
@@ -374,8 +375,7 @@ def ignored_submodule_paths(module_root: str) -> list[str]:
374375
375376class TopLevelFunctionOrMethodVisitor (ast .NodeVisitor ):
376377 def __init__ (
377- self , file_name : Path , function_or_method_name : str , class_name : str | None = None ,
378- line_no : int | None = None
378+ self , file_name : Path , function_or_method_name : str , class_name : str | None = None , line_no : int | None = None
379379 ) -> None :
380380 self .file_name = file_name
381381 self .class_name = class_name
@@ -406,13 +406,13 @@ def visit_ClassDef(self, node: ast.ClassDef) -> None:
406406 if isinstance (body_node , ast .FunctionDef ) and body_node .name == self .function_name :
407407 self .is_top_level = True
408408 if any (
409- isinstance (decorator , ast .Name ) and decorator .id == "classmethod"
410- for decorator in body_node .decorator_list
409+ isinstance (decorator , ast .Name ) and decorator .id == "classmethod"
410+ for decorator in body_node .decorator_list
411411 ):
412412 self .is_classmethod = True
413413 elif any (
414- isinstance (decorator , ast .Name ) and decorator .id == "staticmethod"
415- for decorator in body_node .decorator_list
414+ isinstance (decorator , ast .Name ) and decorator .id == "staticmethod"
415+ for decorator in body_node .decorator_list
416416 ):
417417 self .is_staticmethod = True
418418 return
@@ -421,13 +421,13 @@ def visit_ClassDef(self, node: ast.ClassDef) -> None:
421421 # This way, if we don't have the class name, we can still find the static method
422422 for body_node in node .body :
423423 if (
424- isinstance (body_node , ast .FunctionDef )
425- and body_node .name == self .function_name
426- and body_node .lineno in {self .line_no , self .line_no + 1 }
427- and any (
428- isinstance (decorator , ast .Name ) and decorator .id == "staticmethod"
429- for decorator in body_node .decorator_list
430- )
424+ isinstance (body_node , ast .FunctionDef )
425+ and body_node .name == self .function_name
426+ and body_node .lineno in {self .line_no , self .line_no + 1 }
427+ and any (
428+ isinstance (decorator , ast .Name ) and decorator .id == "staticmethod"
429+ for decorator in body_node .decorator_list
430+ )
431431 ):
432432 self .is_staticmethod = True
433433 self .is_top_level = True
@@ -460,10 +460,7 @@ def inspect_top_level_functions_or_methods(
460460
461461
462462def check_optimization_status (
463- functions_by_file : dict [Path , list [FunctionToOptimize ]],
464- owner : str ,
465- repo : str ,
466- pr_number : int
463+ functions_by_file : dict [Path , list [FunctionToOptimize ]], owner : str , repo : str , pr_number : int
467464) -> tuple [dict [Path , list [FunctionToOptimize ]], int ]:
468465 """Check which functions have already been optimized and filter them out.
469466
@@ -480,6 +477,7 @@ def check_optimization_status(
480477
481478 Returns:
482479 Tuple of (filtered_functions_dict, remaining_count)
480+
483481 """
484482 # Build the code_contexts dictionary for the API call
485483 code_contexts = {}
@@ -500,7 +498,6 @@ def check_optimization_status(
500498 result = is_function_being_optimized_again (owner , repo , pr_number , code_contexts )
501499 already_optimized_paths = set (result .get ("already_optimized_paths" , []))
502500
503-
504501 # Filter out already optimized functions
505502 filtered_functions = defaultdict (list )
506503 remaining_count = 0
@@ -556,12 +553,12 @@ def filter_functions(
556553 test_functions_removed_count += len (_functions )
557554 continue
558555 if file_path in ignore_paths or any (
559- file_path .startswith (str (ignore_path ) + os .sep ) for ignore_path in ignore_paths
556+ file_path .startswith (str (ignore_path ) + os .sep ) for ignore_path in ignore_paths
560557 ):
561558 ignore_paths_removed_count += 1
562559 continue
563560 if file_path in submodule_paths or any (
564- file_path .startswith (str (submodule_path ) + os .sep ) for submodule_path in submodule_paths
561+ file_path .startswith (str (submodule_path ) + os .sep ) for submodule_path in submodule_paths
565562 ):
566563 submodule_ignored_paths_count += 1
567564 continue
@@ -607,13 +604,15 @@ def filter_functions(
607604
608605 # Check optimization status if repository info is provided
609606 already_optimized_count = 0
610- repository = git .Repo (Path .cwd (), search_parent_directories = True )
611- owner , repo = get_repo_owner_and_name (repository )
607+ try :
608+ repository = git .Repo (Path .cwd (), search_parent_directories = True )
609+ owner , repo = get_repo_owner_and_name (repository )
610+ except git .exc .InvalidGitRepositoryError :
611+ logger .warning ("No git repository found" )
612+ owner , repo = None , None
612613 pr_number = get_pr_number ()
613614 if owner and repo and pr_number is not None :
614- path_based_functions , functions_count = check_optimization_status (
615- path_based_functions , owner , repo , pr_number
616- )
615+ path_based_functions , functions_count = check_optimization_status (path_based_functions , owner , repo , pr_number )
617616 initial_count = sum (len (funcs ) for funcs in filtered_modified_functions .values ())
618617 already_optimized_count = initial_count - functions_count
619618
@@ -654,8 +653,8 @@ def filter_files_optimized(file_path: Path, tests_root: Path, ignore_paths: list
654653 if submodule_paths is None :
655654 submodule_paths = ignored_submodule_paths (module_root )
656655 return not (
657- file_path in submodule_paths
658- or any (file_path .is_relative_to (submodule_path ) for submodule_path in submodule_paths )
656+ file_path in submodule_paths
657+ or any (file_path .is_relative_to (submodule_path ) for submodule_path in submodule_paths )
659658 )
660659
661660
@@ -664,4 +663,4 @@ def function_has_return_statement(function_node: FunctionDef | AsyncFunctionDef)
664663
665664
666665def function_is_a_property (function_node : FunctionDef | AsyncFunctionDef ) -> bool :
667- return any (isinstance (node , ast .Name ) and node .id == "property" for node in function_node .decorator_list )
666+ return any (isinstance (node , ast .Name ) and node .id == "property" for node in function_node .decorator_list )
0 commit comments