From 378af922a23cd2c27de65e5aaed77b64be20945d Mon Sep 17 00:00:00 2001 From: Greg Becker Date: Tue, 15 Dec 2020 14:44:58 -0800 Subject: Fix comparisons for abstract specs (#20341) bug only relevant for python3 --- lib/spack/spack/spec.py | 7 +++++-- lib/spack/spack/test/spec_syntax.py | 25 ++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 88516470fb..a424dc60c9 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -3517,8 +3517,11 @@ class Spec(object): def _cmp_node(self): """Comparison key for just *this node* and not its deps.""" - return (self.name, - self.namespace, + # Name or namespace None will lead to invalid comparisons for abstract + # specs. Replace them with the empty string, which is not a valid spec + # name nor namespace so it will not create spurious equalities. + return (self.name or '', + self.namespace or '', tuple(self.versions), self.variants, self.architecture, diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py index edfe73f3e5..b59828206f 100644 --- a/lib/spack/spack/test/spec_syntax.py +++ b/lib/spack/spack/test/spec_syntax.py @@ -2,7 +2,7 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) - +import itertools import os import pytest import shlex @@ -806,3 +806,26 @@ class TestSpecSyntax(object): ]) def test_target_tokenization(self, expected_tokens, spec_string): self.check_lex(expected_tokens, spec_string) + + @pytest.mark.regression('20310') + def test_compare_abstract_specs(self): + """Spec comparisons must be valid for abstract specs. + + Check that the spec cmp_key appropriately handles comparing specs for + which some attributes are None in exactly one of two specs""" + # Add fields in order they appear in `Spec._cmp_node` + constraints = [ + None, + 'foo', + 'foo.foo', + 'foo.foo@foo', + 'foo.foo@foo+foo', + 'foo.foo@foo+foo arch=foo-foo-foo', + 'foo.foo@foo+foo arch=foo-foo-foo %foo', + 'foo.foo@foo+foo arch=foo-foo-foo %foo cflags=foo', + ] + specs = [Spec(s) for s in constraints] + + for a, b in itertools.product(specs, repeat=2): + # Check that we can compare without raising an error + assert a <= b or b < a -- cgit v1.2.3-60-g2f50