Пример #1
0
def test_setattr_list_with_dict():
    l = [{"b": True, "c": {"d": "thename"}}, "somestring", True]
    cfg = Config()

    # When we assign a list to the key
    # it remains an instance of list, or
    # whatever sequence type it was.
    cfg.a = l
    assert isinstance(cfg.a, list)

    # Internally though any Mapping objects
    # inside that list, no matter how nested,
    # got transformed into the Config objects.
    assert cfg.a == [
        Config({
            "b": True,
            "c": {
                "d": "thename"
            }
        }),
        "somestring",
        True,
    ]

    # And, again, we get all the nice accessibility
    # shenenigans as a result of such transformation.
    assert cfg.a[0].c.d == "thename"
Пример #2
0
def test_setattr_dict():
    d = {"b": True, "c": {"d": "thename"}}
    cfg = Config()

    # Assign dict to the key. It should atuomatically
    # get transformed into the Config object.
    cfg.a = d
    assert dict(cfg.a) == d
    assert cfg.a == Config(d)

    # Notice how the dict got transformed into a Config
    # during assignment so that now we have all the "nice"
    # accessibility features of Config.
    assert cfg.a.c.d == "thename"
Пример #3
0
def test_setitem():
    cfg = Config(NESTED, MERGABLE)
    cfg["a1"]["b1"]["c1"] = 6
    assert cfg["a1"]["b1"]["c1"] == 6
    assert cfg.a1.b1.c1 == 6

    cfg = Config()
    cfg["f1"] = False
    assert cfg["f1"] is False

    cfg["f2"]["g3"]["h3"] = 123
    assert cfg["f2.g3.h3"] == 123

    cfg["u1.u4.u6"] = True
    assert cfg["u1"]["u4"]["u6"] is True
Пример #4
0
def test_nested_merge():
    cfg = Config(NESTED, MERGABLE)
    # "val" has replaced 3 as value for a1.b1.c3
    assert cfg.a1.b1.c3 == "val"
    # other values are still intact
    assert cfg.a1.b2.c3 == 1.1
    assert cfg.a1.b1.c1 == 1
Пример #5
0
def test_lower():
    config = Config()

    config.merge({"SOME_KeY": "VALuE"})
    assert config.SOME_KeY == "VALuE"
    with pytest.raises(AssertionError):
        assert config.some_key == "VALuE"

    config.clear()
    config.merge({"SOME_KeY": "VALuE"})
    config = config.lower()

    assert config.some_key == "VALuE"
    with pytest.raises(AssertionError):
        assert config.SOME_KeY == "VALuE"
Пример #6
0
def test_features():
    from ilexconf import Config
    config = Config()

    config.a.b.c = True

    assert (
        config.a.b.c == True
    )
    assert (
        config["a"]["b"]["c"] == True
    )
    assert (
        config["a.b.c"] == True
    )
    assert (
        config["a.b"].c == True
    )
    assert (
        config.a["b.c"] == True
    )
    assert (
        config.a["b"].c == True
    )

    if True:
        config.a.b.c = [
            "my_string",
            {"d": "nested_value"}
        ]

    assert (
        config.a.b.c[0] == "my_string"
    )
    assert (
        config.a.b.c[1] == Config({"d": "nested_value"})
    )
    assert (
        dict(config.a.b.c[1]) == {"d": "nested_value"}
    )
Пример #7
0
def test_nested_access():
    cfg = Config(NESTED)
    # Plain access
    assert cfg["a1"]["b1"]["c1"] == 1
    assert cfg["a1.b1.c1"] == 1
    assert cfg.a1.b1.c1 == 1
    # Mixed access
    assert cfg["a1"].b1.C2 == 2
    assert cfg.a1["b1"].c3 == 3
    assert cfg.a1.b2["c3"] == 1.1
    # Direct access
    assert cfg.d1 is False
    assert cfg["d1"] is False
Пример #8
0
def test_upper():
    config = Config()

    config.merge({"sOmE_kEy": True})
    assert config.sOmE_kEy == True

    uppered = config.upper()
    assert uppered.SOME_KEY == True

    config.upper(inplace=True)
    assert config.SOME_KEY == True
Пример #9
0
def test_from_env_no_separator():
    os.environ["AWS_DEFAULT_REGION"] = "us-east-1"

    config = from_env(prefix="_").lower(True)
    with pytest.raises(AssertionError):
        assert config.aws_default_region == "whatever"
    assert config.aws_default_region == Config()

    config = from_env(separator="").lower(True)
    with pytest.raises(AssertionError):
        assert config.AWS_DEFAULT_REGION == "us-east-1"
    assert config.aws_default_region == "us-east-1"

    config = from_env(separator=None)
    with pytest.raises(AssertionError):
        assert config.aws_default_region == "us-east-1"
    assert config.AWS_DEFAULT_REGION == "us-east-1"

    config = from_env()
    with pytest.raises(AssertionError):
        assert config.aws_default_region == "us-east-1"
    assert config.AWS_DEFAULT_REGION == "us-east-1"
Пример #10
0
from cleo import argument as cleo_argument

from ilexconf import Config

common_args = Config()


def _add_arg(arg):
    common_args[arg.name].arg = arg


def argument(name):
    return common_args[name].arg


path = cleo_argument(
    name="path",
    description="[optional] Path to the configuration file.",
    optional=True,
)
_add_arg(path)
Пример #11
0
def test_as_dict():
    cfg = Config(NESTED, MERGABLE)
    d = dict(cfg)
    assert d == MERGED
Пример #12
0
def test_list():
    cfg = Config(WITH_LISTS)
    assert dict(cfg) == WITH_LISTS
Пример #13
0
def test_setattr():
    cfg = Config(NESTED, MERGABLE)
    cfg.a1.b1.c1 = 8
    assert cfg.a1.b1.c1 == 8
Пример #14
0
def test_empty_config():
    cfg = Config()
    assert cfg == {}
    assert "a0" not in cfg
Пример #15
0
def test_quick_start(
    settings_json_dict, settings_json_file_path, resulting_dict, tmp_path
):
    # os.putenv("AWS_DEFAULT_REGION", "us-east-1")
    os.environ["AWS_DEFAULT_REGION"] = "us-east-1"

    # [create]
    from ilexconf import Config, from_json, from_env, to_json

    # Empty config
    config = Config()
    assert dict(config) == {}

    # Create config from json and merge it into our initial config
    # Let settings_json_file_path = "settings.json" where inside the file we have
    # { "database": { "connection": { "host": "localhost", "port": 5432 } } }
    config.merge(from_json(settings_json_file_path))
    assert dict(config) == {
        "database": {"connection": {"host": "localhost", "port": 5432}}
    }

    # Merge dict into config
    config.merge({"database": {"connection": {"host": "test.local"}}})
    assert dict(config) == {
        "database": {"connection": {"host": "test.local", "port": 5432}}
    }

    # Merge environment variables into config
    config.merge(from_env(prefix="AWS_", separator="__").lower(inplace=True))
    assert dict(config) == {
        "database": {"connection": {"host": "test.local", "port": 5432}},
        "default_region": "us-east-1",
    }

    # Merge keyword arguments
    config.set("my__keyword__argument", True, key_sep="__")
    assert dict(config) == {
        "database": {"connection": {"host": "test.local", "port": 5432}},
        "default_region": "us-east-1",
        "my": {"keyword": {"argument": True}},
    }

    # Clear values, just like with dict
    config.clear()
    assert dict(config) == {}

    # Or, better yet, do this all in one step, since Config() constructor
    # accepts any number of mapping objects and keyword arguments as
    # initialization parameters. However, order of parameters matters.
    # Last mappings are merged on top of others. And keywords override even that.
    config = Config(
        from_json(settings_json_file_path),
        {"database": {"connection": {"host": "test.local"}}},
        database__connection__port=4000,
    )
    assert dict(config) == {
        "database": {"connection": {"host": "test.local", "port": 4000}}
    }
    # [create]

    # from ilexconf import (
    #     from_json,
    #     # from_yaml,
    #     # from_toml,
    #     from_ini,
    #     # from_python,
    #     # from_dotenv,
    #     from_env,
    # )
    # [read]
    cfg1 = from_json(settings_json_file_path)
    assert dict(cfg1) == {
        "database": {"connection": {"host": "localhost", "port": 5432}}
    }
    # [read]

    # cfg2 = Config(
    #     from_yaml("settings.yaml"),
    #     from_toml("settings.toml")
    # )

    # cfg3 = Config(
    #     from_ini("settings.ini"),
    #     from_python("settings.py"),
    #     from_dotenv(".env"),
    #     from_env()
    # )

    # [access]
    # Classic way
    assert config["database"]["connection"]["host"] == "test.local"

    # Dotted key notation
    assert config["database.connection.host"] == "test.local"

    # Via attributes
    assert config.database.connection.host == "test.local"

    # Any combination of the above
    assert config["database"].connection.host == "test.local"
    assert config.database["connection.host"] == "test.local"
    assert config.database["connection"].host == "test.local"
    assert config.database.connection["host"] == "test.local"
    # [access]

    # [upsert]
    # Change value that already exists in the dictionary
    # just like you would do with simple dict
    config["database"]["connection"]["port"] = 8080
    assert config["database"]["connection"]["port"] == 8080

    # Create new value using 'dotted notation'. Notice that
    # 'user' field did not exist before.
    config["database.connection.user"] = "******"
    assert config["database.connection.user"] == "root"

    # Create new value using. 'password' field did not exist
    # before we assigned a value to it and was created automatically.
    config.database.connection.password = "******"
    assert config.database.connection.password == "secret stuff"
    # [upsert]

    # [merge]
    # Config correctly merges nested values. Notice how it overrides
    # the value of the 'password' key in the nested 'connection' config
    # from 'secret stuff' to 'different secret'
    config.database.connection.merge({"password": "******"})
    assert config.database.connection.password == "different secret"
    # [merge]

    # [smart-merge]
    merged = Config(
        {"a1": {"c1": 1, "c2": 2, "c3": 3}}, {"a1": {"c3": "other"}}
    )

    # Instead of overriding the value of the "a1" key completely, `merge` method
    # will recursively look inside and merge nested values.
    assert dict(merged) == {"a1": {"c1": 1, "c2": 2, "c3": "other"}}
    # [smart-merge]

    # [as-dict]
    assert dict(config) == {
        "database": {
            "connection": {
                "host": "test.local",
                "port": 8080,
                "user": "******",
                "password": "******",
            }
        }
    }
    # [as-dict]

    # [write]
    # Temporary path
    p = tmp_path / "settings.json"
    # Save config
    to_json(config, p)
    # Verify written file is correct
    assert dict(from_json(p)) == {
        "database": {
            "connection": {
                "host": "test.local",
                "port": 8080,
                "user": "******",
                "password": "******",
            }
        }
    }
    # [write]

    # [subclass]
    class MyConfig(Config):
        def __init__(self, do_stuff=False):
            # Initialize your custom config using json settings file
            super().__init__(from_json(settings_json_file_path))

            # Add some custom value depending on some logic
            if do_stuff:
                # Here, we create new nested key that did not exist
                # before and assign a value to it.
                self.my.custom.key = "Yes, do stuff"

            # Merge one more mapping on top
            self.merge({"Horizon": "Up"})

    # [subclass]

    # [test-subclass]
    # Now you can use your custom defined Config. Given the `setting.json` file that
    # contains { "database": { "connection": { "host": "localhost", "port": 5432 } } }
    # MyConfig will have the following values:

    config = MyConfig(do_stuff=True)
    assert dict(config) == {
        "database": {
            "connection": {
                "host": "localhost",
                "port": 5432,
            },
        },
        "Horizon": "Up",
        "my": {"custom": {"key": "Yes, do stuff"}},
    }
Пример #16
0
from cleo import option as cleo_option

from ilexconf import Config
from ilexconf.adapters import enabled_formats

common_opts = Config()


def _add_option(o, choices=None):
    common_opts[o.long_name].opt = o
    if choices:
        common_opts[
            o.long_name].opt._description += f"Choices: {', '.join(choices)}."
        common_opts[o.long_name].choices = choices


def option(name):
    if name not in common_opts:
        raise Exception(f"Option {name} was not defined")
    return common_opts[name].opt


filetype = cleo_option(
    long_name="type",
    short_name="t",
    description="File type. ",
    flag=False,
    value_required=True,
)
_add_option(filetype, choices=enabled_formats)
Пример #17
0
def test_simple_merge():
    cfg = Config(Config({"c1": 1, "C2": 2, "c3": 3}), Config({"c3": "val"}))
    assert dict(cfg) == {"c1": 1, "C2": 2, "c3": "val"}