Source code for autowire.impl
"""
impl
====
Implementers.
"""
import contextlib
import functools
from autowire.base import BaseContext, BaseResource
from autowire.decorators import autowired
from autowire.utils import apply_decorators, as_contextmanager
from .types import Implementable, Implementation
[docs]def implement(target: Implementable):
"""
Implement it. ::
@implement(resource)
@contextlib.contextmanager
def implementation(context: Context):
with open('output.log', 'w') as ouput:
yield output
"""
def decorator(implementation: Implementation):
target.implement(implementation)
return implementation
return decorator
[docs]def with_decorators(target: Implementable, *decorators):
"""
Set default implementation with decorators.
It sets implementation with decorators but returns original function
not decorated function so that does not change function's interface.
"""
def decorator(fn):
implement(target)(apply_decorators(fn, decorators))
return fn
return decorator
[docs]def contextual(target: Implementable, *dependencies: BaseResource,
decorators=()):
"""
Implement with contextual & autowired resources. ::
@impl.contextual(resource, dependency1, dependency2)
@contextlib.contextmanager
def create_resource(dependency1, dependency2):
yield dependency1.make_resource(dependency2)
To apply decorators to implementation ::
@impl.contextual(resource, dependency, decorators=[decorator])
@contextlib.contextmanager
def create_resource(dependency):
yield dependency.make_resource()
"""
return with_decorators(target, autowired(*dependencies), *decorators)
[docs]def plain(target: Implementable, *dependencies, decorators=()):
"""
Implement with plain function. ::
@impl.plain(resource, dependency)
def get_resource(dependency):
return os.path.join(dependency, 'resource.json')
"""
return with_decorators(
target,
as_contextmanager,
autowired(*dependencies),
*decorators)
def partial(target: Implementable, *positionals, decorators=(), **keywords):
"""
Implement the target by applying resolved resources partially
to function. ::
@partial(resource, dependency1, baz=dependency2):
def implementation(foo, bar, baz):
print(foo) # dependency1
print(bar) # argument
print(baz) # dependency2
You can use this resource like ::
with context.resolve(resource) as function:
function("argument")
"""
def decorator(fn):
@contextlib.contextmanager
def implementation(context: BaseContext):
keyword_items = list(keywords.items())
keyword_keys = [k for k, _ in keyword_items]
keyword_resources = [v for _, v in keyword_items]
with context.resolve_all(positionals) as resolved_args, \
context.resolve_all(keyword_resources) as \
resolved_kwarg_values:
resolved_kwargs = {}
for k, v in zip(keyword_keys, resolved_kwarg_values):
resolved_kwargs[k] = v
partial = functools.partial(fn,
*resolved_args,
**resolved_kwargs)
yield partial
implement(target)(apply_decorators(implementation, decorators))
return decorator
__all__ = [
'implement',
'with_decorators',
'plain',
'contextual',
'Implementation',
]