diff --git a/codeflash/languages/python/context/code_context_extractor.py b/codeflash/languages/python/context/code_context_extractor.py index 116522629..079707b28 100644 --- a/codeflash/languages/python/context/code_context_extractor.py +++ b/codeflash/languages/python/context/code_context_extractor.py @@ -918,6 +918,18 @@ def _has_descriptor_like_class_fields(class_node: ast.ClassDef) -> bool: def _should_use_raw_project_class_context(class_node: ast.ClassDef, import_aliases: dict[str, str]) -> bool: + # Check decorator presence first - cheapest check that can short-circuit + if class_node.decorator_list: + return True + + # Check for namedtuple/dataclass early - these are common patterns that avoid body scanning + if _is_namedtuple_class(class_node, import_aliases): + return True + is_dataclass, _, _ = _get_dataclass_config(class_node, import_aliases) + if is_dataclass: + return True + + # Calculate size metrics once start_line = _get_class_start_line(class_node) assert class_node.end_lineno is not None class_line_count = class_node.end_lineno - start_line + 1 @@ -925,22 +937,18 @@ def _should_use_raw_project_class_context(class_node: ast.ClassDef, import_alias class_line_count <= MAX_RAW_PROJECT_CLASS_LINES and len(class_node.body) <= MAX_RAW_PROJECT_CLASS_BODY_ITEMS ) - if is_small and _class_has_explicit_init(class_node): - return True - if _is_namedtuple_class(class_node, import_aliases): - return True - is_dataclass, _, _ = _get_dataclass_config(class_node, import_aliases) - if is_dataclass: - return True - if class_node.decorator_list: - return True - if _has_descriptor_like_class_fields(class_node): - return True + # Single-pass body scan with early returns + has_explicit_init = False for item in class_node.body: - if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)) and _has_non_property_method_decorator( - item, import_aliases - ): + if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)): + if item.name == "__init__": + has_explicit_init = True + if is_small: + return True + if _has_non_property_method_decorator(item, import_aliases): + return True + elif isinstance(item, (ast.Assign, ast.AnnAssign)) and isinstance(item.value, ast.Call): return True return False