diff --git a/src/dependency_injector/providers.c b/src/dependency_injector/providers.c index 3503b1aa..f7cc72a8 100644 --- a/src/dependency_injector/providers.c +++ b/src/dependency_injector/providers.c @@ -34208,7 +34208,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_19ConfigurationOption * * config_content = _resolve_config_env_markers( # <<<<<<<<<<<<<< * config_content, - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), */ __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_resolve_config_env_markers); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 1596, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); @@ -34217,7 +34217,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_19ConfigurationOption * * config_content = _resolve_config_env_markers( * config_content, # <<<<<<<<<<<<<< - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), * ) */ if (unlikely(!__pyx_v_config_content)) { __Pyx_RaiseUnboundLocalError("config_content"); __PYX_ERR(1, 1597, __pyx_L1_error) } @@ -34227,7 +34227,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_19ConfigurationOption * * config_content = _resolve_config_env_markers( # <<<<<<<<<<<<<< * config_content, - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), */ __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1596, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); @@ -34238,20 +34238,49 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_19ConfigurationOption /* "dependency_injector/providers.pyx":1598 * config_content = _resolve_config_env_markers( * config_content, - * envs_required=envs_required, # <<<<<<<<<<<<<< + * envs_required=envs_required or self._is_strict_mode_enabled(), # <<<<<<<<<<<<<< * ) * config = yaml.load(config_content, loader) */ __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 1598, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_envs_required, __pyx_v_envs_required) < 0) __PYX_ERR(1, 1598, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_envs_required); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(1, 1598, __pyx_L1_error) + if (!__pyx_t_3) { + } else { + __Pyx_INCREF(__pyx_v_envs_required); + __pyx_t_10 = __pyx_v_envs_required; + goto __pyx_L34_bool_binop_done; + } + __pyx_t_18 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_is_strict_mode_enabled); if (unlikely(!__pyx_t_18)) __PYX_ERR(1, 1598, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_18); + __pyx_t_19 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_18))) { + __pyx_t_19 = PyMethod_GET_SELF(__pyx_t_18); + if (likely(__pyx_t_19)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_18); + __Pyx_INCREF(__pyx_t_19); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_18, function); + } + } + __pyx_t_17 = (__pyx_t_19) ? __Pyx_PyObject_CallOneArg(__pyx_t_18, __pyx_t_19) : __Pyx_PyObject_CallNoArg(__pyx_t_18); + __Pyx_XDECREF(__pyx_t_19); __pyx_t_19 = 0; + if (unlikely(!__pyx_t_17)) __PYX_ERR(1, 1598, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0; + __Pyx_INCREF(__pyx_t_17); + __pyx_t_10 = __pyx_t_17; + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __pyx_L34_bool_binop_done:; + if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_envs_required, __pyx_t_10) < 0) __PYX_ERR(1, 1598, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; /* "dependency_injector/providers.pyx":1596 * return * * config_content = _resolve_config_env_markers( # <<<<<<<<<<<<<< * config_content, - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), */ __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_1, __pyx_t_4); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 1596, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_10); @@ -34262,7 +34291,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_19ConfigurationOption __pyx_t_10 = 0; /* "dependency_injector/providers.pyx":1600 - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), * ) * config = yaml.load(config_content, loader) # <<<<<<<<<<<<<< * @@ -41546,7 +41575,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_46fro * * config_content = _resolve_config_env_markers( # <<<<<<<<<<<<<< * config_content, - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), */ __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_resolve_config_env_markers); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 2026, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_5); @@ -41555,7 +41584,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_46fro * * config_content = _resolve_config_env_markers( * config_content, # <<<<<<<<<<<<<< - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), * ) */ if (unlikely(!__pyx_v_config_content)) { __Pyx_RaiseUnboundLocalError("config_content"); __PYX_ERR(1, 2027, __pyx_L1_error) } @@ -41565,7 +41594,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_46fro * * config_content = _resolve_config_env_markers( # <<<<<<<<<<<<<< * config_content, - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), */ __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2026, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); @@ -41576,20 +41605,49 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_46fro /* "dependency_injector/providers.pyx":2028 * config_content = _resolve_config_env_markers( * config_content, - * envs_required=envs_required, # <<<<<<<<<<<<<< + * envs_required=envs_required or self._is_strict_mode_enabled(), # <<<<<<<<<<<<<< * ) * config = yaml.load(config_content, loader) */ __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 2028, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); - if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_envs_required, __pyx_v_envs_required) < 0) __PYX_ERR(1, 2028, __pyx_L1_error) + __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_envs_required); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(1, 2028, __pyx_L1_error) + if (!__pyx_t_3) { + } else { + __Pyx_INCREF(__pyx_v_envs_required); + __pyx_t_10 = __pyx_v_envs_required; + goto __pyx_L34_bool_binop_done; + } + __pyx_t_18 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_is_strict_mode_enabled); if (unlikely(!__pyx_t_18)) __PYX_ERR(1, 2028, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_18); + __pyx_t_19 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_18))) { + __pyx_t_19 = PyMethod_GET_SELF(__pyx_t_18); + if (likely(__pyx_t_19)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_18); + __Pyx_INCREF(__pyx_t_19); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_18, function); + } + } + __pyx_t_17 = (__pyx_t_19) ? __Pyx_PyObject_CallOneArg(__pyx_t_18, __pyx_t_19) : __Pyx_PyObject_CallNoArg(__pyx_t_18); + __Pyx_XDECREF(__pyx_t_19); __pyx_t_19 = 0; + if (unlikely(!__pyx_t_17)) __PYX_ERR(1, 2028, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0; + __Pyx_INCREF(__pyx_t_17); + __pyx_t_10 = __pyx_t_17; + __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0; + __pyx_L34_bool_binop_done:; + if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_envs_required, __pyx_t_10) < 0) __PYX_ERR(1, 2028, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; /* "dependency_injector/providers.pyx":2026 * return * * config_content = _resolve_config_env_markers( # <<<<<<<<<<<<<< * config_content, - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), */ __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_1, __pyx_t_4); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 2026, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_10); @@ -41600,7 +41658,7 @@ static PyObject *__pyx_pf_19dependency_injector_9providers_13Configuration_46fro __pyx_t_10 = 0; /* "dependency_injector/providers.pyx":2030 - * envs_required=envs_required, + * envs_required=envs_required or self._is_strict_mode_enabled(), * ) * config = yaml.load(config_content, loader) # <<<<<<<<<<<<<< * diff --git a/src/dependency_injector/providers.pyx b/src/dependency_injector/providers.pyx index 3a5d0db6..548412d4 100644 --- a/src/dependency_injector/providers.pyx +++ b/src/dependency_injector/providers.pyx @@ -1595,7 +1595,7 @@ cdef class ConfigurationOption(Provider): config_content = _resolve_config_env_markers( config_content, - envs_required=envs_required, + envs_required=envs_required or self._is_strict_mode_enabled(), ) config = yaml.load(config_content, loader) @@ -2025,7 +2025,7 @@ cdef class Configuration(Object): config_content = _resolve_config_env_markers( config_content, - envs_required=envs_required, + envs_required=envs_required or self._is_strict_mode_enabled(), ) config = yaml.load(config_content, loader) diff --git a/tests/unit/providers/test_configuration_py2_py3.py b/tests/unit/providers/test_configuration_py2_py3.py index 978a686e..f30cb2ad 100644 --- a/tests/unit/providers/test_configuration_py2_py3.py +++ b/tests/unit/providers/test_configuration_py2_py3.py @@ -905,7 +905,7 @@ class ConfigFromYamlWithEnvInterpolationTests(unittest.TestCase): self.assertEqual(self.config.section1.value2(), 'test-path/path') @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') - def test_missing_envs(self): + def test_missing_envs_not_required(self): del os.environ['CONFIG_TEST_ENV'] del os.environ['CONFIG_TEST_PATH'] @@ -930,6 +930,39 @@ class ConfigFromYamlWithEnvInterpolationTests(unittest.TestCase): self.assertIsNone(self.config.section1.value1()) self.assertEqual(self.config.section1.value2(), '/path') + @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') + def test_missing_envs_required(self): + with open(self.config_file, 'w') as config_file: + config_file.write( + 'section:\n' + ' undefined: ${UNDEFINED}\n' + ) + + with self.assertRaises(ValueError) as context: + self.config.from_yaml(self.config_file, envs_required=True) + + self.assertEqual( + str(context.exception), + 'Missing required environment variable "UNDEFINED"', + ) + + @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') + def test_missing_envs_strict_mode(self): + with open(self.config_file, 'w') as config_file: + config_file.write( + 'section:\n' + ' undefined: ${UNDEFINED}\n' + ) + + self.config.set_strict(True) + with self.assertRaises(ValueError) as context: + self.config.from_yaml(self.config_file) + + self.assertEqual( + str(context.exception), + 'Missing required environment variable "UNDEFINED"', + ) + @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') def test_option_missing_envs(self): del os.environ['CONFIG_TEST_ENV'] @@ -956,6 +989,39 @@ class ConfigFromYamlWithEnvInterpolationTests(unittest.TestCase): self.assertIsNone(self.config.option.section1.value1()) self.assertEqual(self.config.option.section1.value2(), '/path') + @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') + def test_option_missing_envs_required(self): + with open(self.config_file, 'w') as config_file: + config_file.write( + 'section:\n' + ' undefined: ${UNDEFINED}\n' + ) + + with self.assertRaises(ValueError) as context: + self.config.option.from_yaml(self.config_file, envs_required=True) + + self.assertEqual( + str(context.exception), + 'Missing required environment variable "UNDEFINED"', + ) + + @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') + def test_option_missing_envs_strict_mode(self): + with open(self.config_file, 'w') as config_file: + config_file.write( + 'section:\n' + ' undefined: ${UNDEFINED}\n' + ) + + self.config.set_strict(True) + with self.assertRaises(ValueError) as context: + self.config.option.from_yaml(self.config_file) + + self.assertEqual( + str(context.exception), + 'Missing required environment variable "UNDEFINED"', + ) + @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') def test_default_values(self): os.environ['DEFINED'] = 'defined'