Update singleton provider docs, including API, and examples

This commit is contained in:
Roman Mogilatov 2015-11-23 14:43:11 +02:00
parent fb6deaec96
commit 61e6f2db60
7 changed files with 122 additions and 49 deletions

View File

@ -268,9 +268,15 @@ class Factory(Provider):
class Singleton(Provider):
"""Singleton provider.
""":py:class:`Singleton` provider returns same instance on every call.
Singleton provider will create instance once and return it on every call.
:py:class:`Singleton` provider creates instance once and return it on every
call. :py:class:`Singleton` uses :py:class:`Factory` for creation of
instance, so, please follow :py:class:`Factory` documentation to go inside
with injections syntax.
:py:class:`Singleton` is thread-safe and could be used in multithreading
environment without any negative impact.
"""
__slots__ = ('instance', 'factory')
@ -278,25 +284,90 @@ class Singleton(Provider):
def __init__(self, provides, *args, **kwargs):
"""Initializer."""
self.instance = None
"""Read-only reference to singleton's instance.
:type: object
"""
self.factory = Factory(provides, *args, **kwargs)
"""Singleton's factory object.
:type: :py:class:`Factory`
"""
super(Singleton, self).__init__()
@property
def provides(self):
"""Class or other callable that provides object for creation.
:type: type | callable
"""
return self.factory.provides
@property
def args(self):
"""Tuple of positional argument injections.
:type: tuple[:py:class:`dependency_injector.injections.Arg`]
"""
return self.factory.args
@property
def kwargs(self):
"""Tuple of keyword argument injections.
:type: tuple[:py:class:`dependency_injector.injections.KwArg`]
"""
return self.factory.kwargs
@property
def attributes(self):
"""Tuple of attribute injections.
:type: tuple[:py:class:`dependency_injector.injections.Attribute`]
"""
return self.factory.attributes
@property
def methods(self):
"""Tuple of method injections.
:type: tuple[:py:class:`dependency_injector.injections.Method`]
"""
return self.factory.methods
@property
def injections(self):
"""Read-only tuple of all injections.
:rtype: tuple[:py:class:`dependency_injector.injections.Injection`]
"""
return self.factory.injections
def reset(self):
"""Reset cached instance, if any.
:rtype: None
"""
self.instance = None
def _provide(self, *args, **kwargs):
"""Return provided instance."""
"""Return provided instance.
:param args: tuple of context positional arguments
:type args: tuple[object]
:param kwargs: dictionary of context keyword arguments
:type kwargs: dict[str, object]
:rtype: object
"""
with GLOBAL_LOCK:
if not self.instance:
self.instance = self.factory(*args, **kwargs)
return self.instance
def reset(self):
"""Reset instance."""
self.instance = None
@property
def injections(self):
"""Return tuple of all injections."""
return self.factory.injections
class ExternalDependency(Provider):
"""External dependency provider.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,8 +1,10 @@
Singleton providers
-------------------
``di.Singleton`` provider creates new instance of specified class on first call
and returns same instance on every next call.
.. module:: dependency_injector.providers
:py:class:`Singleton` provider creates new instance of specified class on
first call and returns same instance on every next call.
Example:
@ -16,9 +18,9 @@ Example:
Singleton providers and injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Singleton`` providers use ``di.Factory`` providers for first creation of
specified class instance, so, all of the rules about injections are the same,
as for ``di.Factory`` providers.
:py:class:`Singleton` providers use :py:class:`Factory` providers for first
creation of specified class instance, so, all of the rules about injections
are the same, as for :py:class:`Factory` providers.
.. image:: /images/providers/singleton_internals.png
:width: 80%
@ -26,29 +28,29 @@ as for ``di.Factory`` providers.
.. note::
Due that ``di.Singleton`` provider creates specified class instance only on
the first call, all injections are done once, during the first call, also.
Every next call, while instance has been already created and memorized, no
injections are done, ``di.Singleton`` provider just returns memorized
earlier instance.
Due that :py:class:`Singleton` provider creates specified class instance
only on the first call, all injections are done once, during the first
call, also. Every next call, while instance has been already created
and memorized, no injections are done, :py:class:`Singleton` provider just
returns memorized earlier instance.
This may cause some problems, for example, in case of trying to bind
``di.Factory`` provider with ``di.Singleton`` provider (provided by
dependent ``di.Factory`` instance will be injected only once, during the
first call). Be aware that such behaviour was made with opened eyes and is
not a bug.
:py:class:`Factory` provider with :py:class:`Singleton` provider (provided
by dependent :py:class:`Factory` instance will be injected only once,
during the first call). Be aware that such behaviour was made with opened
eyes and is not a bug.
By the way, in such case, ``di.Delegate`` provider can be useful. It makes
possible to inject providers *as is*. Please check out full example in
*Providers delegation* section.
By the way, in such case, :py:class:`Delegate` provider can be useful. It
makes possible to inject providers *as is*. Please check out full example
in *Providers delegation* section.
Singleton providers resetting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Created and memorized by ``di.Singleton`` instance can be reset. Reset of
``di.Singleton``'s memorized instance is done by clearing reference to it.
Further lifecycle of memorized instance is out of ``di.Singleton`` provider's
control.
Created and memorized by :py:class:`Singleton` instance can be reset. Reset of
:py:class:`Singleton`'s memorized instance is done by clearing reference to
it. Further lifecycle of memorized instance is out of :py:class:`Singleton`
provider's control.
Example:
@ -58,13 +60,13 @@ Example:
Singleton providers delegation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Singleton`` provider could be delegated to any other provider via any
kind of injection. Delegation of ``di.Singleton`` providers is the same as
``di.Factory`` providers delegation, please follow
*Factory providers delegation* section for example.
:py:class:`Singleton` provider could be delegated to any other provider via
any kind of injection. Delegation of :py:class:`Singleton` providers is the
same as :py:class:`Factory` providers delegation, please follow *Factory
providers delegation* section for example.
``di.Singleton`` delegate could be created obviously using
``di.Delegate(di.Singleton())`` or by calling ``di.Singleton.delegate()``
:py:class:`Singleton` delegate could be created obviously using
``Delegate(Singleton(...))`` or by calling ``Singleton(...).delegate()``
method.
Example:

View File

@ -1,6 +1,6 @@
"""`di.Singleton` providers example."""
"""`Singleton` providers example."""
import dependency_injector as di
from dependency_injector import providers
class UserService(object):
@ -8,7 +8,7 @@ class UserService(object):
# Singleton provider creates new instance of specified class on first call and
# returns same instance on every next call.
users_service_provider = di.Singleton(UserService)
users_service_provider = providers.Singleton(UserService)
# Retrieving several UserService objects:
user_service1 = users_service_provider()

View File

@ -1,12 +1,12 @@
"""`di.Singleton` providers delegation example."""
"""`Singleton` providers delegation example."""
import dependency_injector as di
from dependency_injector import providers
# Some singleton provider and few delegates of it:
singleton_provider = di.Singleton(object)
singleton_provider = providers.Singleton(object)
singleton_provider_delegate1 = singleton_provider.delegate()
singleton_provider_delegate2 = di.Delegate(singleton_provider)
singleton_provider_delegate2 = providers.Delegate(singleton_provider)
# Making some asserts:
assert singleton_provider_delegate1() is singleton_provider

View File

@ -1,13 +1,13 @@
"""`di.Singleton` providers resetting example."""
"""`Singleton` providers resetting example."""
import dependency_injector as di
from dependency_injector import providers
class UserService(object):
"""Example class UserService."""
# Users service singleton provider:
users_service_provider = di.Singleton(UserService)
users_service_provider = providers.Singleton(UserService)
# Retrieving several UserService objects:
user_service1 = users_service_provider()