Overriding of providersΒΆ

Every provider could be overridden by another provider.

This gives opportunity to make system behaviour more flexible at some point. The main feature is that while your code is using providers, it depends on providers, but not on the objects that providers provide. As a result of this, you can change providing by provider object to a different one, but still compatible one, without chaning your previously written code.

Provider overriding functionality has such interface:

../_images/provider_override.png
  • Provider.override() - takes another provider that will be used instead of current provider. This method could be called several times. In such case, last passed provider would be used as overriding one.
  • Provider.reset_override() - resets all overriding providers. Provider starts to behave itself like usual.
  • Provider.reset_last_overriding() - remove last overriding provider from stack of overriding providers.

Example:

../_images/overriding_simple.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
"""Simple providers overriding example."""

import dependency_injector.providers as providers


class User(object):
    """Example class User."""


# Users factory:
users_factory = providers.Factory(User)

# Creating several User objects:
user1 = users_factory()
user2 = users_factory()

# Making some asserts:
assert user1 is not user2
assert isinstance(user1, User) and isinstance(user2, User)


# Extending User:
class SuperUser(User):
    """Example class SuperUser."""


# Overriding users factory:
users_factory.override(providers.Factory(SuperUser))

# Creating some more User objects using overridden users factory:
user3 = users_factory()
user4 = users_factory()

# Making some asserts:
assert user4 is not user3
assert isinstance(user3, SuperUser) and isinstance(user4, SuperUser)

Example:

../_images/overriding_users_model.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"""Overriding user's model example."""

import dependency_injector.providers as providers


class User(object):
    """Example class User."""

    def __init__(self, id, password):
        """Initializer."""
        self.id = id
        self.password = password
        super(User, self).__init__()


class UsersService(object):
    """Example class UsersService."""

    def __init__(self, user_cls):
        """Initializer."""
        self.user_cls = user_cls
        super(UsersService, self).__init__()

    def get_by_id(self, id):
        """Find user by his id and return user model."""
        return self.user_cls(id=id, password='secret' + str(id))


# Users factory and UsersService provider:
users_service = providers.Factory(UsersService, user_cls=User)

# Getting several users and making some asserts:
user1 = users_service().get_by_id(1)
user2 = users_service().get_by_id(2)

assert isinstance(user1, User)
assert user1.id == 1
assert user1.password == 'secret1'

assert isinstance(user2, User)
assert user2.id == 2
assert user2.password == 'secret2'

assert user1 is not user2

# Extending user model and user service for adding custom attributes without
# making any changes to client's code.


class ExtendedUser(User):
    """Example class ExtendedUser."""

    def __init__(self, id, password, first_name=None, last_name=None,
                 gender=None):
        """Initializer."""
        self.first_name = first_name
        self.last_name = last_name
        self.gender = gender
        super(ExtendedUser, self).__init__(id, password)


class ExtendedUsersService(UsersService):
    """Example class ExtendedUsersService."""

    def get_by_id(self, id):
        """Find user by his id and return user model."""
        user = super(ExtendedUsersService, self).get_by_id(id)
        user.first_name = 'John' + str(id)
        user.last_name = 'Smith' + str(id)
        user.gender = 'male'
        return user


# Overriding users_service provider:
extended_users_service = providers.Factory(ExtendedUsersService,
                                           user_cls=ExtendedUser)
users_service.override(extended_users_service)

# Getting few other users users and making some asserts:
user3 = users_service().get_by_id(3)
user4 = users_service().get_by_id(4)

assert isinstance(user3, ExtendedUser)
assert user3.id == 3
assert user3.password == 'secret3'
assert user3.first_name == 'John3'
assert user3.last_name == 'Smith3'

assert isinstance(user4, ExtendedUser)
assert user4.id == 4
assert user4.password == 'secret4'
assert user4.first_name == 'John4'
assert user4.last_name == 'Smith4'

assert user3 is not user4