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 makeTryFinallyStatement(provider, tried, final, source_ref, public_exc = False): # Complex handling, due to the many variants, pylint: disable=too-many-branches,too-many-locals if type(tried) in (tuple, list): tried = makeStatementsSequenceFromStatements( *tried ) if type(final) in (tuple, list): final = StatementsSequence( statements = mergeStatements(final, False), source_ref = source_ref ) if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) if tried is None: return final if final is None: return tried if provider is not None: tried.parent = provider final.parent = provider assert tried is not None, source_ref assert final is not None, source_ref # TODO: Currently it's not possible anymore to get at XML for all codes # during the building phase. So this error catcher cannot work currently. if False and isDebug(): final2 = final.makeClone() final2.parent = provider import nuitka.TreeXML if nuitka.TreeXML.Element is not None: f1 = final.asXml() f2 = final2.asXml() def compare(a, b): for c1, c2 in zip(a, b): compare(c1, c2) assert a.attrib == b.attrib, (a.attrib, b.attrib) compare(f1, f2) def getFinal(): # Make a clone of "final" only if necessary. if hasattr(getFinal, "used"): return final.makeClone() else: getFinal.used = True return final if tried.mayRaiseException(BaseException): except_handler = getStatementsAppended( statement_sequence = getFinal(), statements = makeReraiseExceptionStatement( source_ref = source_ref ) ) if public_exc: preserver_id = provider.allocatePreserverId() except_handler = getStatementsPrepended( statement_sequence = except_handler, statements = ( StatementPreserveFrameException( preserver_id = preserver_id, source_ref = source_ref.atInternal() ), StatementPublishException( source_ref = source_ref ) ) ) except_handler = makeTryFinallyStatement( provider = provider, tried = except_handler, final = StatementRestoreFrameException( preserver_id = preserver_id, source_ref = source_ref.atInternal() ), public_exc = False, source_ref = source_ref, ) except_handler = makeStatementsSequenceFromStatement( statement = except_handler ) except_handler.parent = provider else: except_handler = None if tried.mayBreak(): break_handler = getStatementsAppended( statement_sequence = getFinal(), statements = StatementLoopBreak( source_ref = source_ref ) ) break_handler.parent = provider else: break_handler = None if tried.mayContinue(): continue_handler = getStatementsAppended( statement_sequence = getFinal(), statements = StatementLoopContinue( source_ref = source_ref ) ) continue_handler.parent = provider else: continue_handler = None if tried.mayReturn(): return_handler = getStatementsAppended( statement_sequence = getFinal(), statements = StatementReturn( expression = ExpressionReturnedValueRef( source_ref = source_ref ), source_ref = source_ref ) ) return_handler.parent = provider else: return_handler = None result = StatementTry( tried = tried, except_handler = except_handler, break_handler = break_handler, continue_handler = continue_handler, return_handler = return_handler, source_ref = source_ref ) if result.isStatementAborting(): return result else: return makeStatementsSequence( statements = ( result, getFinal() ), allow_none = False, 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, )
def makeTryFinallyStatement(provider, tried, final, source_ref, public_exc=False): # Complex handling, due to the many variants, pylint: disable=too-many-branches if type(tried) in (tuple, list): if tried: tried = makeStatementsSequenceFromStatements(*tried) else: tried = None if type(final) in (tuple, list): if final: final = StatementsSequence( statements=mergeStatements(final, False), source_ref=source_ref ) else: final = None if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) # Trivial case, nothing tried needs only do the final stuff. if tried is None: return final # Trivial case, nothing final needs nothing but the tried stuff. if final is None: return tried # Parent them to us already. if provider is not None: tried.parent = provider final.parent = provider # TODO: Currently it's not possible anymore to get at XML for all codes # during the building phase. So this error catcher cannot work currently. if False and isDebug(): _checkCloning(final, provider) def getFinal(): # Make a clone of "final" only if necessary. if hasattr(getFinal, "used"): return final.makeClone() else: getFinal.used = True return final if tried.mayRaiseException(BaseException): except_handler = getStatementsAppended( statement_sequence=getFinal(), statements=makeReraiseExceptionStatement(source_ref=source_ref), ) if public_exc: preserver_id = provider.allocatePreserverId() except_handler = getStatementsPrepended( statement_sequence=except_handler, statements=( StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), StatementPublishException(source_ref=source_ref), ), ) except_handler = makeTryFinallyStatement( provider=provider, tried=except_handler, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal() ), public_exc=False, source_ref=source_ref, ) except_handler = makeStatementsSequenceFromStatement( statement=except_handler ) else: except_handler = None if tried.mayBreak(): break_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementLoopBreak(source_ref=source_ref), ) else: break_handler = None if tried.mayContinue(): continue_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementLoopContinue(source_ref=source_ref), ) else: continue_handler = None if tried.mayReturn(): return_handler = getStatementsAppended( statement_sequence=getFinal(), statements=StatementReturn( expression=ExpressionReturnedValueRef(source_ref=source_ref), source_ref=source_ref, ), ) else: return_handler = None result = StatementTry( tried=tried, except_handler=except_handler, break_handler=break_handler, continue_handler=continue_handler, return_handler=return_handler, source_ref=source_ref, ) if result.isStatementAborting(): return result else: return makeStatementsSequence( statements=(result, getFinal()), allow_none=False, source_ref=source_ref )
def makeTryFinallyStatement(provider, tried, final, source_ref, public_exc=False): # Complex handling, due to the many variants, pylint: disable=R0912,R0914 if type(tried) in (tuple, list): tried = makeStatementsSequenceFromStatements(*tried) if type(final) in (tuple, list): final = StatementsSequence(statements=mergeStatements(final, False), source_ref=source_ref) if tried is not None and not tried.isStatementsSequence(): tried = makeStatementsSequenceFromStatement(tried) if final is not None and not final.isStatementsSequence(): final = makeStatementsSequenceFromStatement(final) if tried is None: return final if final is None: return tried if provider is not None: tried.parent = provider final.parent = provider assert tried is not None, source_ref assert final is not None, source_ref if isDebug(): final2 = final.makeClone() final2.parent = provider import nuitka.TreeXML if nuitka.TreeXML.Element is not None: f1 = final.asXml() f2 = final2.asXml() def compare(a, b): for c1, c2 in zip(a, b): compare(c1, c2) assert a.attrib == b.attrib, (a.attrib, b.attrib) compare(f1, f2) if tried.mayRaiseException(BaseException): except_handler = final.makeClone() except_handler = getStatementsAppended( statement_sequence=except_handler, statements=makeReraiseExceptionStatement(source_ref=source_ref)) if public_exc: preserver_id = provider.allocatePreserverId() except_handler = getStatementsPrepended( statement_sequence=except_handler, statements=(StatementPreserveFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), StatementPublishException(source_ref=source_ref))) except_handler = makeTryFinallyStatement( provider=provider, tried=except_handler, final=StatementRestoreFrameException( preserver_id=preserver_id, source_ref=source_ref.atInternal()), public_exc=False, source_ref=source_ref, ) except_handler = makeStatementsSequenceFromStatement( statement=except_handler) except_handler.parent = provider else: except_handler = None if tried.mayBreak(): break_handler = getStatementsAppended( statement_sequence=final.makeClone(), statements=StatementLoopBreak(source_ref=source_ref)) break_handler.parent = provider else: break_handler = None if tried.mayContinue(): continue_handler = getStatementsAppended( statement_sequence=final.makeClone(), statements=StatementLoopContinue(source_ref=source_ref)) continue_handler.parent = provider else: continue_handler = None if tried.mayReturn(): return_handler = getStatementsAppended( statement_sequence=final.makeClone(), statements=StatementReturn( expression=ExpressionReturnedValueRef(source_ref=source_ref), source_ref=source_ref)) else: return_handler = None result = StatementTry(tried=tried, except_handler=except_handler, break_handler=break_handler, continue_handler=continue_handler, return_handler=return_handler, source_ref=source_ref) if result.isStatementAborting(): return result else: return makeStatementsSequence(statements=(result, final), allow_none=False, source_ref=source_ref)