Example #1
0
def buildAwaitNode(provider, node, source_ref):
    return ExpressionYieldFromWaitable(
        expression=ExpressionAsyncWait(
            expression=buildNode(provider, node.value, source_ref),
            source_ref=source_ref,
        ),
        source_ref=source_ref,
    )
Example #2
0
def _buildWithNode(provider, context_expr, assign_target, body, body_lineno,
                   sync, source_ref):
    # Many details, pylint: disable=too-many-locals
    with_source = buildNode(provider, context_expr, source_ref)

    if Options.isFullCompat():
        source_ref = with_source.getCompatibleSourceReference()

    temp_scope = provider.allocateTempScope("with")

    tmp_source_variable = provider.allocateTempVariable(
        temp_scope = temp_scope,
        name       = "source"
    )
    tmp_exit_variable = provider.allocateTempVariable(
        temp_scope = temp_scope,
        name       = "exit"
    )
    tmp_enter_variable = provider.allocateTempVariable(
        temp_scope = temp_scope,
        name       = "enter"
    )
    tmp_indicator_variable = provider.allocateTempVariable(
        temp_scope = temp_scope,
        name       = "indicator"
    )

    statements = (
        buildAssignmentStatements(
            provider   = provider,
            node       = assign_target,
            allow_none = True,
            source     = ExpressionTempVariableRef(
                variable   = tmp_enter_variable,
                source_ref = source_ref
            ),
            source_ref = source_ref
        ),
        body
    )

    with_body = makeStatementsSequence(
        statements = statements,
        allow_none = True,
        source_ref = source_ref
    )

    if Options.isFullCompat():
        if body:
            deepest = body

            while deepest.getVisitableNodes():
                deepest = deepest.getVisitableNodes()[-1]

            body_lineno = deepest.getCompatibleSourceReference().getLineNumber()

        with_exit_source_ref = source_ref.atLineNumber(body_lineno)
    else:
        with_exit_source_ref = source_ref

    # The "__enter__" and "__exit__" were normal attribute lookups under
    # CPython2.6, but that changed with CPython2.7.
    if python_version < 270:
        attribute_lookup_class = ExpressionAttributeLookup
    else:
        attribute_lookup_class = ExpressionAttributeLookupSpecial

    enter_value = ExpressionCallEmpty(
        called     = attribute_lookup_class(
            source         = ExpressionTempVariableRef(
                variable   = tmp_source_variable,
                source_ref = source_ref
            ),
            attribute_name = "__enter__" if sync else "__aenter__",
            source_ref     = source_ref
        ),
        source_ref = source_ref
    )

    exit_value_exception = ExpressionCallNoKeywords(
        called     = ExpressionTempVariableRef(
            variable   = tmp_exit_variable,
            source_ref = with_exit_source_ref
        ),
        args       = ExpressionMakeTuple(
            elements   = (
                ExpressionCaughtExceptionTypeRef(
                    source_ref = with_exit_source_ref
                ),
                ExpressionCaughtExceptionValueRef(
                    source_ref = with_exit_source_ref
                ),
                ExpressionCaughtExceptionTracebackRef(
                    source_ref = source_ref
                ),
            ),
            source_ref = source_ref
        ),
        source_ref = with_exit_source_ref
    )

    exit_value_no_exception = ExpressionCallNoKeywords(
        called     = ExpressionTempVariableRef(
            variable   = tmp_exit_variable,
            source_ref = source_ref
        ),
        args       = makeConstantRefNode(
            constant   = (None, None, None),
            source_ref = source_ref
        ),
        source_ref = with_exit_source_ref
    )

    # For "async with", await the entered value and exit value must be awaited.
    if not sync:
        enter_value = ExpressionAsyncWait(
            expression = enter_value,
            source_ref = source_ref
        )
        exit_value_exception = ExpressionAsyncWait(
            expression = exit_value_exception,
            source_ref = source_ref
        )
        exit_value_no_exception = ExpressionAsyncWait(
            expression = exit_value_no_exception,
            source_ref = source_ref
        )

    statements = [
        # First assign the with context to a temporary variable.
        StatementAssignmentVariable(
            variable   = tmp_source_variable,
            source     = with_source,
            source_ref = source_ref
        )
    ]

    attribute_assignments = [
        # Next, assign "__enter__" and "__exit__" attributes to temporary
        # variables.
        StatementAssignmentVariable(
            variable   = tmp_exit_variable,
            source     = attribute_lookup_class(
                source         = ExpressionTempVariableRef(
                    variable   = tmp_source_variable,
                    source_ref = source_ref
                ),
                attribute_name = "__exit__" if sync else "__aexit__",
                source_ref     = source_ref
            ),
            source_ref = source_ref
        ),
        StatementAssignmentVariable(
            variable   = tmp_enter_variable,
            source     = enter_value,
            source_ref = source_ref
        )
    ]

    if python_version >= 360 and sync:
        attribute_assignments.reverse()

    statements += attribute_assignments

    statements.append(
        StatementAssignmentVariable(
            variable   = tmp_indicator_variable,
            source     = makeConstantRefNode(
                constant   = True,
                source_ref = source_ref
            ),
            source_ref = source_ref
        )
    )

    statements += [
        makeTryFinallyStatement(
            provider   = provider,
            tried      = makeTryExceptSingleHandlerNodeWithPublish(
                provider       = provider,
                tried          = with_body,
                exception_name = "BaseException",
                handler_body   = StatementsSequence(
                    statements = (
                        # Prevents final block from calling __exit__ as
                        # well.
                        StatementAssignmentVariable(
                            variable   = tmp_indicator_variable,
                            source     = makeConstantRefNode(
                                constant   = False,
                                source_ref = source_ref
                            ),
                            source_ref = source_ref
                        ),
                        makeConditionalStatement(
                            condition  = exit_value_exception,
                            no_branch  = makeReraiseExceptionStatement(
                                source_ref = with_exit_source_ref
                            ),
                            yes_branch = None,
                            source_ref = with_exit_source_ref
                        ),
                    ),
                    source_ref = source_ref
                ),
                public_exc     = python_version >= 270,
                source_ref     = source_ref
            ),
            final      = StatementConditional(
                condition  = ExpressionComparisonIs(
                    left       = ExpressionTempVariableRef(
                        variable   = tmp_indicator_variable,
                        source_ref = source_ref
                    ),
                    right      = makeConstantRefNode(
                        constant   = True,
                        source_ref = source_ref
                    ),
                    source_ref = source_ref
                ),
                yes_branch = makeStatementsSequenceFromStatement(
                    statement = StatementExpressionOnly(
                        expression = exit_value_no_exception,
                        source_ref = source_ref
                    )
                ),
                no_branch  = None,
                source_ref = source_ref
            ),
            source_ref = source_ref
        )
    ]

    return makeTryFinallyStatement(
        provider   = provider,
        tried      = statements,
        final      = (
            StatementReleaseVariable(
                variable   = tmp_source_variable,
                source_ref = with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable   = tmp_enter_variable,
                source_ref = with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable   = tmp_exit_variable,
                source_ref = with_exit_source_ref
            ),
            StatementReleaseVariable(
                variable   = tmp_indicator_variable,
                source_ref = with_exit_source_ref
            ),
        ),
        source_ref = source_ref
    )
Example #3
0
def buildAwaitNode(provider, node, source_ref):
    return ExpressionAsyncWait(expression=buildNode(provider, node.value,
                                                    source_ref),
                               source_ref=source_ref)