Commit 6cc0b138 authored by xa's avatar xa

func can be sync or awaitable

parent a44f87a4
...@@ -36,6 +36,40 @@ For example:: ...@@ -36,6 +36,40 @@ For example::
assert (yield from services.apply(fun)) == {'foo': 'I am foo', assert (yield from services.apply(fun)) == {'foo': 'I am foo',
'bar': 'I am bar'} 'bar': 'I am bar'}
The :func:`func` can be a function or an awaitable. These 2 examples works the same::
@annotate('foo', 'bar')
def sync_fun(foo, bar):
return {'foo': foo,
'bar': bar}
assert (yield from services.apply(sync_fun)) == {'foo': 'I am foo',
'bar': 'I am bar'}
@annotate('foo', 'bar')
async def awaitable_fun(foo, bar):
return {'foo': foo,
'bar': bar}
assert (yield from services.apply(awaitable_fun)) == {'foo': 'I am foo',
'bar': 'I am bar'}
Factories also can be either sync or awaitable::
@services.factory('bar:sync')
def bar_factory():
return 'I am bar'
@services.factory('bar:awaitable')
async def bar_factory():
return 'I am bar'
Implementation Implementation
-------------- --------------
......
...@@ -134,7 +134,10 @@ class Injector(metaclass=ABCMeta): ...@@ -134,7 +134,10 @@ class Injector(metaclass=ABCMeta):
service_kwargs[key] = service service_kwargs[key] = service
service_args.extend(args) service_args.extend(args)
service_kwargs.update(kwargs) service_kwargs.update(kwargs)
return func(*service_args, **service_kwargs) result = func(*service_args, **service_kwargs)
if asyncio.iscoroutine(result):
result = yield from result
return result
logger.warn('%r is not annoted' % func) logger.warn('%r is not annoted' % func)
return func(*args, **kwargs) return func(*args, **kwargs)
return wrapper return wrapper
......
...@@ -3,7 +3,7 @@ from knighted import Injector, annotate ...@@ -3,7 +3,7 @@ from knighted import Injector, annotate
@pytest.mark.asyncio @pytest.mark.asyncio
def test_instance_factory(): async def test_instance_factory():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -14,13 +14,13 @@ def test_instance_factory(): ...@@ -14,13 +14,13 @@ def test_instance_factory():
return 'I am foo' return 'I am foo'
@services.factory('bar') @services.factory('bar')
def bar_factory(): async def bar_factory():
return 'I am bar' return 'I am bar'
@services.factory('all') @services.factory('all')
def together_factory(): async def together_factory():
foo = yield from services.get('foo') foo = await services.get('foo')
bar = yield from services.get('bar') bar = await services.get('bar')
return [foo, bar] return [foo, bar]
@annotate('foo', 'bar') @annotate('foo', 'bar')
...@@ -28,15 +28,22 @@ def test_instance_factory(): ...@@ -28,15 +28,22 @@ def test_instance_factory():
return {'foo': foo, return {'foo': foo,
'bar': bar} 'bar': bar}
assert (yield from services.get('foo')) == 'I am foo' @annotate('foo', 'bar')
assert (yield from services.get('bar')) == 'I am bar' async def awaitable_fun(foo, bar):
assert (yield from services.get('all')) == ['I am foo', 'I am bar'] return {'foo': foo,
assert (yield from services.apply(fun)) == {'foo': 'I am foo', 'bar': bar}
'bar': 'I am bar'}
assert (await services.get('foo')) == 'I am foo'
assert (await services.get('bar')) == 'I am bar'
assert (await services.get('all')) == ['I am foo', 'I am bar']
assert (await services.apply(fun)) == {'foo': 'I am foo',
'bar': 'I am bar'}
assert (await services.apply(awaitable_fun)) == {'foo': 'I am foo',
'bar': 'I am bar'}
@pytest.mark.asyncio @pytest.mark.asyncio
def test_partial(): async def test_partial():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -58,12 +65,12 @@ def test_partial(): ...@@ -58,12 +65,12 @@ def test_partial():
assert len(services.services) == 0 assert len(services.services) == 0
part = services.partial(fun) part = services.partial(fun)
assert len(services.services) == 0 assert len(services.services) == 0
assert (yield from part()) == {'foo': 'I am foo', 'bar': 'I am bar'} assert (await part()) == {'foo': 'I am foo', 'bar': 'I am bar'}
assert len(services.services) == 2 assert len(services.services) == 2
@pytest.mark.asyncio @pytest.mark.asyncio
def test_class_factory(): async def test_class_factory():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -76,9 +83,9 @@ def test_class_factory(): ...@@ -76,9 +83,9 @@ def test_class_factory():
return 'I am bar' return 'I am bar'
@MyInjector.factory('all') @MyInjector.factory('all')
def together_factory(): async def together_factory():
foo = yield from services.get('foo') foo = await services.get('foo')
bar = yield from services.get('bar') bar = await services.get('bar')
return [foo, bar] return [foo, bar]
@annotate('foo', 'bar') @annotate('foo', 'bar')
...@@ -88,22 +95,22 @@ def test_class_factory(): ...@@ -88,22 +95,22 @@ def test_class_factory():
services = MyInjector() services = MyInjector()
assert (yield from services.get('foo')) == 'I am foo' assert (await services.get('foo')) == 'I am foo'
assert (yield from services.get('bar')) == 'I am bar' assert (await services.get('bar')) == 'I am bar'
assert (yield from services.get('all')) == ['I am foo', 'I am bar'] assert (await services.get('all')) == ['I am foo', 'I am bar']
assert (yield from services.apply(fun)) == {'foo': 'I am foo', assert (await services.apply(fun)) == {'foo': 'I am foo',
'bar': 'I am bar'} 'bar': 'I am bar'}
@pytest.mark.asyncio @pytest.mark.asyncio
def test_undefined_service_error(): async def test_undefined_service_error():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
services = MyInjector() services = MyInjector()
with pytest.raises(ValueError): with pytest.raises(ValueError):
yield from services.get('foo') await services.get('foo')
def test_annotate_error(): def test_annotate_error():
...@@ -113,7 +120,7 @@ def test_annotate_error(): ...@@ -113,7 +120,7 @@ def test_annotate_error():
@pytest.mark.asyncio @pytest.mark.asyncio
def test_kw_apply(): async def test_kw_apply():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -130,12 +137,12 @@ def test_kw_apply(): ...@@ -130,12 +137,12 @@ def test_kw_apply():
def fun2(baz): def fun2(baz):
return 'nor %s' % baz return 'nor %s' % baz
assert (yield from services.apply(fun, bar='baz')) == 'I am bar, not baz' assert (await services.apply(fun, bar='baz')) == 'I am bar, not baz'
assert (yield from services.apply(fun2, 'baz')) == 'nor baz' assert (await services.apply(fun2, 'baz')) == 'nor baz'
@pytest.mark.asyncio @pytest.mark.asyncio
def test_late_register(): async def test_late_register():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -145,11 +152,11 @@ def test_late_register(): ...@@ -145,11 +152,11 @@ def test_late_register():
services = MyInjector() services = MyInjector()
services.factory('foo', factory_foo) services.factory('foo', factory_foo)
assert (yield from services.get('foo')) == 'I am foo' assert (await services.get('foo')) == 'I am foo'
@pytest.mark.asyncio @pytest.mark.asyncio
def test_sub_factory(): async def test_sub_factory():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -163,12 +170,12 @@ def test_sub_factory(): ...@@ -163,12 +170,12 @@ def test_sub_factory():
def bar_factory(): def bar_factory():
return 'I am bar' return 'I am bar'
assert (yield from services.get('foo')) == 'I am foo' assert (await services.get('foo')) == 'I am foo'
assert (yield from services.get('foo:bar')) == 'I am bar' assert (await services.get('foo:bar')) == 'I am bar'
@pytest.mark.asyncio @pytest.mark.asyncio
def test_close(): async def test_close():
class MyInjector(Injector): class MyInjector(Injector):
pass pass
...@@ -183,8 +190,8 @@ def test_close(): ...@@ -183,8 +190,8 @@ def test_close():
return 'I am bar' return 'I am bar'
assert len(services.services) == 0 assert len(services.services) == 0
yield from services.get('foo') await services.get('foo')
yield from services.get('foo:bar') await services.get('foo:bar')
assert len(services.services) == 2 assert len(services.services) == 2
services.close() services.close()
assert len(services.services) == 0 assert len(services.services) == 0
...@@ -196,7 +203,6 @@ def test_close_register(): ...@@ -196,7 +203,6 @@ def test_close_register():
services = MyInjector() services = MyInjector()
class Foo: class Foo:
def __init__(self): def __init__(self):
...@@ -206,6 +212,7 @@ def test_close_register(): ...@@ -206,6 +212,7 @@ def test_close_register():
self.value = value self.value = value
foo = Foo() foo = Foo()
def reaction(obj): def reaction(obj):
obj.set_value('baz') obj.set_value('baz')
services.close.register(foo, reaction=reaction) services.close.register(foo, reaction=reaction)
...@@ -219,7 +226,6 @@ def test_close_unregister(): ...@@ -219,7 +226,6 @@ def test_close_unregister():
services = MyInjector() services = MyInjector()
class Foo: class Foo:
def __init__(self): def __init__(self):
...@@ -229,6 +235,7 @@ def test_close_unregister(): ...@@ -229,6 +235,7 @@ def test_close_unregister():
self.value = value self.value = value
foo = Foo() foo = Foo()
def reaction(obj): def reaction(obj):
obj.set_value('baz') obj.set_value('baz')
services.close.register(foo, reaction=reaction) services.close.register(foo, reaction=reaction)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment