From 2e3303abd08aec1c7a53e78fabbbf13f6de5b5b3 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Thu, 27 Dec 2018 15:30:32 -0800 Subject: bugfix: nested directives were broken in python 3 - The nested directive implementation was broken for python 3 - directive results were not properly removed from the directive list when it was processed in the DirectiveMeta metaclass. - the issue was that remove_directives only descended into a list or tuple, but in Python3, the initial value passed to the function is a view of dictionary values. - make it a list to fix things, and add a regression test. --- lib/spack/spack/directives.py | 2 +- lib/spack/spack/test/patch.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py index 5b2bf652ed..8e9cf4dbcc 100644 --- a/lib/spack/spack/directives.py +++ b/lib/spack/spack/directives.py @@ -194,7 +194,7 @@ class DirectiveMeta(type): # Nasty, but it's the best way I can think of to avoid # side effects if directive results are passed as args remove_directives(args) - remove_directives(kwargs.values()) + remove_directives(list(kwargs.values())) # A directive returns either something that is callable on a # package or a sequence of them diff --git a/lib/spack/spack/test/patch.py b/lib/spack/spack/test/patch.py index 33db0d2a39..bdc67968f6 100644 --- a/lib/spack/spack/test/patch.py +++ b/lib/spack/spack/test/patch.py @@ -11,6 +11,7 @@ from llnl.util.filesystem import working_dir, mkdirp import spack.patch import spack.paths +import spack.repo import spack.util.compression from spack.util.executable import Executable from spack.stage import Stage @@ -102,6 +103,29 @@ def test_patch_in_spec(mock_packages, config): spec.variants['patches'].value) +def test_nested_directives(mock_packages): + """Ensure pkg data structures are set up properly by nested directives.""" + # this ensures that the patch() directive results were removed + # properly from the DirectiveMeta._directives_to_be_executed list + patcher = spack.repo.path.get_pkg_class('patch-several-dependencies') + assert len(patcher.patches) == 0 + + # this ensures that results of dependency patches were properly added + # to Dependency objects. + libelf_dep = next(iter(patcher.dependencies['libelf'].values())) + assert len(libelf_dep.patches) == 1 + assert len(libelf_dep.patches[Spec('libelf')]) == 1 + + libdwarf_dep = next(iter(patcher.dependencies['libdwarf'].values())) + assert len(libdwarf_dep.patches) == 2 + assert len(libdwarf_dep.patches[Spec('libdwarf')]) == 1 + assert len(libdwarf_dep.patches[Spec('libdwarf@20111030')]) == 1 + + fake_dep = next(iter(patcher.dependencies['fake'].values())) + assert len(fake_dep.patches) == 1 + assert len(fake_dep.patches[Spec('fake')]) == 2 + + def test_patched_dependency( mock_packages, config, install_mockery, mock_fetch): """Test whether patched dependencies work.""" -- cgit v1.2.3-60-g2f50