1"""
2Utility script to migrate Twister configuration files from using string-based
3lists to native YAML lists.
4
5Usage::
6
7    python $ZEPHYR_BASE/scripts/utils/twister_to_list.py \
8           -p path/to/zephyr-based-project
9
10Copyright (c) 2023 Nordic Semiconductor ASA
11SPDX-License-Identifier: Apache-2.0
12"""
13
14import argparse
15from pathlib import Path
16
17from ruamel.yaml import YAML
18
19FIELDS = (
20    "arch_exclude",
21    "arch_allow",
22    "depends_on",
23    "extra_args",
24    "extra_sections",
25    "platform_exclude",
26    "platform_allow",
27    "tags",
28    "toolchain_exclude",
29    "toolchain_allow"
30)
31
32def process(conf):
33    update = False
34    for field in FIELDS:
35        val = conf.get(field)
36        if not val or not isinstance(val, str):
37            continue
38
39        s = val.split()
40        if len(s) > 1:
41            conf[field] = s
42            update = True
43
44    return update
45
46
47def twister_to_list(project, dry_run):
48    yaml = YAML()
49    yaml.indent(offset=2)
50    yaml.preserve_quotes = True
51
52    for p in project.glob("**/*"):
53        if p.name not in ("testcase.yaml", "sample.yaml"):
54            continue
55
56        conf = yaml.load(p)
57        update = False
58
59        common = conf.get("common")
60        if common:
61            update |= process(common)
62
63        for _, spec in conf["tests"].items():
64            update |= process(spec)
65
66        if update:
67            print(f"Updating {p}{' (dry run)' if dry_run else ''}")
68            if not dry_run:
69                with open(p, "w") as f:
70                    yaml.dump(conf, f)
71
72
73if __name__ == "__main__":
74    parser = argparse.ArgumentParser(allow_abbrev=False)
75    parser.add_argument(
76        "-p", "--project", type=Path, required=True, help="Zephyr-based project path"
77    )
78    parser.add_argument("--dry-run", action="store_true", help="Dry run")
79    args = parser.parse_args()
80
81    twister_to_list(args.project, args.dry_run)
82