# Copyright (c) 2020 Rocky Bernstein def tryexcept(self, lhs, n, rule, ast, tokens, first, last): come_from_except = ast[-1] if rule == ( "try_except", ( "SETUP_EXCEPT", "suite_stmts_opt", "POP_BLOCK", "except_handler", "opt_come_from_except", ), ): if come_from_except[0] == "COME_FROM": # There should be at last two COME_FROMs, one from an # exception handler and one from the try. Otherwise # we have a try/else. return True pass elif rule == ( 'try_except', ( 'SETUP_EXCEPT', 'suite_stmts_opt', 'POP_BLOCK', 'except_handler', '\\e_opt_come_from_except' ), ): # Find END_FINALLY. for i in range(last, first, -1): if tokens[i] == "END_FINALLY": jump_before_finally = tokens[i-1] if jump_before_finally.kind.startswith("JUMP"): if jump_before_finally == "JUMP_FORWARD": # If there is a JUMP_FORWARD before # the END_FINALLY to some jumps place # beyond tokens[last].off2int() then # this is a try/else rather than an # try (no else). return tokens[i-1].attr > tokens[last].off2int(prefer_last=True) elif jump_before_finally == "JUMP_BACK": # If there is a JUMP_BACK before the # END_FINALLY then this is a looping # jump, but then jumps in the except # handlers have to also be a looping # jump or this is a try/else rather # than an try (no else). except_handler = ast[3] if (except_handler == "except_handler" and except_handler[0] == "JUMP_FORWARD"): return True return False pass pass pass return False