stacks: environment add/remove respect multiply-defined lists

This commit is contained in:
Gregory Becker 2019-04-08 12:35:12 -07:00 committed by Todd Gamblin
parent f9e6de5474
commit d0bfe0d6a8
2 changed files with 52 additions and 6 deletions

View file

@ -1130,14 +1130,31 @@ def write(self):
# invalidate _repo cache # invalidate _repo cache
self._repo = None self._repo = None
# put any changes in the definitions in the YAML # put any chagnes in the definitions in the YAML
named_speclists = list(self.read_specs.items()) for name, speclist in list(self.read_specs.items())[:-1]:
for i, (name, speclist) in enumerate(named_speclists[:-1]):
conf = config_dict(self.yaml) conf = config_dict(self.yaml)
yaml_list = conf.get('definitions', [])[i].setdefault(name, []) active_yaml_lists = [l for l in conf.get('definitions', [])
yaml_list[:] = speclist.yaml_list if name in l and
_eval_conditional(l.get('when', 'True'))]
# put the new user specs in the YAML # Remove any specs in yaml that are not in internal representation
for ayl in active_yaml_lists:
# If it's not a string, it's a matrix. Those can't have changed
ayl[name][:] = [s for s in ayl.setdefault(name, [])
if not isinstance(s, str) or
Spec(s) in speclist.specs]
# Put the new specs into the first active list from the yaml
new_specs = [entry for entry in speclist.yaml_list
if isinstance(entry, str) and
not any(entry in ayl[name]
for ayl in active_yaml_lists)]
list_for_new_specs = active_yaml_lists[0].setdefault(name, [])
list_for_new_specs[:] = list_for_new_specs + new_specs
# put the new user specs in the YAML.
# This can be done directly because there can't be multiple definitions
# nor when clauses for `specs` list.
yaml_spec_list = config_dict(self.yaml).setdefault('specs', []) yaml_spec_list = config_dict(self.yaml).setdefault('specs', [])
yaml_spec_list[:] = self.user_specs.yaml_list yaml_spec_list[:] = self.user_specs.yaml_list

View file

@ -1059,3 +1059,32 @@ def test_stack_definition_conditional_invalid_variable(tmpdir):
with tmpdir.as_cwd(): with tmpdir.as_cwd():
with pytest.raises(NameError): with pytest.raises(NameError):
env('create', 'test', './spack.yaml') env('create', 'test', './spack.yaml')
def test_stack_definition_conditional_add_write(tmpdir):
filename = str(tmpdir.join('spack.yaml'))
with open(filename, 'w') as f:
f.write("""\
env:
definitions:
- packages: [libelf, mpileaks]
- packages: [callpath]
when: platform == 'test'
specs:
- $packages
""")
with tmpdir.as_cwd():
env('create', 'test', './spack.yaml')
with ev.read('test'):
add('-l', 'packages', 'zmpi')
test = ev.read('test')
packages_lists = list(filter(lambda x: 'packages' in x,
test.yaml['env']['definitions']))
assert len(packages_lists) == 2
assert 'callpath' not in packages_lists[0]['packages']
assert 'callpath' in packages_lists[1]['packages']
assert 'zmpi' in packages_lists[0]['packages']
assert 'zmpi' not in packages_lists[1]['packages']