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 makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise, source_ref): # This helper executes the core re-formulation of "no_raise" blocks, which # are the "else" blocks of "try"/"except" statements. In order to limit the # execution, we use an indicator variable instead, which will signal that # the tried block executed up to the end. And then we make the else block be # a conditional statement checking that. # Indicator variable, will end up with C bool type, and need not be released. tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator", temp_type="bool") statements = mergeStatements( ( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=False, source_ref=source_ref), source_ref=no_raise.getSourceReference(), ), handling, ), allow_none=True, ) handling = StatementsSequence(statements=statements, source_ref=source_ref) return makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable=tmp_handler_indicator_variable, source=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), StatementTry( tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), makeStatementConditional( condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_handler_indicator_variable, source_ref=source_ref), right=makeConstantRefNode(constant=True, source_ref=source_ref), source_ref=source_ref, ), yes_branch=no_raise, no_branch=None, source_ref=source_ref, ), )
def makeTryExceptNoRaise(provider, temp_scope, tried, handling, no_raise, source_ref): # This helper executes the core re-formulation of "no_raise" blocks, which # are the "else" blocks of "try"/"except" statements. In order to limit the # execution, we use an indicator variable instead, which will signal that # the tried block executed up to the end. And then we make the else block be # a conditional statement checking that. if tried is None: return no_raise tmp_handler_indicator_variable = provider.allocateTempVariable( temp_scope=temp_scope, name="unhandled_indicator") statements = mergeStatements((StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable, source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=False, source_ref=source_ref), source_ref=no_raise.getSourceReference().atInternal()), handling), allow_none=True) handling = StatementsSequence(statements=statements, source_ref=source_ref) tried = (StatementTry(tried=tried, except_handler=handling, break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref), StatementConditional(condition=ExpressionComparisonIs( left=ExpressionTempVariableRef( variable=tmp_handler_indicator_variable, source_ref=source_ref), right=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref), yes_branch=no_raise, no_branch=None, source_ref=source_ref)) final = StatementReleaseVariable(variable=tmp_handler_indicator_variable, source_ref=source_ref.atInternal()) return makeStatementsSequenceFromStatements( StatementAssignmentVariable( variable_ref=ExpressionTargetTempVariableRef( variable=tmp_handler_indicator_variable, source_ref=source_ref.atInternal()), source=ExpressionConstantRef(constant=True, source_ref=source_ref), source_ref=source_ref.atInternal()), makeTryFinallyStatement(provider=provider, tried=tried, final=final, source_ref=source_ref))
def buildClassNode2(provider, node, source_ref): # This function is the Python2 special case with special re-formulation as # according to developer manual, and it's very detailed, pylint: disable=too-many-locals class_statement_nodes, class_doc = extractDocFromBody(node) function_body = ExpressionClassBody(provider=provider, name=node.name, doc=class_doc, source_ref=source_ref) parent_module = provider.getParentModule() code_object = CodeObjectSpec( co_name=node.name, co_kind="Class", co_varnames=(), co_argcount=0, co_posonlyargcount=0, co_kwonlyargcount=0, co_has_starlist=False, co_has_stardict=False, co_filename=parent_module.getRunTimeFilename(), co_lineno=source_ref.getLineNumber(), future_spec=parent_module.getFutureSpec(), ) body = buildFrameNode( provider=function_body, nodes=class_statement_nodes, code_object=code_object, source_ref=source_ref, ) if body is not None: # The frame guard has nothing to tell its line number to. body.source_ref = source_ref.atInternal() locals_scope = function_body.getLocalsScope() # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained, and # starts out with a variables "__module__" and potentially "__doc__" set. statements = [ StatementSetLocalsDictionary(locals_scope=locals_scope, source_ref=source_ref), StatementAssignmentVariableName( provider=function_body, variable_name="__module__", source=ExpressionModuleAttributeNameRef( variable=provider.getParentModule().getVariableForReference( "__name__"), source_ref=source_ref, ), source_ref=source_ref.atInternal(), ), ] if class_doc is not None: statements.append( StatementAssignmentVariableName( provider=function_body, variable_name="__doc__", source=makeConstantRefNode(constant=class_doc, source_ref=source_ref, user_provided=True), source_ref=source_ref.atInternal(), )) statements += ( body, StatementReturn( expression=ExpressionBuiltinLocalsRef(locals_scope=locals_scope, source_ref=source_ref), source_ref=source_ref, ), ) body = makeStatementsSequenceFromStatement( statement=makeTryFinallyStatement( provider=function_body, tried=mergeStatements(statements, True), final=StatementReleaseLocals(locals_scope=locals_scope, source_ref=source_ref), source_ref=source_ref, )) # The class body is basically a function that implicitly, at the end # returns its locals and cannot have other return statements contained. function_body.setBody(body) temp_scope = provider.allocateTempScope("class_creation") tmp_bases = provider.allocateTempVariable(temp_scope, "bases") tmp_class_dict = provider.allocateTempVariable(temp_scope, "class_dict") tmp_metaclass = provider.allocateTempVariable(temp_scope, "metaclass") tmp_class = provider.allocateTempVariable(temp_scope, "class") select_metaclass = ExpressionOutlineBody(provider=provider, name="select_metaclass", body=None, source_ref=source_ref) if node.bases: tmp_base = select_metaclass.allocateTempVariable(temp_scope=None, name="base") statements = ( StatementAssignmentVariable( variable=tmp_base, source=ExpressionSubscriptLookup( expression=ExpressionTempVariableRef( variable=tmp_bases, source_ref=source_ref), subscript=makeConstantRefNode(constant=0, source_ref=source_ref, user_provided=True), source_ref=source_ref, ), source_ref=source_ref, ), makeTryFinallyStatement( provider, tried=StatementTry( tried=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionAttributeLookup( expression=ExpressionTempVariableRef( variable=tmp_base, source_ref=source_ref), attribute_name="__class__", source_ref=source_ref, ), source_ref=source_ref, )), except_handler=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionBuiltinType1( value=ExpressionTempVariableRef( variable=tmp_base, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, )), break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), final=StatementReleaseVariable(variable=tmp_base, source_ref=source_ref), source_ref=source_ref, public_exc=False, ), ) else: statements = ( StatementTry( tried=makeStatementsSequenceFromStatement( statement=StatementReturn( # TODO: Should avoid checking __builtins__ for this. expression=ExpressionVariableNameRef( variable_name="__metaclass__", provider=parent_module, source_ref=source_ref, ), source_ref=source_ref, )), except_handler=makeStatementsSequenceFromStatement( statement=StatementReturn( expression=ExpressionBuiltinAnonymousRef( builtin_name="classobj", source_ref=source_ref), source_ref=source_ref, )), break_handler=None, continue_handler=None, return_handler=None, source_ref=source_ref, ), ) select_metaclass.setBody( makeStatementsSequence(statements=statements, allow_none=False, source_ref=source_ref)) statements = [ StatementAssignmentVariable( variable=tmp_bases, source=makeSequenceCreationOrConstant( sequence_kind="tuple", elements=buildNodeList(provider=provider, nodes=node.bases, source_ref=source_ref), source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable(variable=tmp_class_dict, source=function_body, source_ref=source_ref), StatementAssignmentVariable( variable=tmp_metaclass, source=ExpressionConditional( condition=ExpressionDictOperationIn( key=makeConstantRefNode( constant="__metaclass__", source_ref=source_ref, user_provided=True, ), dict_arg=ExpressionTempVariableRef(variable=tmp_class_dict, source_ref=source_ref), source_ref=source_ref, ), expression_yes=ExpressionDictOperationGet( dict_arg=ExpressionTempVariableRef(variable=tmp_class_dict, source_ref=source_ref), key=makeConstantRefNode( constant="__metaclass__", source_ref=source_ref, user_provided=True, ), source_ref=source_ref, ), expression_no=select_metaclass, source_ref=source_ref, ), source_ref=source_ref, ), StatementAssignmentVariable( variable=tmp_class, source=makeExpressionCall( called=ExpressionTempVariableRef(variable=tmp_metaclass, source_ref=source_ref), args=ExpressionMakeTuple( elements=( makeConstantRefNode( constant=node.name, source_ref=source_ref, user_provided=True, ), ExpressionTempVariableRef(variable=tmp_bases, source_ref=source_ref), ExpressionTempVariableRef(variable=tmp_class_dict, source_ref=source_ref), ), source_ref=source_ref, ), kw=None, source_ref=source_ref, ), source_ref=source_ref, ), ] for decorator in buildNodeList(provider, reversed(node.decorator_list), source_ref): statements.append( StatementAssignmentVariable( variable=tmp_class, source=makeExpressionCall( called=decorator, args=ExpressionMakeTuple( elements=(ExpressionTempVariableRef( variable=tmp_class, source_ref=source_ref), ), source_ref=source_ref, ), kw=None, source_ref=decorator.getSourceReference(), ), source_ref=decorator.getSourceReference(), )) statements.append( StatementAssignmentVariableName( provider=provider, variable_name=mangleName(node.name, provider), source=ExpressionTempVariableRef(variable=tmp_class, source_ref=source_ref), source_ref=source_ref, )) final = ( StatementReleaseVariable(variable=tmp_class, source_ref=source_ref), StatementReleaseVariable(variable=tmp_bases, source_ref=source_ref), StatementReleaseVariable(variable=tmp_class_dict, source_ref=source_ref), StatementReleaseVariable(variable=tmp_metaclass, source_ref=source_ref), ) return makeTryFinallyStatement(provider=function_body, tried=statements, final=final, 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 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 )
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)