From 18ef566aae22ac40946174a6a2ef80f016308d66 Mon Sep 17 00:00:00 2001 From: Roman Mogylatov Date: Thu, 5 Nov 2020 10:16:39 -0500 Subject: [PATCH] Fix issue #319 resulting in configuration.reset_override() not working properly --- src/dependency_injector/providers.c | 83 ++++++++++--------- src/dependency_injector/providers.pyx | 2 +- .../providers/test_configuration_py2_py3.py | 15 ++++ 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/src/dependency_injector/providers.c b/src/dependency_injector/providers.c index d1b02c99..55eb4a77 100644 --- a/src/dependency_injector/providers.c +++ b/src/dependency_injector/providers.c @@ -27926,7 +27926,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set * :rtype: :py:class:`OverridingContext` * """ * keys = selector.split('.') # <<<<<<<<<<<<<< - * original_value = current_value = self.__call__() + * original_value = current_value = deepcopy(self.__call__()) * */ __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_selector, __pyx_n_s_split); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1388, __pyx_L1_error) @@ -27952,7 +27952,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set /* "dependency_injector/providers.pyx":1389 * """ * keys = selector.split('.') - * original_value = current_value = self.__call__() # <<<<<<<<<<<<<< + * original_value = current_value = deepcopy(self.__call__()) # <<<<<<<<<<<<<< * * while len(keys) > 0: */ @@ -27973,14 +27973,17 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1389, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_INCREF(__pyx_t_1); - __pyx_v_original_value = __pyx_t_1; - __Pyx_INCREF(__pyx_t_1); - __pyx_v_current_value = __pyx_t_1; + __pyx_t_2 = __pyx_f_19dependency_injector_9providers_deepcopy(__pyx_t_1, 0, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1389, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_INCREF(__pyx_t_2); + __pyx_v_original_value = __pyx_t_2; + __Pyx_INCREF(__pyx_t_2); + __pyx_v_current_value = __pyx_t_2; + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; /* "dependency_injector/providers.pyx":1391 - * original_value = current_value = self.__call__() + * original_value = current_value = deepcopy(self.__call__()) * * while len(keys) > 0: # <<<<<<<<<<<<<< * key = keys.pop(0) @@ -27998,10 +28001,10 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set * if len(keys) == 0: * current_value[key] = value */ - __pyx_t_1 = __Pyx_PyObject_PopIndex(__pyx_v_keys, __pyx_int_0, 0, 1, Py_ssize_t, PyInt_FromSsize_t); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1392, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_1); - __pyx_t_1 = 0; + __pyx_t_2 = __Pyx_PyObject_PopIndex(__pyx_v_keys, __pyx_int_0, 0, 1, Py_ssize_t, PyInt_FromSsize_t); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1392, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_2); + __pyx_t_2 = 0; /* "dependency_injector/providers.pyx":1393 * while len(keys) > 0: @@ -28048,37 +28051,37 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set * current_value[key] = temp_value * current_value = temp_value */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_current_value, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1396, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_current_value, __pyx_n_s_get); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1396, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1396, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_6 = NULL; __pyx_t_7 = 0; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_2); + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); if (likely(__pyx_t_6)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); __Pyx_INCREF(__pyx_t_6); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); __pyx_t_7 = 1; } } #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_2)) { + if (PyFunction_Check(__pyx_t_1)) { PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_key, __pyx_t_3}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1396, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1396, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } else #endif #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) { + if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) { PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_key, __pyx_t_3}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1396, __pyx_L1_error) + __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1396, __pyx_L1_error) __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_GOTREF(__pyx_t_1); + __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; } else #endif @@ -28094,13 +28097,13 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_3); __pyx_t_3 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1396, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_8, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1396, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_XDECREF_SET(__pyx_v_temp_value, __pyx_t_1); - __pyx_t_1 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_temp_value, __pyx_t_2); + __pyx_t_2 = 0; /* "dependency_injector/providers.pyx":1397 * break @@ -28131,25 +28134,25 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_14set * def override(self, provider): */ __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_override); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1400, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); + __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_override); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1400, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); __pyx_t_8 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_2); + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { + __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1); if (likely(__pyx_t_8)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); __Pyx_INCREF(__pyx_t_8); __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); + __Pyx_DECREF_SET(__pyx_t_1, function); } } - __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_8, __pyx_v_original_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_original_value); + __pyx_t_2 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_8, __pyx_v_original_value) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_original_value); __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1400, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; + if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1400, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_r = __pyx_t_2; + __pyx_t_2 = 0; goto __pyx_L0; /* "dependency_injector/providers.pyx":1376 diff --git a/src/dependency_injector/providers.pyx b/src/dependency_injector/providers.pyx index 782ee3f9..2ef6a590 100644 --- a/src/dependency_injector/providers.pyx +++ b/src/dependency_injector/providers.pyx @@ -1386,7 +1386,7 @@ cdef class Configuration(Object): :rtype: :py:class:`OverridingContext` """ keys = selector.split('.') - original_value = current_value = self.__call__() + original_value = current_value = deepcopy(self.__call__()) while len(keys) > 0: key = keys.pop(0) diff --git a/tests/unit/providers/test_configuration_py2_py3.py b/tests/unit/providers/test_configuration_py2_py3.py index 72ed08f9..5b4c00a3 100644 --- a/tests/unit/providers/test_configuration_py2_py3.py +++ b/tests/unit/providers/test_configuration_py2_py3.py @@ -110,6 +110,21 @@ class ConfigTests(unittest.TestCase): self.assertEqual(abc(), 1) self.assertEqual(abd(), 2) + def test_configuration_option_override_and_reset_override(self): + # Bug: https://github.com/ets-labs/python-dependency-injector/issues/319 + self.config.from_dict({'a': {'b': {'c': 1}}}) + + self.assertEqual(self.config.a.b.c(), 1) + + with self.config.set('a.b.c', 'xxx'): + self.assertEqual(self.config.a.b.c(), 'xxx') + self.assertEqual(self.config.a.b.c(), 1) + + with self.config.a.b.c.override('yyy'): + self.assertEqual(self.config.a.b.c(), 'yyy') + + self.assertEqual(self.config.a.b.c(), 1) + def test_providers_with_already_overridden_value(self): self.config.override({'a': {'b': {'c': 1, 'd': 2}}})