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,
    )
Exemple #2
0
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
    )
Exemple #3
0
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,
        )
Exemple #6
0
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
        )
Exemple #7
0
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)