5 from tests.helpers import validates, traverse, load_yaml
6 from tests.structures import Resource
7 from tests.utils import nested_dict
10 class GetAttrValidator:
11 def __init__(self, yaml, base_dir):
13 self.base_dir = base_dir
18 return self.yaml.get("resources", {})
20 def __call__(self, path, get_attr_arg):
21 if not isinstance(get_attr_arg, list):
22 self.add_error(path, get_attr_arg, "get_attr argument is not a list")
23 elif len(get_attr_arg) < 1:
25 path, get_attr_arg, "get_attr argument must have a parameter"
27 elif get_attr_arg[0] not in self.resources:
31 "Resource ID could not be found. Please ensure "
32 "the resource is spelled correctly and defined "
33 "under the resources section of the YAML file.",
36 r_id = get_attr_arg[0]
37 r = Resource(r_id, self.yaml["resources"][r_id])
40 if len(get_attr_arg) < 2:
44 "get_attr used on nested "
45 "resource, but no attribute "
49 expected_param = get_attr_arg[1]
50 nested_yaml = r.get_nested_yaml(self.base_dir)
51 param = nested_dict.get(nested_yaml, "outputs", expected_param)
58 + " not found in outputs "
59 + r.get_nested_filename(),
62 def add_error(self, path, arg, message):
63 path_str = ".".join(path)
64 self.errors.append("{} {}: {}".format(path_str, arg, message))
67 def error_message(self):
68 errs = ", ".join(self.errors)
69 return "Invalid get_attr usage detected: {}".format(errs)
74 def test_08_validate_get_attr_usage(yaml_file):
75 """Ensures that every get_attr refers to a valid resource name,
76 and if that resource is a nested YAML that the attribute exists as
77 an output of the nested YAML file. It does not validate the
78 attribute keys are always valid because of the attributes could
79 refer to intrinsic attributes of the resource that are not present
82 yml = load_yaml(yaml_file)
83 base_dir, _ = os.path.split(yaml_file)
84 validator = GetAttrValidator(yml, base_dir)
85 traverse(yml, "get_attr", validator)
86 assert not validator.errors, validator.error_message