def test_configset_setdefault():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=False),
        config_from_dict(PROTECTED, lowercase_keys=False),
    )

    # no changes
    assert cfg.setdefault("a2.b1.c1") == "f"
    assert len(cfg) == 8
    with cfg.dotted_iter():
        assert len(cfg) == 17
        assert sorted(cfg) == sorted(
            list(DICT.keys()) + list(PROTECTED.keys()))

    # add key
    assert cfg.setdefault("a2.b1.c7") is None
    assert len(cfg) == 8
    with cfg.dotted_iter():
        assert len(cfg) == 18

    # add key with default
    assert cfg.setdefault("a2.b1.c8", "some value") == "some value"
    assert len(cfg) == 8
    with cfg.dotted_iter():
        assert len(cfg) == 19
    assert cfg["a2.b1.c8"] == "some value"
def test_configset_setitem():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=False),
        config_from_dict(PROTECTED, lowercase_keys=False),
    )

    with cfg.dotted_iter():
        assert len(cfg) == 17
    assert cfg["a1.b2.c1"] == "a"

    cfg["a1.b2.c1"] = 89
    with cfg.dotted_iter():
        assert len(cfg) == 17
    assert cfg["a1.b2.c1"] == 89

    cfg["a1.b2.c4"] = True
    with cfg.dotted_iter():
        assert len(cfg) == 18
    assert cfg["a1.b2.c1"] == 89
    assert cfg["a1.b2.c4"] is True

    cfg["a3"] = {"b1": 10, "b2": "test"}
    with cfg.dotted_iter():
        assert len(cfg) == 20
    assert cfg["a3.b1"] == 10
    assert cfg["a3.b2"] == "test"
def test_configset_clear():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=False),
        config_from_dict(PROTECTED, lowercase_keys=False),
    )
    with cfg.dotted_iter():
        assert len(cfg) == 17

    cfg.clear()
    assert len(cfg) == 0
    with cfg.dotted_iter():
        assert len(cfg) == 0
def test_configset_delitem():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=True),
        config_from_dict(PROTECTED, lowercase_keys=True),
    )

    with cfg.dotted_iter():
        assert len(cfg) == 17

    del cfg["a1.b1"]
    with cfg.dotted_iter():
        assert len(cfg) == 14

    with raises(KeyError):
        del cfg["z"]
def test_configset_pop():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=True),
        config_from_dict(PROTECTED, lowercase_keys=True),
    )

    with cfg.dotted_iter():
        assert len(cfg) == 17

    assert cfg.pop("a2.b1.c1") == "f"
    assert cfg.pop("a2.b1.c1", "something") == "something"
    with raises(KeyError):
        cfg.pop("a2.b1.c1")

    with cfg.dotted_iter():
        assert len(cfg) == 16
def test_configset_update():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=True),
        config_from_dict(PROTECTED, lowercase_keys=True),
    )

    with cfg.dotted_iter():
        assert len(cfg) == 17
    assert cfg["a1.b2.c1"] == "a"

    cfg.update(NESTED)
    with cfg.dotted_iter():
        assert len(cfg) == 17
    assert cfg["a1.b2.c1"] == "a0"

    cfg.update({"important_password_2": "abc"})
    with cfg.dotted_iter():
        assert len(cfg) == 18
def test_configset_list():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT, lowercase_keys=False),
        config_from_dict(PROTECTED, lowercase_keys=False),
    )

    assert sorted(cfg) == sorted(["A1", "a1", "a2"] + list(PROTECTED.keys()))
    with cfg.dotted_iter():
        assert sorted(cfg) == sorted(
            list(DICT.keys()) + list(PROTECTED.keys()))
    assert list(cfg) == list(reversed(cfg))[::-1]
def test_dict_methods_keys_values():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT2_1, lowercase_keys=True),
        config_from_dict(DICT2_2, lowercase_keys=True),
        config_from_env(prefix=PREFIX, lowercase_keys=True),
    )

    assert sorted(cfg.keys()) == [
        "a1",
        "a2",
    ]

    assert dict(zip(cfg.keys(), cfg.values())) == {
        "a1": {
            "b1.c1": "1",
            "b1.c2": "2",
            "b1.c3": "3",
            "b2.c1": "a",
            "b2.c2": "True",
            "b2.c3": "1.1",
        },
        "a2": {
            "b1.c1": "f",
            "b1.c2": False,
            "b1.c3": None,
            "b2.c1": 10,
            "b2.c2": "YWJjZGVmZ2g=",
            "b2.c3": "abcdefgh",
        },
    }

    with cfg.dotted_iter():
        assert sorted(cfg.keys()) == [
            "a1.b1.c1",
            "a1.b1.c2",
            "a1.b1.c3",
            "a1.b2.c1",
            "a1.b2.c2",
            "a1.b2.c3",
            "a2.b1.c1",
            "a2.b1.c2",
            "a2.b1.c3",
            "a2.b2.c1",
            "a2.b2.c2",
            "a2.b2.c3",
        ]

        assert dict(zip(cfg.keys(), cfg.values())) == cfg.as_dict()
def test_get_dict():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT2_1, lowercase_keys=True),
        config_from_dict(DICT2_2, lowercase_keys=True),
        config_from_env(prefix=PREFIX, lowercase_keys=True),
    )

    a2 = {
        "b2.c1": 10,
        "b1.c1": "f",
        "b1.c2": False,
        "b1.c3": None,
        "b2.c1": 10,
        "b2.c2": "YWJjZGVmZ2g=",
        "b2.c3": "abcdefgh",
    }
    a2nested = {
        "b1": {
            "c1": "f",
            "c2": False,
            "c3": None
        },
        "b2": {
            "c1": 10,
            "c2": "YWJjZGVmZ2g=",
            "c3": "abcdefgh"
        },
    }

    assert cfg.get_dict("a2") == a2
    assert cfg.a2.as_dict() == a2
    assert dict(cfg.a2) == a2nested
    with cfg.dotted_iter():
        assert cfg.get_dict("a2") == a2
        assert cfg.a2.as_dict() == a2
        # note that this still returns he nested dict since the dotted iteration
        # impacts only the parent cfg, not cfg.a
        assert dict(cfg.a2) == a2nested
        # to use dotted iteration for children, we need to explicitly set it
        with cfg.a2.dotted_iter() as cfg_a2:
            assert dict(cfg_a2) == a2

    with pytest.raises(KeyError):
        assert cfg.get_dict("a3") is Exception

    assert dict(cfg.a2) == dict(cfg.a2.items())
def test_get_dict_different_types():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT3_1, lowercase_keys=True),
        config_from_dict(DICT3_2, lowercase_keys=True),  # a2 is ignored here
        config_from_dict(DICT3_3, lowercase_keys=True),
    )

    a2 = {
        "b2.c1": 10,
        "b2.c2": "YWJjZGVmZ2g=",
        "b2.c3": "abcdefgh",
        "g2": 10,
        "w2": 123,
        "w3": "abc",
    }
    a2nested = {
        "b2": {
            "c1": 10,
            "c2": "YWJjZGVmZ2g=",
            "c3": "abcdefgh"
        },
        "g2": 10,
        "w2": 123,
        "w3": "abc",
    }

    assert cfg.get_dict("a2") == a2
    assert cfg.a2.as_dict() == a2
    assert dict(cfg.a2) == a2nested

    with cfg.dotted_iter():
        assert cfg.get_dict("a2") == a2
        assert cfg.a2.as_dict() == a2
        # note that this still returns he nested dict since the dotted iteration
        # impacts only the parent cfg, not cfg.a
        assert dict(cfg.a2) == a2nested
        # to use dotted iteration for children, we need to explicitly set it
        with cfg.a2.dotted_iter() as cfg_a2:
            assert dict(cfg_a2) == a2

    with pytest.raises(
            TypeError):  # the first configuration overrides the type
        assert cfg.get_dict("z1") is Exception
    assert cfg.z1 == 100
def test_dict_methods_items():  # type: ignore
    cfg = ConfigurationSet(
        config_from_dict(DICT2_1, lowercase_keys=True),
        config_from_dict(DICT2_2, lowercase_keys=True),
        config_from_env(prefix=PREFIX, lowercase_keys=True),
    )

    assert dict(cfg.items()) == {
        "a1": {
            "b1.c1": "1",
            "b1.c2": "2",
            "b1.c3": "3",
            "b2.c1": "a",
            "b2.c2": "True",
            "b2.c3": "1.1",
        },
        "a2": {
            "b1.c1": "f",
            "b1.c2": False,
            "b1.c3": None,
            "b2.c1": 10,
            "b2.c2": "YWJjZGVmZ2g=",
            "b2.c3": "abcdefgh",
        },
    }

    with cfg.dotted_iter():
        assert dict(cfg.items()) == dict(
            [
                ("a2.b2.c2", "YWJjZGVmZ2g="),
                ("a1.b2.c2", "True"),
                ("a1.b2.c1", "a"),
                ("a1.b1.c2", "2"),
                ("a2.b2.c3", "abcdefgh"),
                ("a2.b1.c1", "f"),
                ("a1.b1.c3", "3"),
                ("a2.b1.c2", False),
                ("a2.b1.c3", None),
                ("a1.b1.c1", "1"),
                ("a2.b2.c1", 10),
                ("a1.b2.c3", "1.1"),
            ]
        )