mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-11-04 01:47:36 +03:00 
			
		
		
		
	Edit Dependency provider docs
This commit is contained in:
		
							parent
							
								
									9e6b52aad4
								
							
						
					
					
						commit
						6fac06fd91
					
				
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 42 KiB  | 
| 
						 | 
					@ -10,7 +10,7 @@ follows `Semantic versioning`_
 | 
				
			||||||
Development version
 | 
					Development version
 | 
				
			||||||
-------------------
 | 
					-------------------
 | 
				
			||||||
- Update documentation and rework examples for: ``Singleton``, ``Callable``, ``Coroutine``,
 | 
					- Update documentation and rework examples for: ``Singleton``, ``Callable``, ``Coroutine``,
 | 
				
			||||||
  ``Object``, ``List``, ``Configuration``, ``Selector`` providers.
 | 
					  ``Object``, ``List``, ``Configuration``, ``Selector``, and ``Dependency`` providers.
 | 
				
			||||||
- Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface.
 | 
					- Fix mypy stub of the ``DeclarativeContainer`` to specify the ``__init__`` interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3.34.0
 | 
					3.34.0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,43 +1,21 @@
 | 
				
			||||||
Dependency providers
 | 
					Dependency provider
 | 
				
			||||||
--------------------
 | 
					-------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: dependency_injector.providers
 | 
					.. currentmodule:: dependency_injector.providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:py:class:`Dependency` provider can be useful for development of
 | 
					:py:class:`Dependency` provider is a placeholder for the dependency of the specified type.
 | 
				
			||||||
self-sufficient libraries / modules / applications that have required external
 | 
					 | 
				
			||||||
dependencies.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
For example, you have created self-sufficient library / module / application,
 | 
					The first argument of the ``Dependency`` provider specifies a type of the dependency. It is
 | 
				
			||||||
that has dependency on *database connection*.
 | 
					called ``instance_of``. ``Dependency`` provider controls the type of the returned object to be an
 | 
				
			||||||
 | 
					instance of the ``instance_of`` type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Second step you want to do is to make this software component to be easy
 | 
					The ``Dependency`` provider must be overridden before usage. It can be overridden by any type of
 | 
				
			||||||
reusable by wide amount of developers and to be easily integrated into many
 | 
					the provider. The only rule is that overriding provider must return an instance of ``instance_of``
 | 
				
			||||||
applications.
 | 
					dependency type.
 | 
				
			||||||
 | 
					 | 
				
			||||||
It may be good idea, to move all external dependencies (like
 | 
					 | 
				
			||||||
*database connection*) to the top level and make them to be injected on your
 | 
					 | 
				
			||||||
software component's initialization. It will make third party developers feel
 | 
					 | 
				
			||||||
themselves free about integration of your component in their applications,
 | 
					 | 
				
			||||||
because they would be able to find right place / right way for doing this
 | 
					 | 
				
			||||||
in their application's architectures.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
At the same time, you can be sure, that your external dependency will be
 | 
					 | 
				
			||||||
satisfied with appropriate instance.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. note::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Class ``UsersService`` is a part of some library. ``UsersService`` has
 | 
					 | 
				
			||||||
    dependency on database connection, which can be satisfied with any
 | 
					 | 
				
			||||||
    DBAPI 2.0 database connection. Being a self-sufficient library,
 | 
					 | 
				
			||||||
    ``UsersService`` doesn't hardcode any kind of database management logic.
 | 
					 | 
				
			||||||
    Instead of this, ``UsersService`` has external dependency, that has to
 | 
					 | 
				
			||||||
    be satisfied by client's code, out of library's scope.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. image:: /images/providers/dependency.png
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. literalinclude:: ../../examples/providers/dependency.py
 | 
					.. literalinclude:: ../../examples/providers/dependency.py
 | 
				
			||||||
   :language: python
 | 
					   :language: python
 | 
				
			||||||
 | 
					   :lines: 3-
 | 
				
			||||||
 | 
					   :emphasize-lines: 26
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. disqus::
 | 
					.. disqus::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,73 +1,50 @@
 | 
				
			||||||
"""`Dependency` providers example."""
 | 
					"""`Dependency` provider example."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sqlite3
 | 
					import abc
 | 
				
			||||||
import contextlib
 | 
					import dataclasses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dependency_injector.providers as providers
 | 
					from dependency_injector import containers, providers, errors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UsersService:
 | 
					class DbAdapter(metaclass=abc.ABCMeta):
 | 
				
			||||||
    """Example class UsersService.
 | 
					    ...
 | 
				
			||||||
 | 
					 | 
				
			||||||
    UsersService has dependency on DBAPI 2.0 database connection.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, database):
 | 
					 | 
				
			||||||
        """Initialize instance.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :param database: Database connection.
 | 
					 | 
				
			||||||
        :type database: sqlite3.dbapi2.Connection
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        self.database = database
 | 
					 | 
				
			||||||
        self.database.row_factory = sqlite3.dbapi2.Row
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def init_database(self):
 | 
					 | 
				
			||||||
        """Initialize database, if it has not been initialized yet."""
 | 
					 | 
				
			||||||
        with contextlib.closing(self.database.cursor()) as cursor:
 | 
					 | 
				
			||||||
            cursor.execute("""
 | 
					 | 
				
			||||||
              CREATE TABLE IF NOT EXISTS users(
 | 
					 | 
				
			||||||
                id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
					 | 
				
			||||||
                name VARCHAR(32)
 | 
					 | 
				
			||||||
              )
 | 
					 | 
				
			||||||
            """)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def create(self, name):
 | 
					 | 
				
			||||||
        """Create user with provided name and return his id."""
 | 
					 | 
				
			||||||
        with contextlib.closing(self.database.cursor()) as cursor:
 | 
					 | 
				
			||||||
            cursor.execute('INSERT INTO users(name) VALUES (?)', (name,))
 | 
					 | 
				
			||||||
            return cursor.lastrowid
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_by_id(self, id):
 | 
					 | 
				
			||||||
        """Return user info by user id."""
 | 
					 | 
				
			||||||
        with contextlib.closing(self.database.cursor()) as cursor:
 | 
					 | 
				
			||||||
            cursor.execute('SELECT id, name FROM users WHERE id=?', (id,))
 | 
					 | 
				
			||||||
            return cursor.fetchone()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Database and UsersService providers:
 | 
					class SqliteDbAdapter(DbAdapter):
 | 
				
			||||||
database = providers.Dependency(instance_of=sqlite3.dbapi2.Connection)
 | 
					    ...
 | 
				
			||||||
users_service_factory = providers.Factory(UsersService,
 | 
					 | 
				
			||||||
                                          database=database)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Out of library's scope.
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# Setting database provider:
 | 
					 | 
				
			||||||
database.provided_by(providers.Singleton(sqlite3.dbapi2.Connection,
 | 
					 | 
				
			||||||
                                         database=':memory:',
 | 
					 | 
				
			||||||
                                         timeout=30,
 | 
					 | 
				
			||||||
                                         detect_types=True,
 | 
					 | 
				
			||||||
                                         isolation_level='EXCLUSIVE'))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Creating UsersService instance:
 | 
					class PostgresDbAdapter(DbAdapter):
 | 
				
			||||||
users_service = users_service_factory()
 | 
					    ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Initializing UsersService database:
 | 
					 | 
				
			||||||
users_service.init_database()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Creating test user and retrieving full information about him:
 | 
					@dataclasses.dataclass
 | 
				
			||||||
test_user_id = users_service.create(name='test_user')
 | 
					class UserService:
 | 
				
			||||||
test_user = users_service.get_by_id(test_user_id)
 | 
					    database: DbAdapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Making some asserts:
 | 
					
 | 
				
			||||||
assert test_user['id'] == 1
 | 
					class Container(containers.DeclarativeContainer):
 | 
				
			||||||
assert test_user['name'] == 'test_user'
 | 
					
 | 
				
			||||||
 | 
					    database = providers.Dependency(instance_of=DbAdapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    user_service = providers.Factory(
 | 
				
			||||||
 | 
					        UserService,
 | 
				
			||||||
 | 
					        database=database,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    container1 = Container(database=providers.Singleton(SqliteDbAdapter))
 | 
				
			||||||
 | 
					    container2 = Container(database=providers.Singleton(PostgresDbAdapter))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert isinstance(container1.user_service().database, SqliteDbAdapter)
 | 
				
			||||||
 | 
					    assert isinstance(container2.user_service().database, PostgresDbAdapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    container3 = Container(database=providers.Singleton(object))
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        container3.user_service()
 | 
				
			||||||
 | 
					    except errors.Error as exception:
 | 
				
			||||||
 | 
					        print(exception)
 | 
				
			||||||
 | 
					        # The output is:
 | 
				
			||||||
 | 
					        # <object object at 0x107ce5c40> is not an
 | 
				
			||||||
 | 
					        # instance of <class '__main__.DbAdapter'>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user