diff options
author | Greg Becker <becker33@llnl.gov> | 2020-06-25 12:34:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-25 12:34:09 -0500 |
commit | 096bd69a949225590feeaeaf16545d673c4cee6d (patch) | |
tree | 27bfb6caf1f1d19c7dd3ac5431b39284312d81bd /lib | |
parent | f936e3a1dbc43629e01a3a7e2cc1682419cb381b (diff) | |
download | spack-096bd69a949225590feeaeaf16545d673c4cee6d.tar.gz spack-096bd69a949225590feeaeaf16545d673c4cee6d.tar.bz2 spack-096bd69a949225590feeaeaf16545d673c4cee6d.tar.xz spack-096bd69a949225590feeaeaf16545d673c4cee6d.zip |
prevent multiple version sigils in the same spec (#17246)
* prevent multiple version sigils in the same spec
* fix packages with malformed versions
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/spec.py | 35 | ||||
-rw-r--r-- | lib/spack/spack/test/spec_syntax.py | 15 | ||||
-rw-r--r-- | lib/spack/spack/version.py | 3 |
3 files changed, 44 insertions, 9 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index b23142e101..175d160855 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -511,8 +511,17 @@ class CompilerSpec(object): raise TypeError( "__init__ takes 1 or 2 arguments. (%d given)" % nargs) - def _add_version(self, version): - self.versions.add(version) + def _add_versions(self, version_list): + # If it already has a non-trivial version list, this is an error + if self.versions and self.versions != vn.VersionList(':'): + # Note: This may be impossible to reach by the current parser + # Keeping it in case the implementation changes. + raise MultipleVersionError( + 'A spec cannot contain multiple version signifiers.' + ' Use a version list instead.') + self.versions = vn.VersionList() + for version in version_list: + self.versions.add(version) def _autospec(self, compiler_spec_like): if isinstance(compiler_spec_like, CompilerSpec): @@ -1050,9 +1059,16 @@ class Spec(object): # # Private routines here are called by the parser when building a spec. # - def _add_version(self, version): + def _add_versions(self, version_list): """Called by the parser to add an allowable version.""" - self.versions.add(version) + # If it already has a non-trivial version list, this is an error + if self.versions and self.versions != vn.VersionList(':'): + raise MultipleVersionError( + 'A spec cannot contain multiple version signifiers.' + ' Use a version list instead.') + self.versions = vn.VersionList() + for version in version_list: + self.versions.add(version) def _add_flag(self, name, value): """Called by the parser to add a known flag. @@ -4157,9 +4173,7 @@ class SpecParser(spack.parse.Parser): while self.next: if self.accept(AT): vlist = self.version_list() - spec.versions = vn.VersionList() - for version in vlist: - spec._add_version(version) + spec._add_versions(vlist) elif self.accept(ON): name = self.variant() @@ -4251,8 +4265,7 @@ class SpecParser(spack.parse.Parser): compiler.versions = vn.VersionList() if self.accept(AT): vlist = self.version_list() - for version in vlist: - compiler._add_version(version) + compiler._add_versions(vlist) else: compiler.versions = vn.VersionList(':') return compiler @@ -4325,6 +4338,10 @@ class DuplicateDependencyError(spack.error.SpecError): """Raised when the same dependency occurs in a spec twice.""" +class MultipleVersionError(spack.error.SpecError): + """Raised when version constraints occur in a spec twice.""" + + class DuplicateCompilerSpecError(spack.error.SpecError): """Raised when the same compiler occurs in a spec twice.""" diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py index c9a2100b09..52a842912e 100644 --- a/lib/spack/spack/test/spec_syntax.py +++ b/lib/spack/spack/test/spec_syntax.py @@ -20,6 +20,7 @@ from spack.spec import AmbiguousHashError, InvalidHashError, NoSuchHashError from spack.spec import DuplicateArchitectureError from spack.spec import DuplicateDependencyError, DuplicateCompilerSpecError from spack.spec import SpecFilenameError, NoSuchSpecFileError +from spack.spec import MultipleVersionError from spack.variant import DuplicateVariantError @@ -149,6 +150,9 @@ class TestSpecSyntax(object): self.check_parse("openmpi ^hwloc ^libunwind", "openmpi^hwloc^libunwind") + def test_version_after_compiler(self): + self.check_parse('foo@2.0%bar@1.0', 'foo %bar@1.0 @2.0') + def test_dependencies_with_versions(self): self.check_parse("openmpi ^hwloc@1.2e6") self.check_parse("openmpi ^hwloc@1.2e6:") @@ -432,6 +436,17 @@ class TestSpecSyntax(object): ] self._check_raises(DuplicateVariantError, duplicates) + def test_multiple_versions(self): + multiples = [ + 'x@1.2@2.3', + 'x@1.2:2.3@1.4', + 'x@1.2@2.3:2.4', + 'x@1.2@2.3,2.4', + 'x@1.2 +foo~bar @2.3', + 'x@1.2%y@1.2@2.3:2.4', + ] + self._check_raises(MultipleVersionError, multiples) + def test_duplicate_dependency(self): self._check_raises(DuplicateDependencyError, ["x ^y ^y"]) diff --git a/lib/spack/spack/version.py b/lib/spack/spack/version.py index bb7a79772e..0c7399c3fb 100644 --- a/lib/spack/spack/version.py +++ b/lib/spack/spack/version.py @@ -782,6 +782,9 @@ class VersionList(object): def __len__(self): return len(self.versions) + def __bool__(self): + return bool(self.versions) + @coerced def __eq__(self, other): return other is not None and self.versions == other.versions |