1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
from typing import Any
import pytest
from testlib.fixtures.nix import Nix
def do_evaluate(nix: Nix, args: list[str], expect_success: bool = True) -> dict[str, Any] | str:
res = (
nix.nix_instantiate(
[
"--eval",
"--json",
"-E",
"{ arg1, arg2 ? null }: { inherit arg1 arg2; }",
"--strict",
*args,
]
)
.run()
.expect(0 if expect_success else 1)
)
if expect_success:
return res.json()
return res.stderr_s
def test_trivial(nix: Nix):
res = do_evaluate(nix, args=["--arg", "arg1", "[ 1 2 3 ]", "--arg", "arg2", "1"])
assert res["arg1"] == [1, 2, 3]
assert res["arg2"] == 1
def test_recursive(nix: Nix):
res = do_evaluate(
nix,
args=["--arg", "arg1.foo.bar", "1", "--arg", "arg1.foo.baz", "2", "--arg", "arg1.bar", "3"],
)
assert res["arg1"] == {"foo": {"bar": 1, "baz": 2}, "bar": 3}
assert res["arg2"] is None
@pytest.mark.parametrize(
("attribute_path", "expected"),
[("arg1", 2), ("arg1.foo", {"foo": 2}), ("arg1.foo.bar", {"foo": {"bar": 2}})],
)
def test_override(nix: Nix, attribute_path: str, expected: Any):
res = do_evaluate(nix, args=["--arg", attribute_path, "1", "--arg", attribute_path, "2"])
assert res["arg1"] == expected
def test_quoting(nix: Nix):
res = do_evaluate(
nix,
args=[
"--arg",
"arg1.foo.bar",
"1",
"--arg",
'arg1."foo bar baz".baz',
"2",
"--arg",
"arg1.bar",
"2",
],
)
assert res["arg1"] == {"foo": {"bar": 1}, "bar": 2, "foo bar baz": {"baz": 2}}
assert res["arg2"] is None
def test_quoting_error(nix: Nix):
res = do_evaluate(nix, ["--arg", 'arg1."foo bar.baz', "1"], expect_success=False)
assert "error: missing closing quote in selection path 'arg1.\"foo bar.baz'" in res
def test_trailing_dot(nix: Nix):
# This is what `parseAttrPath` from `libutil` does and is consistent with the selection path
# passed to e.g. `nix-build -A`.
res = do_evaluate(nix, args=["--arg", "arg1.bar.", "[ 1 2 3 ]"], expect_success=False)
assert (
"error: Trailing dot on the right-hand side of path expr 'arg1.bar.' is not allowed!" in res
)
@pytest.mark.parametrize(
"args",
[
["--arg", "arg1.foo", "1", "--arg", "arg1.foo.bar", "2"],
["--arg", "arg1.foo.bar", "2", "--arg", "arg1.foo", "1"],
],
)
def test_conflict(nix: Nix, args: list[str]):
res = do_evaluate(nix, args, expect_success=False)
assert (
"error: Cannot set arg1.foo.bar via --arg/--argstr when it's the path-extension of another auto-argument!"
in res
)
@pytest.mark.parametrize("selection", ["foo..bar", "foo.bar.."])
def test_no_empty_items(nix: Nix, selection: str):
res = do_evaluate(nix, ["--arg", selection, "1"], expect_success=False)
assert f"error: consecutive dots not allowed in selection path '{selection}'" in res
|