mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2024-11-21 17:16:46 +03:00
Merge branch 'release/4.25.0' into master
This commit is contained in:
commit
6a73b9d3fd
|
@ -7,6 +7,14 @@ that were made in every particular version.
|
|||
From version 0.7.6 *Dependency Injector* framework strictly
|
||||
follows `Semantic versioning`_
|
||||
|
||||
4.25.0
|
||||
------
|
||||
- Add ``application-multiple-containers-runtime-overriding`` example. This example demonstrates
|
||||
how to build application from multiple containers and override one container config from
|
||||
another one in the runtime.
|
||||
See issue: `#207 <https://github.com/ets-labs/python-dependency-injector/issues/207>`_.
|
||||
- Add attributes forwarding for the ``Dependency`` provider.
|
||||
|
||||
4.24.0
|
||||
------
|
||||
- Add docs on ``@containers.copy()`` decorator.
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
Application example (multiple containers, runtime config overriding)
|
||||
====================================================================
|
||||
|
||||
This example demonstrates how to build application from multiple containers
|
||||
and override one container config from another one in the runtime.
|
||||
|
||||
Run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python -m example
|
||||
|
||||
You should see:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
Adapter=[DB Path=[~/test]], queue=[Some storage]
|
|
@ -0,0 +1 @@
|
|||
"""Top-level package."""
|
|
@ -0,0 +1,12 @@
|
|||
"""Main module."""
|
||||
|
||||
from .containers import Application
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
application = Application()
|
||||
config = application.service.config()
|
||||
config.build()
|
||||
|
||||
print(application.repository.site())
|
||||
# Output: Adapter=[DB Path=[~/test]], queue=[Some storage]
|
|
@ -0,0 +1,45 @@
|
|||
"""Containers module."""
|
||||
|
||||
from dependency_injector import containers, providers
|
||||
|
||||
from .services import ConfigService
|
||||
|
||||
|
||||
class Core(containers.DeclarativeContainer):
|
||||
config = providers.Configuration('config')
|
||||
|
||||
|
||||
class Storage(containers.DeclarativeContainer):
|
||||
queue = providers.Singleton(lambda: 'Some storage')
|
||||
|
||||
|
||||
class Adapter(containers.DeclarativeContainer):
|
||||
core = providers.DependenciesContainer(config=providers.Configuration())
|
||||
tinydb = providers.Singleton(
|
||||
lambda db_path: f'DB Path=[{db_path}]',
|
||||
db_path=core.config.default.db_path,
|
||||
)
|
||||
|
||||
|
||||
class Repository(containers.DeclarativeContainer):
|
||||
adapter = providers.DependenciesContainer()
|
||||
storage = providers.DependenciesContainer()
|
||||
site = providers.Singleton(
|
||||
lambda adapter, queue: f'Adapter=[{adapter}], queue=[{queue}]',
|
||||
adapter=adapter.tinydb,
|
||||
queue=storage.queue,
|
||||
)
|
||||
|
||||
|
||||
class Service(containers.DeclarativeContainer):
|
||||
core = providers.DependenciesContainer()
|
||||
config = providers.Singleton(ConfigService, core.config.provider)
|
||||
|
||||
|
||||
class Application(containers.DeclarativeContainer):
|
||||
|
||||
core = providers.Container(Core)
|
||||
storage = providers.Container(Storage)
|
||||
adapter = providers.Container(Adapter, core=core)
|
||||
repository = providers.Container(Repository, adapter=adapter, storage=storage)
|
||||
service = providers.Container(Service, core=core)
|
|
@ -0,0 +1,9 @@
|
|||
"""Services module."""
|
||||
|
||||
|
||||
class ConfigService:
|
||||
def __init__(self, config):
|
||||
self._config = config
|
||||
|
||||
def build(self):
|
||||
self._config.from_dict({'default': {'db_path': '~/test'}})
|
|
@ -1,6 +1,6 @@
|
|||
"""Top-level package."""
|
||||
|
||||
__version__ = '4.24.0'
|
||||
__version__ = '4.25.0'
|
||||
"""Version number.
|
||||
|
||||
:type: str
|
||||
|
|
|
@ -14646,7 +14646,7 @@ static PyObject *__pyx_pf_19dependency_injector_10containers_4override(CYTHON_UN
|
|||
|
||||
/* Python wrapper */
|
||||
static PyObject *__pyx_pw_19dependency_injector_10containers_7copy(PyObject *__pyx_self, PyObject *__pyx_v_container); /*proto*/
|
||||
static char __pyx_doc_19dependency_injector_10containers_6copy[] = ":py:class:`DeclarativeContainer` copying decorator.\n\n This decorator copy all providers from provided container to decorated one.\n If one of the decorated container providers matches to source container\n providers by name, it would be replaced by reference.\n\n :param container: Container that should be copied by decorated container.\n :type container: :py:class:`DeclarativeContainer`\n\n :return: Declarative container's copying decorator.\n :rtype: callable(:py:class:`DeclarativeContainer`)\n ";
|
||||
static char __pyx_doc_19dependency_injector_10containers_6copy[] = ":py:class:`DeclarativeContainer` copying decorator.\n\n This decorator copies all providers from provided container to decorated one.\n If one of the decorated container providers matches to source container\n providers by name, it would be replaced by reference.\n\n :param container: Container that should be copied by decorated container.\n :type container: :py:class:`DeclarativeContainer`\n\n :return: Declarative container's copying decorator.\n :rtype: callable(:py:class:`DeclarativeContainer`)\n ";
|
||||
static PyMethodDef __pyx_mdef_19dependency_injector_10containers_7copy = {"copy", (PyCFunction)__pyx_pw_19dependency_injector_10containers_7copy, METH_O, __pyx_doc_19dependency_injector_10containers_6copy};
|
||||
static PyObject *__pyx_pw_19dependency_injector_10containers_7copy(PyObject *__pyx_self, PyObject *__pyx_v_container) {
|
||||
PyObject *__pyx_r = 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -102,6 +102,7 @@ class Delegate(Provider[Provider]):
|
|||
|
||||
class Dependency(Provider[T]):
|
||||
def __init__(self, instance_of: Type[T] = object, default: Optional[Union[Provider, Any]] = None) -> None: ...
|
||||
def __getattr__(self, name: str) -> Any: ...
|
||||
@property
|
||||
def instance_of(self) -> Type[T]: ...
|
||||
@property
|
||||
|
|
|
@ -680,6 +680,13 @@ cdef class Dependency(Provider):
|
|||
self._check_instance_type(result)
|
||||
return result
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self.__last_overriding:
|
||||
return getattr(self.__last_overriding, name)
|
||||
elif self.__default is not UNDEFINED:
|
||||
return getattr(self.__default, name)
|
||||
return super().__getattr__(name)
|
||||
|
||||
def __str__(self):
|
||||
"""Return string representation of provider.
|
||||
|
||||
|
|
|
@ -496,6 +496,28 @@ class DependencyTests(unittest.TestCase):
|
|||
self.assertIsNot(container.name, copied.name)
|
||||
self.assertIsNot(container.name.parent, copied.name.parent)
|
||||
|
||||
def test_forward_attr_to_default(self):
|
||||
default = providers.Configuration()
|
||||
|
||||
provider = providers.Dependency(default=default)
|
||||
provider.from_dict({'foo': 'bar'})
|
||||
|
||||
self.assertEqual(default(), {'foo': 'bar'})
|
||||
|
||||
def test_forward_attr_to_overriding(self):
|
||||
overriding = providers.Configuration()
|
||||
|
||||
provider = providers.Dependency()
|
||||
provider.override(overriding)
|
||||
provider.from_dict({'foo': 'bar'})
|
||||
|
||||
self.assertEqual(overriding(), {'foo': 'bar'})
|
||||
|
||||
def test_forward_attr_to_none(self):
|
||||
provider = providers.Dependency()
|
||||
with self.assertRaises(AttributeError):
|
||||
provider.from_dict
|
||||
|
||||
def test_deepcopy(self):
|
||||
provider = providers.Dependency(int)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user