Shared Resource

The resource can be used multiple times in one context. Sometimes you don’t want to build a new resource for each usages. You can share resources by shared decorator.

Sharing Resource

from contextlib import contextmanager

from autowire import Context, Resource
from autowire.decorators import shared

dog = Resource('dog', __name__)
walk = Resource('walk', __name__)

@dog.impl
@shared
@contextmanager
def with_dog(context):
    print("Dog is entering")
    try:
        yield "🐶"
    finally:
        print("Dog leaved")

@walk.impl
@contextmanager
def with_walking(context):
    with context.resolve(dog) as dog_value:
        yield "Walking with {}".format(dog_value)

context = Context()

with context.resolve(walk) as message:
    print(message)
    with context.resolve(dog) as dog_value:
        print("Feeding {}".format(dog_value))

# Output:
# Dog is entering
# Walking with 🐶
# Feeding 🐶
# Dog leaved

Since dog resource is shared resource, setup & teardown were called only once.

Globally Shared Resource

When you have nested contexts, the shared resource will be created for each contexts. If you want to have only one resource per whole contexts, you can do that with globally_shared decorator.

from contextlib import contextmanager

from autowire import Context, Resource, impl
from autowire.decorators import shared

dog = Resource('dog', __name__)
walk = Resource('walk', __name__)

@impl.implement(dog)
@globally_shared
@contextmanager
def with_dog(context):
    print("Dog is entering")
    try:
        yield "🐶"
    finally:
        print("Dog leaved")

@impl.implement(walk)
@contextmanager
def with_walking(context):
    with context.resolve(dog) as dog_value:
        yield "Walking with {}".format(dog_value)

context = Context()
child = Context(context)

with context.resolve(walk) as message:
    print(message)
    with child.resolve(dog) as dog_value:
        print("Feeding {}".format(dog_value))

# Output:
# Dog is entering
# Walking with 🐶
# Feeding 🐶
# Dog leaved

Since, globally shared resource can be only defined on providing context, it can’t use children context’s resources.

from contextlib import contextmanager

from autowire import Context, Resource
from autowire.decorators import shared

dog = Resource('dog', __name__)
walk = Resource('walk', __name__)

@impl.implement(walk)
@globally_shared
@contextmanager
def with_walking(context):
    with context.resolve(dog) as dog_value:
        yield "Walking with {}".format(dog_value)

context = Context()
child = Context(context)

# Provide dog
@impl.implement(child(dog))
@contextmanager
def with_dog(context):
    yield "🐶"

# Will raise ResourceNotProvidedError
with child.resolve(walk) as message:
    ...