def test_load_from_args(self):
        mock = Mock()
        config_source('my')(mock)

        config = DictConfig()
        config.load_from('my', 1, 2, k=3, w=4)

        assert mock.mock_calls == [call(config, 1, 2, k=3, w=4)]
    def test_load_from_noargs(self):
        mock = Mock()
        config_source('my')(mock)

        config = DictConfig()
        config.load_from('my')

        assert mock.mock_calls == [call(config)]
    def test_from_json(self, tmpdir):
        myconfig = tmpdir.join('myconfig.json')
        myconfig.write('{"ONE": 1, "TWO": "hello", "three": 3}')

        config = DictConfig()
        config.load_from('json', str(myconfig))

        # three won't load because it's lowercase.
        assert config == dict(ONE=1, TWO='hello')
    def test_from_pyfile(self, tmpdir):
        myconfig = tmpdir.join('myconfig.py')
        myconfig.write('ONE = 1\nTWO = "hello"\nthree = 3')

        config = DictConfig()
        config.load_from('pyfile', str(myconfig))

        # three won't load because it's lowercase.
        assert config == dict(ONE=1, TWO='hello')
    def test_from_object(self):
        class Cfg:
            PARAM1 = 1
            PARAM_2 = '2'
            lower_param = dict()  # lowercase won't load.

        config = DictConfig()
        config.load_from('object', Cfg)

        assert config == dict(PARAM1=1, PARAM_2='2')
    def test_from_dict(self):
        src = dict(
            PARAM1=1,
            PARAM_2='2',
            lower_param=None  # lowercase won't load.
        )

        config = DictConfig()
        config.load_from('dict', src)

        assert config == dict(PARAM1=1, PARAM_2='2')
    def test_load_from_args_extra(self):
        mock = Mock()
        config_source('my')(mock)

        config = DictConfig(defaults={'my': dict(x='y')})
        config.load_from('my', 1, k=3)

        # It must add extra args from source_args.
        assert mock.mock_calls == [call(config, 1, k=3, x='y')]

        # 'source_args' must stay unchanged.
        assert config._defaults == {'my': dict(x='y')}
    def test_from_json_missing_silent(self, tmpdir):
        filename = str(tmpdir.join('myconfig.json'))
        config = DictConfig()
        res = config.load_from('json', filename, silent=True)

        assert res is False
        assert config == dict()
    def test_from_json_prefix(self, tmpdir):
        myconfig = tmpdir.join('myconfig.cfg')
        myconfig.write('{"ONE": 1, "TWO": "hello", "three": 3}')

        config = DictConfig()
        filename = 'json:/%s' % myconfig
        res = config.load_from('json', filename)

        assert res is True
        # three won't load because it's lowercase.
        assert config == dict(ONE=1, TWO='hello')
def create_config(source, env_prefix=None, defaults=None):
    """Create app configuration.

    Configurations precedence:

    * ``defaults``.
    * S3 configuration file.
    * ``source``.
    * Environment variables ``<env_prefix>_*``.

    Add the following fields to local config to load S3 config::

        S3CONFIG_BUCKET_NAME = 'mybucket'
        S3CONFIG_FILENAME = 'path/in/bucket/cfg.py'
        S3CONFIG_CACHE_FILENAME = '/path/to/cache/file.py'
        S3CONFIG_UPDATE_CACHE = False

        # Skip S3 config loading.
        # S3CONFIG_SKIP = True

        # AWS credentials.
        #
        # NOTE: you may use standard env vars to specify credentials:
        # AWS_PROFILE, AWS_REGION, AWS_DEFAULT_REGION, AWS_ACCESS_KEY,
        # AWS_SECRET_KEY.
        #
        # S3CONFIG_PROFILE = ''
        # S3CONFIG_ACCESS_KEY = ''
        # S3CONFIG_SECRET_KEY = ''

    Args:
        source: Single configuration source or list of them (filenames,
            dictionaries or objects or classes).
        env_prefix: Environment variables prefix.
        defaults: Single configuration source or list of them with
            default configurations. Loaded before the ``source``.

    Returns:
        :class:`DictConfig` instance with loaded configuration.

    Notes:
        It loads only UPPER CASE fields (nested fields may be lower case).

    See Also:
        https://docs.aws.amazon.com/cli/latest/reference/s3/
    """
    env_config = DictConfig()
    if env_prefix:
        env_config.load_from('env', prefix=env_prefix)

    configs = [load_config(defaults), load_config(source), env_config]

    s3_config = {}
    for config in configs:
        s3 = get_namespace(config, 'S3CONFIG_', lowercase=True)
        if s3:
            s3_config.update(s3)

    # If S3 config exists then load it and put after default.
    if s3_config and not s3_config.get('skip', False):
        s3config = DictConfig(defaults={'s3': s3_config})
        s3config.load_from('s3')
        configs.insert(1, s3config)

    # Merge loaded configs.
    config = {}
    for cfg in configs:
        config.update(cfg)

    return config
    def test_from_env(self):
        config = DictConfig()
        config.load_from('env', prefix='MYTEST_')

        assert config == dict(ONE='12', TWO='hello')
 def test_load_from_unknown(self):
     config = DictConfig()
     with pytest.raises(ConfigSourceError) as e:
         config.load_from('test_env')
     assert str(e.value) == 'Unknown source: test_env (config type: dict)'
    def test_from_json_missing_nosilent(self, tmpdir):
        filename = str(tmpdir.join('myconfig.json'))
        config = DictConfig()

        with pytest.raises(IOError):
            config.load_from('json', filename)