def _makeTryExceptSingleHandlerNode(provider, public_exc, tried, exception_name, handler_body, source_ref): # No need to create this in the first place if nothing is tried. if tried is None: return None if public_exc: preserver_id = provider.allocatePreserverId() handling = [ StatementPreserveFrameException(preserver_id=preserver_id, source_ref=source_ref), StatementPublishException(source_ref=source_ref), ] else: handling = [] if not handler_body.isStatementsSequence(): handler_body = makeStatementsSequenceFromStatement( statement=handler_body) if not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(statement=tried) handling.append( makeStatementConditional( condition=ExpressionComparisonExceptionMatch( left=ExpressionCaughtExceptionTypeRef(source_ref=source_ref), right=ExpressionBuiltinExceptionRef( exception_name=exception_name, source_ref=source_ref), source_ref=source_ref, ), yes_branch=handler_body, no_branch=makeReraiseExceptionStatement(source_ref=source_ref), source_ref=source_ref, )) if python_version >= 0x300 and public_exc: handling = (makeTryFinallyStatement( provider=provider, tried=handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal(), ), ) handling = makeStatementsSequenceFromStatements(*handling) return StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, )
def makeTryExceptSingleHandlerNode(tried, exception_name, handler_body, public_exc, source_ref): if public_exc: statements = [ StatementPreserveFrameException( source_ref = source_ref.atInternal() ), StatementPublishException( source_ref = source_ref.atInternal() ) ] else: statements = [] statements.append( StatementConditional( condition = ExpressionComparisonExceptionMatch( left = ExpressionCaughtExceptionTypeRef( source_ref = source_ref ), right = ExpressionBuiltinExceptionRef( exception_name = exception_name, source_ref = source_ref ), source_ref = source_ref ), yes_branch = handler_body, no_branch = makeReraiseExceptionStatement( source_ref = source_ref ), source_ref = source_ref ) ) if Utils.python_version >= 300 and public_exc: statements = [ makeTryFinallyStatement( tried = statements, final = StatementRestoreFrameException( source_ref = source_ref.atInternal() ), source_ref = source_ref.atInternal() ) ] return StatementTryExcept( tried = tried, handling = StatementsSequence( statements = statements, source_ref = source_ref ), public_exc = public_exc, source_ref = source_ref )
def buildTryExceptionNode(provider, node, source_ref): # Try/except nodes. Re-formulated as described in the developer # manual. Exception handlers made the assignment to variables explicit. Same # for the "del" as done for Python3. Also catches always work a tuple of # exception types and hides away that they may be built or not. # Many variables and branches, due to the re-formulation that is going on # here, which just has the complexity, pylint: disable=R0912,R0914 tried = buildStatementsNode( provider = provider, nodes = node.body, source_ref = source_ref ) handlers = [] for handler in node.handlers: exception_expression, exception_assign, exception_block = ( handler.type, handler.name, handler.body ) if exception_assign is None: statements = [ buildStatementsNode( provider = provider, nodes = exception_block, source_ref = source_ref ) ] elif Utils.python_version < 300: statements = [ buildAssignmentStatements( provider = provider, node = exception_assign, source = ExpressionCaughtExceptionValueRef( source_ref = source_ref.atInternal() ), source_ref = source_ref.atInternal() ), buildStatementsNode( provider = provider, nodes = exception_block, source_ref = source_ref ) ] else: target_info = decodeAssignTarget( provider = provider, node = exception_assign, source_ref = source_ref, ) # We didn't allow None, therefore it cannot be None, and # the unpack is safe: pylint: disable=W0633 kind, detail = target_info assert kind == "Name", kind kind = "Name_Exception" statements = [ buildAssignmentStatements( provider = provider, node = exception_assign, source = ExpressionCaughtExceptionValueRef( source_ref = source_ref.atInternal() ), source_ref = source_ref.atInternal() ), makeTryFinallyStatement( tried = buildStatementsNode( provider = provider, nodes = exception_block, source_ref = source_ref ), final = buildDeleteStatementFromDecoded( kind = kind, detail = detail, source_ref = source_ref ), source_ref = source_ref ) ] handler_body = makeStatementsSequence( statements = statements, allow_none = True, source_ref = source_ref ) exception_types = buildNode( provider = provider, node = exception_expression, source_ref = source_ref, allow_none = True ) # The exception types should be a tuple, so as to be most general. if exception_types is None: if handler is not node.handlers[-1]: SyntaxErrors.raiseSyntaxError( reason = "default 'except:' must be last", source_ref = source_ref.atLineNumber( handler.lineno-1 if Options.isFullCompat() else handler.lineno ) ) handlers.append( ( exception_types, handler_body, ) ) # Reraise by default exception_handling = makeReraiseExceptionStatement( source_ref = source_ref ) for exception_type, handler in reversed(handlers): if exception_type is None: # A default handler was given, so use that indead. exception_handling = handler else: exception_handling = StatementsSequence( statements = ( StatementConditional( condition = ExpressionComparisonExceptionMatch( left = ExpressionCaughtExceptionTypeRef( source_ref = exception_type.source_ref ), right = exception_type, source_ref = exception_type.source_ref ), yes_branch = handler, no_branch = exception_handling, source_ref = exception_type.source_ref ), ), source_ref = exception_type.source_ref ) prelude = ( StatementPreserveFrameException( source_ref = source_ref.atInternal() ), StatementPublishException( source_ref = source_ref.atInternal() ) ) if exception_handling is None: # For Python3, we need not publish at all, if all we do is to revert # that immediately. For Python2, the publish may release previously # published exception, which has side effects potentially. if Utils.python_version < 300: exception_handling = StatementsSequence( statements = prelude, source_ref = source_ref.atInternal() ) public_exc = True else: public_exc = False else: public_exc = True if Utils.python_version < 300: exception_handling.setStatements( prelude + exception_handling.getStatements() ) else: exception_handling = StatementsSequence( statements = prelude + ( makeTryFinallyStatement( tried = exception_handling, final = StatementRestoreFrameException( source_ref = source_ref.atInternal() ), source_ref = source_ref ), ), source_ref = source_ref.atInternal() ) no_raise = buildStatementsNode( provider = provider, nodes = node.orelse, source_ref = source_ref ) if no_raise is None: return StatementTryExcept( tried = tried, handling = exception_handling, public_exc = public_exc, source_ref = source_ref ) else: return makeTryExceptNoRaise( provider = provider, temp_scope = provider.allocateTempScope("try_except"), handling = exception_handling, tried = tried, public_exc = public_exc, no_raise = no_raise, source_ref = source_ref )
def buildTryExceptionNode(provider, node, source_ref): # Try/except nodes. Re-formulated as described in the developer # manual. Exception handlers made the assignment to variables explicit. Same # for the "del" as done for Python3. Also catches always work a tuple of # exception types and hides away that they may be built or not. # Many variables and branches, due to the re-formulation that is going on # here, which just has the complexity, pylint: disable=too-many-branches,too-many-locals tried = buildStatementsNode(provider=provider, nodes=node.body, source_ref=source_ref) handlers = [] for handler in node.handlers: exception_expression, exception_assign, exception_block = ( handler.type, handler.name, handler.body, ) if exception_assign is None: statements = [ buildStatementsNode(provider=provider, nodes=exception_block, source_ref=source_ref) ] elif python_version < 0x300: statements = [ buildAssignmentStatements( provider=provider, node=exception_assign, source=ExpressionCaughtExceptionValueRef( source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal(), ), buildStatementsNode(provider=provider, nodes=exception_block, source_ref=source_ref), ] else: # Python3 requires temporary assignment of exception assignment. target_info = decodeAssignTarget(provider=provider, node=exception_assign, source_ref=source_ref) kind, detail = target_info assert kind == "Name", kind kind = "Name_Exception" statements = [ buildAssignmentStatements( provider=provider, node=exception_assign, source=ExpressionCaughtExceptionValueRef( source_ref=source_ref.atInternal()), source_ref=source_ref.atInternal(), ), makeTryFinallyStatement( provider=provider, tried=buildStatementsNode(provider=provider, nodes=exception_block, source_ref=source_ref), final=buildDeleteStatementFromDecoded( provider=provider, kind=kind, detail=detail, source_ref=source_ref, ), source_ref=source_ref, ), ] handler_body = makeStatementsSequence(statements=statements, allow_none=True, source_ref=source_ref) exception_types = buildNode( provider=provider, node=exception_expression, source_ref=source_ref, allow_none=True, ) # The exception types should be a tuple, so as to be most general. if exception_types is None: if handler is not node.handlers[-1]: raiseSyntaxError( "default 'except:' must be last", source_ref.atLineNumber(handler.lineno).atColumnNumber( handler.col_offset), ) handlers.append((exception_types, handler_body)) # Re-raise by default exception_handling = makeReraiseExceptionStatement(source_ref=source_ref) for exception_type, handler in reversed(handlers): if exception_type is None: # A default handler was given, so use that indeed. exception_handling = handler else: exception_handling = StatementsSequence( statements=(makeStatementConditional( condition=ExpressionComparisonExceptionMatch( left=ExpressionCaughtExceptionTypeRef( source_ref=exception_type.source_ref), right=exception_type, source_ref=exception_type.source_ref, ), yes_branch=handler, no_branch=exception_handling, source_ref=exception_type.source_ref, ), ), source_ref=exception_type.source_ref, ) if exception_handling is None: # For Python3, we need not publish at all, if all we do is to revert # that immediately. For Python2, the publish may release previously # published exception, which has side effects potentially. if python_version < 0x300: exception_handling = StatementsSequence( statements=( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal(), ), StatementPublishException( source_ref=source_ref.atInternal()), ), source_ref=source_ref.atInternal(), ) else: if python_version < 0x300: exception_handling.setChild( "statements", ( StatementPreserveFrameException( preserver_id=0, # unused with Python2 source_ref=source_ref.atInternal(), ), StatementPublishException( source_ref=source_ref.atInternal()), ) + exception_handling.subnode_statements, ) else: preserver_id = provider.allocatePreserverId() exception_handling = makeStatementsSequenceFromStatements( StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), StatementPublishException(source_ref=source_ref.atInternal()), makeTryFinallyStatement( provider=provider, tried=exception_handling, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), source_ref=source_ref, ), ) no_raise = buildStatementsNode(provider=provider, nodes=node.orelse, source_ref=source_ref) if no_raise is None: if tried is None: return None return StatementTry( tried=tried, except_handler=exception_handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ) else: if tried is None: return no_raise return makeTryExceptNoRaise( provider=provider, temp_scope=provider.allocateTempScope("try_except"), handling=exception_handling, tried=tried, no_raise=no_raise, source_ref=source_ref, )