From ff3205d21efe149fbffc36c3b8e82ac1b69bfec7 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Mon, 7 May 2018 09:05:50 +0200 Subject: [PATCH] Specs add a space before dependencies (#7942) fixes #7941 Modified string representation of Specs to add a space before deps Unit-tests have been modified accordingly Added a test for regression on #7941 --- lib/spack/spack/spec.py | 2 +- lib/spack/spack/test/concretize.py | 13 +++++++ lib/spack/spack/test/spec_syntax.py | 56 ++++++++++++++++------------- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index a2112c060a..59df9e3867 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -3123,7 +3123,7 @@ def cformat(self, *args, **kwargs): return self.format(*args, **kwargs) def dep_string(self): - return ''.join("^" + dep.format() for dep in self.sorted_deps()) + return ''.join(" ^" + dep.format() for dep in self.sorted_deps()) def __str__(self): ret = self.format() + self.dep_string() diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 13dd490d24..f23c20fd6e 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -524,3 +524,16 @@ def test_regression_issue_7705(self): s.concretize() assert not s.package.provides('lapack') + + @pytest.mark.regression('7941') + def test_regression_issue_7941(self): + # The string representation of a spec containing + # an explicit multi-valued variant and a dependency + # might be parsed differently than the originating spec + s = Spec('a foobar=bar ^b') + t = Spec(str(s)) + + s.concretize() + t.concretize() + + assert s.dag_hash() == t.dag_hash() diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py index 6d5225f26e..76867cec73 100644 --- a/lib/spack/spack/test/spec_syntax.py +++ b/lib/spack/spack/test/spec_syntax.py @@ -94,7 +94,7 @@ class TestSpecSyntax(object): # Parse checks # ======================================================================== - def check_parse(self, expected, spec=None, remove_arch=True): + def check_parse(self, expected, spec=None): """Assert that the provided spec is able to be parsed. If this is called with one argument, it assumes that the @@ -152,14 +152,18 @@ def test_anonymous_specs_with_multiple_parts(self): self.check_parse('@4.2: languages=go') def test_simple_dependence(self): - self.check_parse("openmpi^hwloc") - self.check_parse("openmpi^hwloc^libunwind") + self.check_parse("openmpi ^hwloc") + self.check_parse("openmpi ^hwloc", "openmpi^hwloc") + + self.check_parse("openmpi ^hwloc ^libunwind") + self.check_parse("openmpi ^hwloc ^libunwind", + "openmpi^hwloc^libunwind") def test_dependencies_with_versions(self): - self.check_parse("openmpi^hwloc@1.2e6") - self.check_parse("openmpi^hwloc@1.2e6:") - self.check_parse("openmpi^hwloc@:1.4b7-rc3") - self.check_parse("openmpi^hwloc@1.2e6:1.4b7-rc3") + self.check_parse("openmpi ^hwloc@1.2e6") + self.check_parse("openmpi ^hwloc@1.2e6:") + self.check_parse("openmpi ^hwloc@:1.4b7-rc3") + self.check_parse("openmpi ^hwloc@1.2e6:1.4b7-rc3") def test_multiple_specs(self): self.check_parse("mvapich emacs") @@ -172,31 +176,33 @@ def test_multiple_specs_after_kv(self): def test_multiple_specs_long_second(self): self.check_parse('mvapich emacs@1.1.1%intel cflags="-O3"', 'mvapich emacs @1.1.1 %intel cflags=-O3') - self.check_parse('mvapich cflags="-O3 -fPIC" emacs^ncurses%intel') + self.check_parse('mvapich cflags="-O3 -fPIC" emacs ^ncurses%intel') + self.check_parse('mvapich cflags="-O3 -fPIC" emacs ^ncurses%intel', + 'mvapich cflags="-O3 -fPIC" emacs^ncurses%intel') def test_full_specs(self): self.check_parse( "mvapich_foo" - "^_openmpi@1.2:1.4,1.6%intel@12.1+debug~qt_4" - "^stackwalker@8.1_1e") + " ^_openmpi@1.2:1.4,1.6%intel@12.1+debug~qt_4" + " ^stackwalker@8.1_1e") self.check_parse( "mvapich_foo" - "^_openmpi@1.2:1.4,1.6%intel@12.1 debug=2 ~qt_4" - "^stackwalker@8.1_1e") + " ^_openmpi@1.2:1.4,1.6%intel@12.1 debug=2 ~qt_4" + " ^stackwalker@8.1_1e") self.check_parse( 'mvapich_foo' - '^_openmpi@1.2:1.4,1.6%intel@12.1 cppflags="-O3" +debug~qt_4' - '^stackwalker@8.1_1e') + ' ^_openmpi@1.2:1.4,1.6%intel@12.1 cppflags="-O3" +debug~qt_4' + ' ^stackwalker@8.1_1e') self.check_parse( "mvapich_foo" - "^_openmpi@1.2:1.4,1.6%intel@12.1 debug=2 ~qt_4" - "^stackwalker@8.1_1e arch=test-redhat6-x86_32") + " ^_openmpi@1.2:1.4,1.6%intel@12.1 debug=2 ~qt_4" + " ^stackwalker@8.1_1e arch=test-redhat6-x86_32") def test_canonicalize(self): self.check_parse( "mvapich_foo" - "^_openmpi@1.2:1.4,1.6%intel@12.1:12.6+debug~qt_4" - "^stackwalker@8.1_1e", + " ^_openmpi@1.2:1.4,1.6%intel@12.1:12.6+debug~qt_4" + " ^stackwalker@8.1_1e", "mvapich_foo " "^_openmpi@1.6,1.2:1.4%intel@12.1:12.6+debug~qt_4 " @@ -204,21 +210,21 @@ def test_canonicalize(self): self.check_parse( "mvapich_foo" - "^_openmpi@1.2:1.4,1.6%intel@12.1:12.6+debug~qt_4" - "^stackwalker@8.1_1e", + " ^_openmpi@1.2:1.4,1.6%intel@12.1:12.6+debug~qt_4" + " ^stackwalker@8.1_1e", "mvapich_foo " "^stackwalker@8.1_1e " "^_openmpi@1.6,1.2:1.4%intel@12.1:12.6~qt_4+debug") self.check_parse( - "x^y@1,2:3,4%intel@1,2,3,4+a~b+c~d+e~f", + "x ^y@1,2:3,4%intel@1,2,3,4+a~b+c~d+e~f", "x ^y~f+e~d+c~b+a@4,2:3,1%intel@4,3,2,1") self.check_parse( "x arch=test-redhat6-None " - "^y arch=test-None-x86_64 " - "^z arch=linux-None-None", + " ^y arch=test-None-x86_64 " + " ^z arch=linux-None-None", "x os=fe " "^y target=be " @@ -226,12 +232,12 @@ def test_canonicalize(self): self.check_parse( "x arch=test-debian6-x86_64 " - "^y arch=test-debian6-x86_64", + " ^y arch=test-debian6-x86_64", "x os=default_os target=default_target " "^y os=default_os target=default_target") - self.check_parse("x^y", "x@: ^y@:") + self.check_parse("x ^y", "x@: ^y@:") def test_parse_errors(self): errors = ['x@@1.2', 'x ^y@@1.2', 'x@1.2::', 'x::']