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): 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') __slots__ = ('instance', 'factory')
@ -278,25 +284,90 @@ class Singleton(Provider):
def __init__(self, provides, *args, **kwargs): def __init__(self, provides, *args, **kwargs):
"""Initializer.""" """Initializer."""
self.instance = None self.instance = None
"""Read-only reference to singleton's instance.
:type: object
"""
self.factory = Factory(provides, *args, **kwargs) self.factory = Factory(provides, *args, **kwargs)
"""Singleton's factory object.
:type: :py:class:`Factory`
"""
super(Singleton, self).__init__() 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): 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: with GLOBAL_LOCK:
if not self.instance: if not self.instance:
self.instance = self.factory(*args, **kwargs) self.instance = self.factory(*args, **kwargs)
return self.instance 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): class ExternalDependency(Provider):
"""External dependency 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 Singleton providers
------------------- -------------------
``di.Singleton`` provider creates new instance of specified class on first call .. module:: dependency_injector.providers
and returns same instance on every next call.
:py:class:`Singleton` provider creates new instance of specified class on
first call and returns same instance on every next call.
Example: Example:
@ -16,9 +18,9 @@ Example:
Singleton providers and injections Singleton providers and injections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Singleton`` providers use ``di.Factory`` providers for first creation of :py:class:`Singleton` providers use :py:class:`Factory` providers for first
specified class instance, so, all of the rules about injections are the same, creation of specified class instance, so, all of the rules about injections
as for ``di.Factory`` providers. are the same, as for :py:class:`Factory` providers.
.. image:: /images/providers/singleton_internals.png .. image:: /images/providers/singleton_internals.png
:width: 80% :width: 80%
@ -26,29 +28,29 @@ as for ``di.Factory`` providers.
.. note:: .. note::
Due that ``di.Singleton`` provider creates specified class instance only on Due that :py:class:`Singleton` provider creates specified class instance
the first call, all injections are done once, during the first call, also. only on the first call, all injections are done once, during the first
Every next call, while instance has been already created and memorized, no call, also. Every next call, while instance has been already created
injections are done, ``di.Singleton`` provider just returns memorized and memorized, no injections are done, :py:class:`Singleton` provider just
earlier instance. returns memorized earlier instance.
This may cause some problems, for example, in case of trying to bind This may cause some problems, for example, in case of trying to bind
``di.Factory`` provider with ``di.Singleton`` provider (provided by :py:class:`Factory` provider with :py:class:`Singleton` provider (provided
dependent ``di.Factory`` instance will be injected only once, during the by dependent :py:class:`Factory` instance will be injected only once,
first call). Be aware that such behaviour was made with opened eyes and is during the first call). Be aware that such behaviour was made with opened
not a bug. eyes and is not a bug.
By the way, in such case, ``di.Delegate`` provider can be useful. It makes By the way, in such case, :py:class:`Delegate` provider can be useful. It
possible to inject providers *as is*. Please check out full example in makes possible to inject providers *as is*. Please check out full example
*Providers delegation* section. in *Providers delegation* section.
Singleton providers resetting Singleton providers resetting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Created and memorized by ``di.Singleton`` instance can be reset. Reset of Created and memorized by :py:class:`Singleton` instance can be reset. Reset of
``di.Singleton``'s memorized instance is done by clearing reference to it. :py:class:`Singleton`'s memorized instance is done by clearing reference to
Further lifecycle of memorized instance is out of ``di.Singleton`` provider's it. Further lifecycle of memorized instance is out of :py:class:`Singleton`
control. provider's control.
Example: Example:
@ -58,13 +60,13 @@ Example:
Singleton providers delegation Singleton providers delegation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``di.Singleton`` provider could be delegated to any other provider via any :py:class:`Singleton` provider could be delegated to any other provider via
kind of injection. Delegation of ``di.Singleton`` providers is the same as any kind of injection. Delegation of :py:class:`Singleton` providers is the
``di.Factory`` providers delegation, please follow same as :py:class:`Factory` providers delegation, please follow *Factory
*Factory providers delegation* section for example. providers delegation* section for example.
``di.Singleton`` delegate could be created obviously using :py:class:`Singleton` delegate could be created obviously using
``di.Delegate(di.Singleton())`` or by calling ``di.Singleton.delegate()`` ``Delegate(Singleton(...))`` or by calling ``Singleton(...).delegate()``
method. method.
Example: 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): class UserService(object):
@ -8,7 +8,7 @@ class UserService(object):
# Singleton provider creates new instance of specified class on first call and # Singleton provider creates new instance of specified class on first call and
# returns same instance on every next call. # returns same instance on every next call.
users_service_provider = di.Singleton(UserService) users_service_provider = providers.Singleton(UserService)
# Retrieving several UserService objects: # Retrieving several UserService objects:
user_service1 = users_service_provider() 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: # 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_delegate1 = singleton_provider.delegate()
singleton_provider_delegate2 = di.Delegate(singleton_provider) singleton_provider_delegate2 = providers.Delegate(singleton_provider)
# Making some asserts: # Making some asserts:
assert singleton_provider_delegate1() is singleton_provider 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): class UserService(object):
"""Example class UserService.""" """Example class UserService."""
# Users service singleton provider: # Users service singleton provider:
users_service_provider = di.Singleton(UserService) users_service_provider = providers.Singleton(UserService)
# Retrieving several UserService objects: # Retrieving several UserService objects:
user_service1 = users_service_provider() user_service1 = users_service_provider()