mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
- Overriding a config value : foo.bar=value - Appending a config value : +foo.bar=value - Appending or overriding a config value : ++foo.bar=value - Removing a config value : ~foo.bar, ~foo.bar=value See https://hydra.cc/docs/advanced/override_grammar/basic/#modifying-the-config-object --- Breaking changes: To modify a list, `foo[0]=bar` must now be passed as `foo.0=bar`. Modifying a nested list inside a dictionary is not supported by omegaconf. --- Closes #4883 Closes #5868 Closes #6129
123 lines
3.3 KiB
Python
123 lines
3.3 KiB
Python
import pytest
|
|
|
|
from dvc.exceptions import InvalidArgumentError
|
|
from dvc.utils.hydra import apply_overrides
|
|
|
|
|
|
@pytest.mark.parametrize("suffix", ["yaml", "toml", "json"])
|
|
@pytest.mark.parametrize(
|
|
"overrides, expected",
|
|
[
|
|
# Overriding
|
|
(["foo=baz"], {"foo": "baz", "goo": {"bag": 3.0}, "lorem": False}),
|
|
(["foo=baz", "goo=bar"], {"foo": "baz", "goo": "bar", "lorem": False}),
|
|
(
|
|
["foo.0=bar"],
|
|
{"foo": ["bar", {"baz": 2}], "goo": {"bag": 3.0}, "lorem": False},
|
|
),
|
|
(
|
|
["foo.1.baz=3"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 3}],
|
|
"goo": {"bag": 3.0},
|
|
"lorem": False,
|
|
},
|
|
),
|
|
(
|
|
["goo.bag=4.0"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 4.0},
|
|
"lorem": False,
|
|
},
|
|
),
|
|
(
|
|
["++goo={bag: 1, b: 2}"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 1, "b": 2},
|
|
"lorem": False,
|
|
},
|
|
),
|
|
# 6129
|
|
(
|
|
["lorem="],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 3.0},
|
|
"lorem": "",
|
|
},
|
|
),
|
|
# 6129
|
|
(
|
|
["lorem=null"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 3.0},
|
|
"lorem": None,
|
|
},
|
|
),
|
|
# 5868
|
|
(
|
|
["lorem=1992-11-20"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 3.0},
|
|
"lorem": "1992-11-20",
|
|
},
|
|
),
|
|
# 5868
|
|
(
|
|
["lorem='1992-11-20'"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 3.0},
|
|
"lorem": "1992-11-20",
|
|
},
|
|
),
|
|
# Appending
|
|
(
|
|
["+a=1"],
|
|
{
|
|
"foo": [{"bar": 1}, {"baz": 2}],
|
|
"goo": {"bag": 3.0},
|
|
"lorem": False,
|
|
"a": 1,
|
|
},
|
|
),
|
|
# Removing
|
|
(["~foo"], {"goo": {"bag": 3.0}, "lorem": False}),
|
|
],
|
|
)
|
|
def test_apply_overrides(tmp_dir, suffix, overrides, expected):
|
|
if suffix == "toml":
|
|
if overrides in [
|
|
["foo=baz"],
|
|
["foo.0=bar"],
|
|
["foo=baz", "goo=bar"],
|
|
["lorem=null"],
|
|
]:
|
|
# TOML dumper breaks when overriding a list/dict with other type
|
|
# or when handling `null` values.
|
|
pytest.xfail()
|
|
|
|
params_file = tmp_dir / f"params.{suffix}"
|
|
params_file.dump(
|
|
{"foo": [{"bar": 1}, {"baz": 2}], "goo": {"bag": 3.0}, "lorem": False}
|
|
)
|
|
apply_overrides(path=params_file.name, overrides=overrides)
|
|
assert params_file.parse() == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"overrides",
|
|
[["foobar=2"], ["lorem=3,2"], ["+lorem=3"], ["foo[0]=bar"]],
|
|
)
|
|
def test_invalid_overrides(tmp_dir, overrides):
|
|
params_file = tmp_dir / "params.yaml"
|
|
params_file.dump(
|
|
{"foo": [{"bar": 1}, {"baz": 2}], "goo": {"bag": 3.0}, "lorem": False}
|
|
)
|
|
with pytest.raises(InvalidArgumentError):
|
|
apply_overrides(path=params_file.name, overrides=overrides)
|