diff --git a/examples/miniapps/factory_patterns/chained_factories.py b/examples/miniapps/factory_patterns/chained_factories.py new file mode 100644 index 00000000..993d1fa2 --- /dev/null +++ b/examples/miniapps/factory_patterns/chained_factories.py @@ -0,0 +1,59 @@ +"""`Chained Factories` pattern.""" + +from dependency_injector import providers + +from data import ( + id_generator, + session, + SqlAlchemyDatabaseService, + TokensService, + Token, + UsersService, + User, +) + + +# "Chained Factories" pattern + +database = providers.Factory(SqlAlchemyDatabaseService, session=session) + +tokens = providers.Factory( + TokensService, + id_generator=id_generator, + database=providers.Factory(database, base_class=Token), +) + +users = providers.Factory( + UsersService, + id_generator=id_generator, + database=providers.Factory(database, base_class=User), +) + +tokens_service = tokens() +assert tokens_service.database.base_class is Token + +users_service = users() +assert users_service.database.base_class is User + +# Explanation & some more examples + +# 1. Keyword arguments of upper level factory are added to lower level factory +chained_dict_factory = providers.Factory( + providers.Factory(dict, arg1=1), + arg2=2, +) +print(chained_dict_factory()) # prints: {'arg1': 1, 'arg2': 2} + +# 2. Keyword arguments of upper level factory have priority +chained_dict_factory = providers.Factory( + providers.Factory(dict, arg1=1), + arg1=2, +) +print(chained_dict_factory()) # prints: {'arg1': 2} + +# 3. Keyword arguments provided from context have most priority +chained_dict_factory = providers.Factory( + providers.Factory(dict, arg1=1), + arg1=2, +) +print(chained_dict_factory(arg1=3)) # prints: {'arg1': 3} diff --git a/examples/miniapps/factory_patterns/data.py b/examples/miniapps/factory_patterns/data.py new file mode 100644 index 00000000..80fdd20f --- /dev/null +++ b/examples/miniapps/factory_patterns/data.py @@ -0,0 +1,41 @@ +"""Sample data classes.""" + + +class SqlAlchemyDatabaseService: + """Database service of an entity.""" + + def __init__(self, session, base_class): + """Initialize object.""" + self.session = session + self.base_class = base_class + + +class TokensService: + """Tokens service.""" + + def __init__(self, id_generator, database): + """Initialize object.""" + self.id_generator = id_generator + self.database = database + + +class Token: + """Token entity.""" + + +class UsersService: + """Users service.""" + + def __init__(self, id_generator, database): + """Initialize object.""" + self.id_generator = id_generator + self.database = database + + +class User: + """User entity.""" + + +# Sample objects +session = object() +id_generator = object() diff --git a/examples/miniapps/factory_patterns/factory_of_factories.py b/examples/miniapps/factory_patterns/factory_of_factories.py new file mode 100644 index 00000000..7a6a5fc1 --- /dev/null +++ b/examples/miniapps/factory_patterns/factory_of_factories.py @@ -0,0 +1,69 @@ +"""`Factory of Factories` pattern.""" + +from dependency_injector import providers + +from data import ( + id_generator, + session, + SqlAlchemyDatabaseService, + TokensService, + Token, + UsersService, + User, +) + + +# "Factory of Factories" pattern + +database_factory = providers.Factory( + providers.Factory, + SqlAlchemyDatabaseService, + session=session, +) + +tokens = providers.Factory( + TokensService, + id_generator=id_generator, + database=database_factory(base_class=Token), +) + +users = providers.Factory( + UsersService, + id_generator=id_generator, + database=database_factory(base_class=User), +) + +tokens_service = tokens() +assert tokens_service.database.base_class is Token + +users_service = users() +assert users_service.database.base_class is User + +# Explanation & some more examples + +# 1. Keyword arguments of upper level factory are added to lower level factory +factory_of_dict_factories = providers.Factory( + providers.Factory, + dict, + arg1=1, +) +dict_factory = factory_of_dict_factories(arg2=2) +print(dict_factory()) # prints: {'arg1': 1, 'arg2': 2} + +# 2. Keyword arguments of upper level factory have priority +factory_of_dict_factories = providers.Factory( + providers.Factory, + dict, + arg1=1, +) +dict_factory = factory_of_dict_factories(arg1=2) +print(dict_factory()) # prints: {'arg1': 2} + +# 3. Keyword arguments provided from context have most priority +factory_of_dict_factories = providers.Factory( + providers.Factory, + dict, + arg1=1, +) +dict_factory = factory_of_dict_factories(arg1=2) +print(dict_factory(arg1=3)) # prints: {'arg1': 3}