77from enum import Enum , IntEnum
88from pathlib import Path
99from re import Pattern
10- from typing import Any , Optional , Union
10+ from typing import Annotated , Any , Optional , Union
1111
12+ import sentry_sdk
13+ from coverage .exceptions import NoDataError
1214from jedi .api .classes import Name
1315from pydantic import AfterValidator , BaseModel , ConfigDict , Field
1416from pydantic .dataclasses import dataclass
15- from typing_extensions import Annotated
1617
1718from codeflash .cli_cmds .console import console , logger
1819from codeflash .code_utils .code_utils import validate_python_code
@@ -217,7 +218,7 @@ class CoverageData:
217218 graph : dict [str , dict [str , Collection [object ]]]
218219 code_context : CodeOptimizationContext
219220 main_func_coverage : FunctionCoverage
220- dependent_func_coverage : Union [FunctionCoverage , None ]
221+ dependent_func_coverage : Optional [FunctionCoverage ]
221222 status : CoverageStatus
222223 blank_re : Pattern [str ] = re .compile (r"\s*(#|$)" )
223224 else_re : Pattern [str ] = re .compile (r"\s*else\s*:\s*(#|$)" )
@@ -231,34 +232,21 @@ def load_from_sqlite_database(
231232 from coverage .jsonreport import JsonReporter
232233
233234 cov = Coverage (data_file = database_path , data_suffix = True , auto_data = True , branch = True )
235+
234236 if not database_path .stat ().st_size or not database_path .exists ():
235237 logger .debug (f"Coverage database { database_path } is empty or does not exist" )
236- return CoverageData (
237- file_path = source_code_path ,
238- coverage = 0.0 ,
239- function_name = function_name ,
240- functions_being_tested = [],
241- graph = {},
242- code_context = code_context ,
243- main_func_coverage = FunctionCoverage (
244- name = function_name ,
245- coverage = 0.0 ,
246- executed_lines = [],
247- unexecuted_lines = [],
248- executed_branches = [],
249- unexecuted_branches = [],
250- ),
251- dependent_func_coverage = None ,
252- status = CoverageStatus .NOT_FOUND ,
253- )
254-
238+ sentry_sdk .capture_message (f"Coverage database { database_path } is empty or does not exist" )
239+ return CoverageData .create_empty (source_code_path , function_name , code_context )
255240 cov .load ()
256241
257242 reporter = JsonReporter (cov )
258243 temp_json_file = database_path .with_suffix (".report.json" )
259244 with temp_json_file .open ("w" ) as f :
260- reporter .report (morfs = [source_code_path .as_posix ()], outfile = f )
261-
245+ try :
246+ reporter .report (morfs = [source_code_path .as_posix ()], outfile = f )
247+ except NoDataError :
248+ sentry_sdk .capture_message (f"No coverage data found for { function_name } in { source_code_path } " )
249+ return CoverageData .create_empty (source_code_path , function_name , code_context )
262250 with temp_json_file .open () as f :
263251 original_coverage_data = json .load (f )
264252
@@ -461,6 +449,34 @@ def log_coverage(self) -> None:
461449 if is_end_to_end ():
462450 console .print (self )
463451
452+ @classmethod
453+ def create_empty (cls , file_path : Path , function_name : str , code_context : CodeOptimizationContext ) -> CoverageData :
454+ return cls (
455+ file_path = file_path ,
456+ coverage = 0.0 ,
457+ function_name = function_name ,
458+ functions_being_tested = [function_name ],
459+ graph = {
460+ function_name : {
461+ "executed_lines" : set (),
462+ "unexecuted_lines" : set (),
463+ "executed_branches" : [],
464+ "unexecuted_branches" : [],
465+ }
466+ },
467+ code_context = code_context ,
468+ main_func_coverage = FunctionCoverage (
469+ name = function_name ,
470+ coverage = 0.0 ,
471+ executed_lines = [],
472+ unexecuted_lines = [],
473+ executed_branches = [],
474+ unexecuted_branches = [],
475+ ),
476+ dependent_func_coverage = None ,
477+ status = CoverageStatus .NOT_FOUND ,
478+ )
479+
464480
465481@dataclass
466482class FunctionCoverage :
0 commit comments