diff --git a/README.md b/README.md index 293e649e..7e604ec1 100644 --- a/README.md +++ b/README.md @@ -310,3 +310,50 @@ assert (object_a2 is not object_a3) and \ (object_a2 is not object_a5) and \ (object_a2 is not object_a6) ``` + +Example of objects catalog with callable provider: + +```python +""" +Callable provider examples. +""" + +from objects import AbstractCatalog +from objects.providers import Singleton, Callable +from objects.injections import Injection, InitArg, Attribute + +import sqlite3 + + +# Some example function. +def consuming_function(arg, db): + return arg, db + + +# Catalog of objects providers. +class Catalog(AbstractCatalog): + """ + Objects catalog. + """ + + database = Singleton(sqlite3.Connection, + InitArg('database', ':memory:'), + Attribute('row_factory', sqlite3.Row)) + """ :type: (objects.Provider) -> sqlite3.Connection """ + + consuming_function = Callable(consuming_function, + Injection('db', database)) + """ :type: (objects.Provider) -> consuming_function """ + + +# Some calls. +arg1, db1 = Catalog.consuming_function(1) +arg2, db2 = Catalog.consuming_function(2) +arg3, db3 = Catalog.consuming_function(3) + +# Some asserts. +assert db1 is db2 is db3 +assert arg1 == 1 +assert arg2 == 2 +assert arg3 == 3 +``` diff --git a/examples/callable_provider.py b/examples/callable_provider.py new file mode 100644 index 00000000..3e037c81 --- /dev/null +++ b/examples/callable_provider.py @@ -0,0 +1,42 @@ +""" +Callable provider examples. +""" + +from objects import AbstractCatalog +from objects.providers import Singleton, Callable +from objects.injections import Injection, InitArg, Attribute + +import sqlite3 + + +# Some example function. +def consuming_function(arg, db): + return arg, db + + +# Catalog of objects providers. +class Catalog(AbstractCatalog): + """ + Objects catalog. + """ + + database = Singleton(sqlite3.Connection, + InitArg('database', ':memory:'), + Attribute('row_factory', sqlite3.Row)) + """ :type: (objects.Provider) -> sqlite3.Connection """ + + consuming_function = Callable(consuming_function, + Injection('db', database)) + """ :type: (objects.Provider) -> consuming_function """ + + +# Some calls. +arg1, db1 = Catalog.consuming_function(1) +arg2, db2 = Catalog.consuming_function(2) +arg3, db3 = Catalog.consuming_function(3) + +# Some asserts. +assert db1 is db2 is db3 +assert arg1 == 1 +assert arg2 == 2 +assert arg3 == 3 diff --git a/objects/providers.py b/objects/providers.py index 2d0fbdd1..9b0a63dc 100644 --- a/objects/providers.py +++ b/objects/providers.py @@ -3,7 +3,7 @@ Standard providers. """ from collections import Iterable -from .injections import InitArg, Attribute, Method +from .injections import Injection, InitArg, Attribute, Method class Provider(object): @@ -247,3 +247,31 @@ class Value(_StaticProvider): """ Value provider provides value. """ + + +class Callable(Provider): + """ + Callable providers will provides callable calls with some predefined + dependencies injections. + """ + + def __init__(self, calls, *injections): + """ + Initializer. + """ + self.calls = calls + self.injections = fetch_injections(injections, Injection) + super(Callable, self).__init__() + + def __call__(self, *args, **kwargs): + """ + Returns provided instance. + """ + if self.__overridden_by__: + return self.__overridden_by__[-1].__call__(*args, **kwargs) + + injections = prepare_injections(self.injections) + injections = dict(injections) + injections.update(kwargs) + + return self.calls(*args, **injections)