diff --git a/src/dependency_injector/providers.c b/src/dependency_injector/providers.c index d7dea2c3..d7fdf15b 100644 --- a/src/dependency_injector/providers.c +++ b/src/dependency_injector/providers.c @@ -2575,7 +2575,7 @@ static const char __pyx_k_Incompatible_checksums_s_vs_0xd8[] = "Incompatible che static const char __pyx_k_Incompatible_checksums_s_vs_0xf1[] = "Incompatible checksums (%s vs 0xf1f5217 = (__instance_of, __last_overriding, __overridden))"; static const char __pyx_k_Provider_0_could_not_be_overridd[] = "Provider {0} could not be overridden with itself"; static const char __pyx_k_Provider_0_expected_to_get_calla[] = "Provider {0} expected to get callable, got {0}"; -static const char __pyx_k_Provider_0_expected_to_get_corou[] = "Provider {0} expected to get coroutine function, got {0}"; +static const char __pyx_k_Provider_0_expected_to_get_corou[] = "Provider {0} expected to get coroutine function, got {1}"; static const char __pyx_k_Incompatible_checksums_s_vs_0xa7_2[] = "Incompatible checksums (%s vs 0xa73b866 = (__attributes, __attributes_len, __instantiator, __last_overriding, __overridden))"; static PyObject *__pyx_kp_s_0_can_aggregate_only_instances; static PyObject *__pyx_kp_s_0_can_provide_only_1_instances; @@ -16634,7 +16634,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct * * if not asyncio.iscoroutinefunction(provides): # <<<<<<<<<<<<<< * raise Error('Provider {0} expected to get coroutine function, ' - * 'got {0}'.format('.'.join((self.__class__.__module__, + * 'got {1}'.format('.'.join((self.__class__.__module__, */ __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_asyncio); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 905, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); @@ -16693,7 +16693,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct * * if not asyncio.iscoroutinefunction(provides): * raise Error('Provider {0} expected to get coroutine function, ' # <<<<<<<<<<<<<< - * 'got {0}'.format('.'.join((self.__class__.__module__, + * 'got {1}'.format('.'.join((self.__class__.__module__, * self.__class__.__name__)), */ __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_Error); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 906, __pyx_L1_error) @@ -16702,7 +16702,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct /* "dependency_injector/providers.pyx":907 * if not asyncio.iscoroutinefunction(provides): * raise Error('Provider {0} expected to get coroutine function, ' - * 'got {0}'.format('.'.join((self.__class__.__module__, # <<<<<<<<<<<<<< + * 'got {1}'.format('.'.join((self.__class__.__module__, # <<<<<<<<<<<<<< * self.__class__.__name__)), * provides)) */ @@ -16716,7 +16716,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct /* "dependency_injector/providers.pyx":908 * raise Error('Provider {0} expected to get coroutine function, ' - * 'got {0}'.format('.'.join((self.__class__.__module__, + * 'got {1}'.format('.'.join((self.__class__.__module__, * self.__class__.__name__)), # <<<<<<<<<<<<<< * provides)) * @@ -16730,7 +16730,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct /* "dependency_injector/providers.pyx":907 * if not asyncio.iscoroutinefunction(provides): * raise Error('Provider {0} expected to get coroutine function, ' - * 'got {0}'.format('.'.join((self.__class__.__module__, # <<<<<<<<<<<<<< + * 'got {1}'.format('.'.join((self.__class__.__module__, # <<<<<<<<<<<<<< * self.__class__.__name__)), * provides)) */ @@ -16747,7 +16747,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; /* "dependency_injector/providers.pyx":909 - * 'got {0}'.format('.'.join((self.__class__.__module__, + * 'got {1}'.format('.'.join((self.__class__.__module__, * self.__class__.__name__)), * provides)) # <<<<<<<<<<<<<< * @@ -16855,7 +16855,7 @@ static int __pyx_pf_19dependency_injector_9providers_9Coroutine___init__(struct * * if not asyncio.iscoroutinefunction(provides): # <<<<<<<<<<<<<< * raise Error('Provider {0} expected to get coroutine function, ' - * 'got {0}'.format('.'.join((self.__class__.__module__, + * 'got {1}'.format('.'.join((self.__class__.__module__, */ } @@ -18720,7 +18720,7 @@ static int __pyx_pf_19dependency_injector_9providers_17CoroutineDelegate___init_ * if isinstance(coroutine, Coroutine) is False: * raise Error('{0} can wrap only {1} providers'.format( # <<<<<<<<<<<<<< * self.__class__, Callable)) - * super(CoroutineDelegate, self).__init__(callable) + * super(CoroutineDelegate, self).__init__(coroutine) */ __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_Error); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 981, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); @@ -18731,7 +18731,7 @@ static int __pyx_pf_19dependency_injector_9providers_17CoroutineDelegate___init_ * if isinstance(coroutine, Coroutine) is False: * raise Error('{0} can wrap only {1} providers'.format( * self.__class__, Callable)) # <<<<<<<<<<<<<< - * super(CoroutineDelegate, self).__init__(callable) + * super(CoroutineDelegate, self).__init__(coroutine) * */ __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_class); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 982, __pyx_L1_error) @@ -18845,7 +18845,7 @@ static int __pyx_pf_19dependency_injector_9providers_17CoroutineDelegate___init_ /* "dependency_injector/providers.pyx":983 * raise Error('{0} can wrap only {1} providers'.format( * self.__class__, Callable)) - * super(CoroutineDelegate, self).__init__(callable) # <<<<<<<<<<<<<< + * super(CoroutineDelegate, self).__init__(coroutine) # <<<<<<<<<<<<<< * * */ @@ -18863,51 +18863,46 @@ static int __pyx_pf_19dependency_injector_9providers_17CoroutineDelegate___init_ __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_init); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 983, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_10 = __Pyx_GetBuiltinName(__pyx_n_s_callable); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 983, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __pyx_t_5 = NULL; + __pyx_t_10 = NULL; if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_5)) { + __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_10)) { PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_10); __Pyx_INCREF(function); __Pyx_DECREF_SET(__pyx_t_4, function); } } - if (!__pyx_t_5) { - __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_10); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 983, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + if (!__pyx_t_10) { + __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_coroutine); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 983, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); } else { #if CYTHON_FAST_PYCALL if (PyFunction_Check(__pyx_t_4)) { - PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_10}; + PyObject *__pyx_temp[2] = {__pyx_t_10, __pyx_v_coroutine}; __pyx_t_3 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 983, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; } else #endif #if CYTHON_FAST_PYCCALL if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) { - PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_t_10}; + PyObject *__pyx_temp[2] = {__pyx_t_10, __pyx_v_coroutine}; __pyx_t_3 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 983, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0; __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; } else #endif { - __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 983, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __pyx_t_5 = NULL; - __Pyx_GIVEREF(__pyx_t_10); - PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_10); - __pyx_t_10 = 0; - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 983, __pyx_L1_error) + __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 983, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_GIVEREF(__pyx_t_10); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_10); __pyx_t_10 = NULL; + __Pyx_INCREF(__pyx_v_coroutine); + __Pyx_GIVEREF(__pyx_v_coroutine); + PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_coroutine); + __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 983, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; } } __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; diff --git a/src/dependency_injector/providers.pyx b/src/dependency_injector/providers.pyx index 4a956f68..b2fe5634 100644 --- a/src/dependency_injector/providers.pyx +++ b/src/dependency_injector/providers.pyx @@ -904,7 +904,7 @@ cdef class Coroutine(Callable): if not asyncio.iscoroutinefunction(provides): raise Error('Provider {0} expected to get coroutine function, ' - 'got {0}'.format('.'.join((self.__class__.__module__, + 'got {1}'.format('.'.join((self.__class__.__module__, self.__class__.__name__)), provides)) @@ -980,7 +980,7 @@ cdef class CoroutineDelegate(Delegate): if isinstance(coroutine, Coroutine) is False: raise Error('{0} can wrap only {1} providers'.format( self.__class__, Callable)) - super(CoroutineDelegate, self).__init__(callable) + super(CoroutineDelegate, self).__init__(coroutine) cdef class Configuration(Object): diff --git a/tests/unit/providers/test_coroutines.py b/tests/unit/providers/test_coroutines.py new file mode 100644 index 00000000..6702171d --- /dev/null +++ b/tests/unit/providers/test_coroutines.py @@ -0,0 +1,291 @@ +"""Dependency injector coroutine providers unit tests.""" + +try: + import asyncio +except ImportError: + asyncio = None + +import unittest2 as unittest + +from dependency_injector import ( + providers, + errors, +) + + +if asyncio: + @asyncio.coroutine + def _example(arg1, arg2, arg3, arg4): + future = asyncio.Future() + future.set_result(None) + yield from future + return arg1, arg2, arg3, arg4 + + def _run(coro): + loop = asyncio.get_event_loop() + return loop.run_until_complete(coro) +else: + _example = None + + +class CoroutineTests(unittest.TestCase): + + if asyncio: + def test_init_with_coroutine(self): + self.assertTrue(providers.Coroutine(_example)) + + def test_init_with_not_coroutine(self): + self.assertRaises(errors.Error, providers.Coroutine, lambda: None) + + def test_call_with_positional_args(self): + provider = providers.Coroutine(_example, 1, 2, 3, 4) + self.assertTupleEqual(_run(provider()), (1, 2, 3, 4)) + + def test_call_with_keyword_args(self): + provider = providers.Coroutine(_example, + arg1=1, arg2=2, arg3=3, arg4=4) + self.assertTupleEqual(_run(provider()), (1, 2, 3, 4)) + + def test_call_with_positional_and_keyword_args(self): + provider = providers.Coroutine(_example, + 1, 2, + arg3=3, arg4=4) + self.assertTupleEqual(_run(provider()), (1, 2, 3, 4)) + + def test_call_with_context_args(self): + provider = providers.Coroutine(_example, 1, 2) + self.assertTupleEqual(_run(provider(3, 4)), (1, 2, 3, 4)) + + def test_call_with_context_kwargs(self): + provider = providers.Coroutine(_example, arg1=1) + self.assertTupleEqual( + _run(provider(arg2=2, arg3=3, arg4=4)), + (1, 2, 3, 4), + ) + + def test_call_with_context_args_and_kwargs(self): + provider = providers.Coroutine(_example, 1) + self.assertTupleEqual( + _run(provider(2, arg3=3, arg4=4)), + (1, 2, 3, 4), + ) + + def test_fluent_interface(self): + provider = providers.Coroutine(_example) \ + .add_args(1, 2) \ + .add_kwargs(arg3=3, arg4=4) + + self.assertTupleEqual(_run(provider()), (1, 2, 3, 4)) + + def test_set_args(self): + provider = providers.Coroutine(_example) \ + .add_args(1, 2) \ + .set_args(3, 4) + self.assertEqual(provider.args, tuple([3, 4])) + + def test_set_kwargs(self): + provider = providers.Coroutine(_example) \ + .add_kwargs(init_arg3=3, init_arg4=4) \ + .set_kwargs(init_arg3=4, init_arg4=5) + self.assertEqual(provider.kwargs, dict(init_arg3=4, init_arg4=5)) + + def test_clear_args(self): + provider = providers.Coroutine(_example) \ + .add_args(1, 2) \ + .clear_args() + self.assertEqual(provider.args, tuple()) + + def test_clear_kwargs(self): + provider = providers.Coroutine(_example) \ + .add_kwargs(init_arg3=3, init_arg4=4) \ + .clear_kwargs() + self.assertEqual(provider.kwargs, dict()) + + def test_call_overridden(self): + provider = providers.Coroutine(_example) + + provider.override(providers.Object((4, 3, 2, 1))) + provider.override(providers.Object((1, 2, 3, 4))) + + self.assertTupleEqual(provider(), (1, 2, 3, 4)) + + def test_deepcopy(self): + provider = providers.Coroutine(_example) + + provider_copy = providers.deepcopy(provider) + + self.assertIsNot(provider, provider_copy) + self.assertIs(provider.provides, provider_copy.provides) + self.assertIsInstance(provider, providers.Coroutine) + + def test_deepcopy_from_memo(self): + provider = providers.Coroutine(_example) + provider_copy_memo = providers.Coroutine(_example) + + provider_copy = providers.deepcopy( + provider, memo={id(provider): provider_copy_memo}) + + self.assertIs(provider_copy, provider_copy_memo) + + def test_deepcopy_args(self): + provider = providers.Coroutine(_example) + dependent_provider1 = providers.Callable(list) + dependent_provider2 = providers.Callable(dict) + + provider.add_args(dependent_provider1, dependent_provider2) + + provider_copy = providers.deepcopy(provider) + dependent_provider_copy1 = provider_copy.args[0] + dependent_provider_copy2 = provider_copy.args[1] + + self.assertNotEqual(provider.args, provider_copy.args) + + self.assertIs(dependent_provider1.provides, + dependent_provider_copy1.provides) + self.assertIsNot(dependent_provider1, dependent_provider_copy1) + + self.assertIs(dependent_provider2.provides, + dependent_provider_copy2.provides) + self.assertIsNot(dependent_provider2, dependent_provider_copy2) + + def test_deepcopy_kwargs(self): + provider = providers.Coroutine(_example) + dependent_provider1 = providers.Callable(list) + dependent_provider2 = providers.Callable(dict) + + provider.add_kwargs(a1=dependent_provider1, a2=dependent_provider2) + + provider_copy = providers.deepcopy(provider) + dependent_provider_copy1 = provider_copy.kwargs['a1'] + dependent_provider_copy2 = provider_copy.kwargs['a2'] + + self.assertNotEqual(provider.kwargs, provider_copy.kwargs) + + self.assertIs(dependent_provider1.provides, + dependent_provider_copy1.provides) + self.assertIsNot(dependent_provider1, dependent_provider_copy1) + + self.assertIs(dependent_provider2.provides, + dependent_provider_copy2.provides) + self.assertIsNot(dependent_provider2, dependent_provider_copy2) + + def test_deepcopy_overridden(self): + provider = providers.Coroutine(_example) + object_provider = providers.Object(object()) + + provider.override(object_provider) + + provider_copy = providers.deepcopy(provider) + object_provider_copy = provider_copy.overridden[0] + + self.assertIsNot(provider, provider_copy) + self.assertIs(provider.provides, provider_copy.provides) + self.assertIsInstance(provider, providers.Callable) + + self.assertIsNot(object_provider, object_provider_copy) + self.assertIsInstance(object_provider_copy, providers.Object) + + def test_repr(self): + provider = providers.Coroutine(_example) + + self.assertEqual(repr(provider), + ''.format( + repr(_example), + hex(id(provider)))) + + +class DelegatedCoroutineTests(unittest.TestCase): + + if asyncio: + def test_inheritance(self): + self.assertIsInstance(providers.DelegatedCoroutine(_example), + providers.Coroutine) + + def test_is_provider(self): + self.assertTrue( + providers.is_provider(providers.DelegatedCoroutine(_example))) + + def test_is_delegated_provider(self): + provider = providers.DelegatedCoroutine(_example) + self.assertTrue(providers.is_delegated(provider)) + + def test_repr(self): + provider = providers.DelegatedCoroutine(_example) + + self.assertEqual(repr(provider), + ''.format( + repr(_example), + hex(id(provider)))) + + +class AbstractCoroutineTests(unittest.TestCase): + + if asyncio: + def test_inheritance(self): + self.assertIsInstance(providers.AbstractCoroutine(_example), + providers.Coroutine) + + def test_call_overridden_by_coroutine(self): + @asyncio.coroutine + def _abstract_example(): + raise RuntimeError('Should not be raised') + + provider = providers.AbstractCoroutine(_abstract_example) + provider.override(providers.Coroutine(_example)) + + self.assertTrue(_run(provider(1, 2, 3, 4)), (1, 2, 3, 4)) + + def test_call_overridden_by_delegated_coroutine(self): + @asyncio.coroutine + def _abstract_example(): + raise RuntimeError('Should not be raised') + + provider = providers.AbstractCoroutine(_abstract_example) + provider.override(providers.DelegatedCoroutine(_example)) + + self.assertTrue(_run(provider(1, 2, 3, 4)), (1, 2, 3, 4)) + + def test_call_not_overridden(self): + provider = providers.AbstractCoroutine(_example) + + with self.assertRaises(errors.Error): + provider(1, 2, 3, 4) + + def test_override_by_not_coroutine(self): + provider = providers.AbstractCoroutine(_example) + + with self.assertRaises(errors.Error): + provider.override(providers.Factory(object)) + + def test_provide_not_implemented(self): + provider = providers.AbstractCoroutine(_example) + + with self.assertRaises(NotImplementedError): + provider._provide((1, 2, 3, 4), dict()) + + def test_repr(self): + provider = providers.AbstractCoroutine(_example) + + self.assertEqual(repr(provider), + ''.format( + repr(_example), + hex(id(provider)))) + + +class CoroutineDelegateTests(unittest.TestCase): + + if asyncio: + def setUp(self): + self.delegated = providers.Coroutine(_example) + self.delegate = providers.CoroutineDelegate(self.delegated) + + def test_is_delegate(self): + self.assertIsInstance(self.delegate, providers.Delegate) + + def test_init_with_not_callable(self): + self.assertRaises(errors.Error, + providers.CoroutineDelegate, + providers.Object(object()))