GitHub

API reference for scope.

Scopes: where resources register their release.

acquire_release adds a finalizer to the current Scope (which joins R); scoped creates a scope, runs the effect in it, and closes it however the effect ends, removing Scope from R. Finalizers run in reverse order of registration, uninterruptibly, and all of them run even if some fail.

Classes

Functions

scoped

scoped(eff) -> Effect[Any, Any, Any]

Run eff in a new scope and close it when eff ends.

ParameterTypeDescription
effEffect[Any, Any, Any]

Returns Effect[Any, Any, Any]

def scoped(eff: Effect[Any, Any, Any]) -> Effect[Any, Any, Any]:
    """Run ``eff`` in a new scope and close it when ``eff`` ends."""
    require_effect(eff, "eff")

    def body() -> Effect[Any, Any, Any]:
        scope = CloseableScope()
        inner: Effect[Any, Any, Any] = _Locally(eff, lambda ctx: ctx.add(Scope, scope))
        return inner.on_exit(scope.close)

    return _Suspend(body)

scoped_with

scoped_with(f) -> Effect[A, E, R]

Run f with a new scope and close it when the effect f gives ends.

ParameterTypeDescription
fCallable[[CloseableScope], Effect[A, E, R]]

Returns Effect[A, E, R]

def scoped_with[A, E = Never, R = Never](
    f: Callable[[CloseableScope], Effect[A, E, R]],
) -> Effect[A, E, R]:
    """Run ``f`` with a new scope and close it when the effect ``f`` gives
    ends."""

    def body() -> Effect[A, E, R]:
        scope = CloseableScope()
        return _call_user(f, scope).on_exit(scope.close)

    return _Suspend(body)

add_finalizer

add_finalizer(f) -> Effect[None, Never, Scope | R]
ParameterTypeDescription
fCallable[[Exit[Any, Any]], Effect[object, Never, R]]

Returns Effect[None, Never, Scope | R]

def add_finalizer[R = Never](
    f: Callable[[Exit[Any, Any]], Effect[object, Never, R]],
) -> Effect[None, Never, Scope | R]:
    return Scope().flat_map(lambda scope: scope.add_finalizer(f))

acquire_release

acquire_release(acquire, release) -> Effect[A, E, RR | Scope]

Acquire uninterruptibly and register release on the current scope.

ParameterTypeDescription
acquireEffect[A, E, RR]
releaseCallable[[A, Exit[Any, Any]], Effect[object, Never, RR]]

Returns Effect[A, E, RR | Scope]

def acquire_release[A, E = Never, RR = Never](
    acquire: Effect[A, E, RR],
    release: Callable[[A, Exit[Any, Any]], Effect[object, Never, RR]],
) -> Effect[A, E, RR | Scope]:
    """Acquire uninterruptibly and register ``release`` on the current
    scope."""
    require_effect(acquire, "acquire")

    def body():
        a = yield from acquire
        scope = yield from Scope()
        yield from scope.add_finalizer(lambda ex: release(a, ex))
        return a

    return _Gen(body).uninterruptible()

acquire_use_release

acquire_use_release(acquire, use, release) -> Effect[B, EE, RR]

Acquire, use, and always release, without needing a scope.

ParameterTypeDescription
acquireEffect[A, EE, RR]
useCallable[[A], Effect[B, EE, RR]]
releaseCallable[[A, Exit[B, EE]], Effect[object, Never, RR]]

Returns Effect[B, EE, RR]

def acquire_use_release[A, B, EE = Never, RR = Never](
    acquire: Effect[A, EE, RR],
    use: Callable[[A], Effect[B, EE, RR]],
    release: Callable[[A, Exit[B, EE]], Effect[object, Never, RR]],
) -> Effect[B, EE, RR]:
    """Acquire, use, and always release, without needing a scope."""
    require_effect(acquire, "acquire")
    return uninterruptible_mask(
        lambda restore: acquire.flat_map(
            lambda a: restore(_call_user(use, a)).on_exit(lambda ex: release(a, ex))
        )
    )

fork_scoped

fork_scoped(eff, *, start_immediately=False, uninterruptible=False) -> Effect[Fiber[A, E], Never, R | Scope]

Fork eff into the current scope (see fork_in).

ParameterTypeDescription
effEffect[A, E, R]
start_immediatelybool = False
uninterruptibleUninterruptible = False

Returns Effect[Fiber[A, E], Never, R | Scope]

def fork_scoped[A, E, R](
    eff: Effect[A, E, R],
    *,
    start_immediately: bool = False,
    uninterruptible: Uninterruptible = False,
) -> Effect[Fiber[A, E], Never, R | Scope]:
    """Fork ``eff`` into the current scope (see ``fork_in``)."""
    require_effect(eff, "eff")
    return Scope().flat_map(
        lambda scope: fork_in(
            eff, scope, start_immediately=start_immediately, uninterruptible=uninterruptible
        )
    )

fork_in

fork_in(eff, scope, *, start_immediately=False, uninterruptible=False) -> Effect[Fiber[A, E], Never, R]

Fork eff on a fiber that outlives its parent but is interrupted when scope closes, and leaves the scope when it exits. Into a closed scope it gives an already-interrupted fiber that never ran eff.

ParameterTypeDescription
effEffect[A, E, R]
scopeCloseableScope
start_immediatelybool = False
uninterruptibleUninterruptible = False

Returns Effect[Fiber[A, E], Never, R]

def fork_in[A, E, R](
    eff: Effect[A, E, R],
    scope: CloseableScope,
    *,
    start_immediately: bool = False,
    uninterruptible: Uninterruptible = False,
) -> Effect[Fiber[A, E], Never, R]:
    """Fork ``eff`` on a fiber that outlives its parent but is interrupted
    when ``scope`` closes, and leaves the scope when it exits. Into a
    closed scope it gives an already-interrupted fiber that never ran
    ``eff``."""
    require_effect(eff, "eff")

    def body(parent: Fiber[Any, Any]) -> Effect[Fiber[A, E]]:
        if scope._closed is not None:
            unstarted: Fiber[A, E] = Fiber(parent._run_scheduler, parent._context, None)
            unstarted.unsafe_interrupt_as(parent.id, parent._interruptor_annotations())
            return _Succeed(unstarted)
        fiber: Fiber[A, E] = parent._fork(
            eff, daemon=True, start_immediately=start_immediately, uninterruptible=uninterruptible
        )
        scope._watch(fiber)
        return _AfterStarted(fiber)

    return _WithFiber(body)