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

Function transform_try_except

mypyc/irbuild/statement.py:669–751  ·  view source on GitHub ↗

Generalized try/except/else handling that takes functions to gen the bodies. The point of this is to also be able to support with.

(
    builder: IRBuilder,
    body: GenFunc,
    handlers: Sequence[tuple[tuple[ValueGenFunc, int] | None, Expression | None, GenFunc]],
    else_body: GenFunc | None,
    line: int,
)

Source from the content-addressed store, hash-verified

667
668
669def transform_try_except(
670 builder: IRBuilder,
671 body: GenFunc,
672 handlers: Sequence[tuple[tuple[ValueGenFunc, int] | None, Expression | None, GenFunc]],
673 else_body: GenFunc | None,
674 line: int,
675) -> None:
676 """Generalized try/except/else handling that takes functions to gen the bodies.
677
678 The point of this is to also be able to support with."""
679 assert handlers, "try needs except"
680
681 except_entry, exit_block, cleanup_block = BasicBlock(), BasicBlock(), BasicBlock()
682 double_except_block = BasicBlock()
683 # If there is an else block, jump there after the try, otherwise just leave
684 else_block = BasicBlock() if else_body else exit_block
685
686 # Compile the try block with an error handler
687 builder.builder.push_error_handler(except_entry)
688 builder.goto_and_activate(BasicBlock())
689 body()
690 builder.goto(else_block)
691 builder.builder.pop_error_handler()
692
693 # The error handler catches the error and then checks it
694 # against the except clauses. We compile the error handler
695 # itself with an error handler so that it can properly restore
696 # the *old* exc_info if an exception occurs.
697 # The exception chaining will be done automatically when the
698 # exception is raised, based on the exception in exc_info.
699 builder.builder.push_error_handler(double_except_block)
700 builder.activate_block(except_entry)
701 old_exc = builder.maybe_spill(builder.call_c(error_catch_op, [], line))
702 # Compile the except blocks with the nonlocal control flow overridden to clear exc_info
703 builder.nonlocal_control.append(ExceptNonlocalControl(builder.nonlocal_control[-1], old_exc))
704
705 # Process the bodies
706 for type, var, handler_body in handlers:
707 next_block = None
708 if type:
709 type_f, type_line = type
710 next_block, body_block = BasicBlock(), BasicBlock()
711 matches = builder.call_c(exc_matches_op, [type_f()], type_line)
712 builder.add(Branch(matches, body_block, next_block, Branch.BOOL, type_line))
713 builder.activate_block(body_block)
714 if var:
715 target = builder.get_assignment_target(var)
716 builder.assign(target, builder.call_c(get_exc_value_op, [], var.line), var.line)
717 handler_body()
718 builder.goto(cleanup_block)
719 if next_block:
720 builder.activate_block(next_block)
721
722 # Reraise the exception if needed
723 if next_block:
724 builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
725 builder.add(Unreachable())
726

Callers 4

gen_conditionMethod · 0.90
transform_withFunction · 0.85
emit_yield_from_or_awaitFunction · 0.85

Calls 15

BasicBlockClass · 0.90
BranchClass · 0.90
UnreachableClass · 0.90
bodyFunction · 0.85
else_bodyFunction · 0.85
push_error_handlerMethod · 0.80
pop_error_handlerMethod · 0.80
maybe_spillMethod · 0.80
appendMethod · 0.80
get_assignment_targetMethod · 0.80
goto_and_activateMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…