@@ -963,19 +963,28 @@ def _is_target_function_call(self, node: ast.Call) -> bool:
963963
964964 return False
965965
966- def _get_call_name (self , func_node ) -> Optional [str ]: # noqa : ANN001
966+ def _get_call_name (self , func_node ) -> Optional [str ]:
967967 """Extract the name being called from a function node."""
968+ # Fast path short-circuit for ast.Name nodes
968969 if isinstance (func_node , ast .Name ):
969970 return func_node .id
971+
972+ # Fast attribute chain extraction (speed: append, loop, join, NO reversed)
970973 if isinstance (func_node , ast .Attribute ):
971974 parts = []
972975 current = func_node
973- while isinstance (current , ast .Attribute ):
976+ # Unwind attribute chain as tight as possible (checked at each loop iteration)
977+ while True :
974978 parts .append (current .attr )
975- current = current .value
976- if isinstance (current , ast .Name ):
977- parts .append (current .id )
978- return "." .join (reversed (parts ))
979+ val = current .value
980+ if isinstance (val , ast .Attribute ):
981+ current = val
982+ continue
983+ if isinstance (val , ast .Name ):
984+ parts .append (val .id )
985+ # Join in-place backwards via slice instead of reversed for slight speedup
986+ return "." .join (parts [::- 1 ])
987+ break
979988 return None
980989
981990 def _extract_source_code (self , node : ast .FunctionDef ) -> str :
0 commit comments