MCPcopy Index your code
hub / github.com/python/mypy / transform_try_finally_stmt_async

Function transform_try_finally_stmt_async

mypyc/irbuild/statement.py:929–1034  ·  view source on GitHub ↗

Async-aware try/finally handling for when finally contains await. This version uses a modified approach that preserves exceptions across await.

(
    builder: IRBuilder, try_body: GenFunc, finally_body: GenFunc, line: int = -1
)

Source from the content-addressed store, hash-verified

927
928
929def transform_try_finally_stmt_async(
930 builder: IRBuilder, try_body: GenFunc, finally_body: GenFunc, line: int = -1
931) -> None:
932 """Async-aware try/finally handling for when finally contains await.
933
934 This version uses a modified approach that preserves exceptions across await."""
935
936 # We need to handle returns properly, so we'll use TryFinallyNonlocalControl
937 # to track return values, similar to the regular try/finally implementation
938
939 err_handler, main_entry, return_entry, finally_entry = (
940 BasicBlock(),
941 BasicBlock(),
942 BasicBlock(),
943 BasicBlock(),
944 )
945
946 # Track if we're returning from the try block
947 control = TryFinallyNonlocalControl(return_entry)
948 builder.builder.push_error_handler(err_handler)
949 builder.nonlocal_control.append(control)
950 builder.goto_and_activate(BasicBlock())
951 try_body()
952 builder.goto(main_entry)
953 builder.nonlocal_control.pop()
954 builder.builder.pop_error_handler()
955 ret_reg = control.ret_reg
956
957 # Normal case - no exception or return
958 builder.activate_block(main_entry)
959 builder.goto(finally_entry)
960
961 # Return case
962 builder.activate_block(return_entry)
963 builder.goto(finally_entry)
964
965 # Exception case - need to catch to clear the error indicator
966 builder.activate_block(err_handler)
967 # Catch the error to clear Python's error indicator
968 builder.call_c(error_catch_op, [], line)
969 # We're not going to use old_exc since it won't survive await
970 # The exception is now in sys.exc_info()
971 builder.goto(finally_entry)
972
973 # Finally block
974 builder.activate_block(finally_entry)
975
976 # Execute finally body
977 finally_body()
978
979 # After finally, we need to handle exceptions carefully:
980 # 1. If finally raised a new exception, it's in the error indicator - let it propagate
981 # 2. If finally didn't raise, check if we need to reraise the original from sys.exc_info()
982 # 3. If there was a return, return that value
983 # 4. Otherwise, normal exit
984
985 # First, check if there's a current exception in the error indicator
986 # (this would be from the finally block)

Callers 1

transform_try_stmtFunction · 0.85

Calls 15

BasicBlockClass · 0.90
BranchClass · 0.90
UnreachableClass · 0.90
TupleGetClass · 0.90
try_bodyFunction · 0.85
finally_bodyFunction · 0.85
push_error_handlerMethod · 0.80
appendMethod · 0.80
pop_error_handlerMethod · 0.80
goto_and_activateMethod · 0.45
gotoMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…