diff --git a/docs/providers/configuration.rst b/docs/providers/configuration.rst index 1c36ee21..dfa20539 100644 --- a/docs/providers/configuration.rst +++ b/docs/providers/configuration.rst @@ -96,4 +96,34 @@ where ``examples/providers/configuration/config.local.yml`` is: .. literalinclude:: ../../examples/providers/configuration/config.local.yml :language: ini +Specifying value type +~~~~~~~~~~~~~~~~~~~~~ + +You can specify the type of the injected configuration value explicitly. + +This helps when you read the value from the ini file or the environment variable and need to +convert it into an ``int`` or a ``float``. + +.. literalinclude:: ../../examples/providers/configuration/configuration_type.py + :language: python + :lines: 3- + :emphasize-lines: 17 + +:py:class:`Configuration` provider has next helper methods: + +- ``.as_int()`` +- ``.as_float()`` +- ``.as_(callback, *args, **kwargs)`` + +The last method ``.as_(callback, *args, **kwargs)`` helps to implement a other conversions. + +.. literalinclude:: ../../examples/providers/configuration/configuration_type_custom.py + :language: python + :lines: 3- + :emphasize-lines: 16 + +With the ``.as_(callback, *args, **kwargs)`` you can specify the function that will be called +before the injection. The value from the config will be passed as a first argument. The returned +value will be injected. Parameters ``*args`` and ``**kwargs`` are handled as any other injections. + .. disqus:: diff --git a/docs/providers/provided_instance.rst b/docs/providers/provided_instance.rst index a70d5d5b..381557fe 100644 --- a/docs/providers/provided_instance.rst +++ b/docs/providers/provided_instance.rst @@ -62,3 +62,5 @@ should use the :py:class:`ProvidedInstance` provider. In all other cases you should not use :py:class:`ProvidedInstance`, :py:class:`AttributeGetter`, :py:class:`ItemGetter`, or :py:class:`MethodCaller` providers directly. Use the ``.provided`` attribute of the injected provider instead. + +.. disqus:: diff --git a/examples/miniapps/api_client/main.py b/examples/miniapps/api_client/main.py index d99979d8..ee0272be 100644 --- a/examples/miniapps/api_client/main.py +++ b/examples/miniapps/api_client/main.py @@ -7,7 +7,7 @@ import models # Creating ApiClient and User providers: -api_client = providers.Singleton(api.ApiClient, +api_client = providers.Singleton(api.Converter, host='production.com', api_key='PROD_API_KEY') user_factory = providers.Factory(models.User, @@ -27,7 +27,7 @@ if __name__ == '__main__': # {'id': 2} # Overriding of ApiClient on dev environment: - api_client.override(providers.Singleton(api.ApiClient, + api_client.override(providers.Singleton(api.Converter, host='localhost', api_key='DEV_API_KEY')) diff --git a/examples/miniapps/api_client/tests.py b/examples/miniapps/api_client/tests.py index c304e6b0..0115933d 100644 --- a/examples/miniapps/api_client/tests.py +++ b/examples/miniapps/api_client/tests.py @@ -6,7 +6,7 @@ import main import api # Mock ApiClient for testing: -with main.api_client.override(Mock(api.ApiClient)) as api_client_mock: +with main.api_client.override(Mock(api.Converter)) as api_client_mock: user = main.user_factory('test') user.register() api_client_mock().call.assert_called_with('register', {'id': 'test'}) diff --git a/examples/providers/configuration/configuration_type.py b/examples/providers/configuration/configuration_type.py new file mode 100644 index 00000000..213f9f79 --- /dev/null +++ b/examples/providers/configuration/configuration_type.py @@ -0,0 +1,34 @@ +"""`Configuration` provider type specification example.""" + +import os + +from dependency_injector import providers + + +class ApiClient: + def __init__(self, api_key: str, timeout: int): + self.api_key = api_key + self.timeout = timeout + + +config = providers.Configuration() + +api_client_factory = providers.Factory( + ApiClient, + api_key=config.api.key, + timeout=config.api.timeout.as_int(), +) + + +if __name__ == '__main__': + # Emulate environment variables + os.environ['API_KEY'] = 'secret' + os.environ['API_TIMEOUT'] = '5' + + config.api.key.from_env('API_KEY') + config.api.timeout.from_env('API_TIMEOUT') + + api_client = api_client_factory() + + assert api_client.api_key == 'secret' + assert api_client.timeout == 5 diff --git a/examples/providers/configuration/configuration_type_custom.py b/examples/providers/configuration/configuration_type_custom.py new file mode 100644 index 00000000..9b53dafe --- /dev/null +++ b/examples/providers/configuration/configuration_type_custom.py @@ -0,0 +1,30 @@ +"""`Configuration` provider custom type specification example.""" + +import os +import decimal + +from dependency_injector import providers + + +class Calculator: + def __init__(self, pi: decimal.Decimal): + self.pi = pi + + +config = providers.Configuration() + +calculator_factory = providers.Factory( + Calculator, + pi=config.pi.as_(decimal.Decimal), +) + + +if __name__ == '__main__': + # Emulate environment variables + os.environ['PI'] = '3.1415926535897932384626433832' + + config.pi.from_env('PI') + + calculator = calculator_factory() + + assert calculator.pi == decimal.Decimal('3.1415926535897932384626433832')