diff options
author | Gregory Becker <becker33@llnl.gov> | 2015-09-25 09:25:12 -0700 |
---|---|---|
committer | Gregory Becker <becker33@llnl.gov> | 2015-11-10 15:45:22 -0800 |
commit | db1b21b9aa1bd28ef706f38e982966f7a01f6aca (patch) | |
tree | cd66cae73c0607287eb62c5d673cd247ebaf0a8b | |
parent | 7989a7f903da149d81f8e6370a9ef8a4f64c45a8 (diff) | |
download | spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.tar.gz spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.tar.bz2 spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.tar.xz spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.zip |
reclaimed the = sign. Architectures now specified by +arch= instead. Decided to prepend flag names with + for clarity in spec names and ease of parsing. Also generalized variants, although there is not yet a way to specify a generalized (name=value) variant.
-rw-r--r-- | lib/spack/spack/spec.py | 110 | ||||
-rw-r--r-- | lib/spack/spack/test/concretize.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/test/multimethod.py | 10 | ||||
-rw-r--r-- | lib/spack/spack/test/spec_dag.py | 5 | ||||
-rw-r--r-- | lib/spack/spack/test/spec_semantics.py | 26 | ||||
-rw-r--r-- | lib/spack/spack/test/spec_syntax.py | 1 | ||||
-rw-r--r-- | lib/spack/spack/variant.py | 2 | ||||
-rw-r--r-- | var/spack/mock_packages/multimethod/package.py | 8 |
8 files changed, 104 insertions, 60 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 572f13901f..9c95fc2177 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -72,7 +72,7 @@ Here is the EBNF grammar for a spec:: dep_list = { ^ spec } spec = id [ options ] options = { @version-list | +variant | -variant | ~variant | - %compiler | =architecture } + %compiler | +arch=architecture | +flag=value} variant = id architecture = id compiler = id [ version-list ] @@ -297,22 +297,25 @@ class VariantSpec(object): on the particular package being built, and each named variant can be enabled or disabled. """ - def __init__(self, name, enabled): + def __init__(self, name, value): self.name = name - self.enabled = enabled + self.value = value def _cmp_key(self): - return (self.name, self.enabled) + return (self.name, self.value) def copy(self): - return VariantSpec(self.name, self.enabled) + return VariantSpec(self.name, self.value) def __str__(self): - out = '+' if self.enabled else '~' - return out + self.name + if self.value in [True,False]: + out = '+' if self.value else '~' + return out + self.name + else: + return '+' + self.name + "=" + self.value class VariantMap(HashableMap): @@ -323,10 +326,10 @@ class VariantMap(HashableMap): def satisfies(self, other, strict=False): if strict or self.spec._concrete: - return all(k in self and self[k].enabled == other[k].enabled + return all(k in self and self[k].value == other[k].value for k in other) else: - return all(self[k].enabled == other[k].enabled + return all(self[k].value == other[k].value for k in other if k in self) @@ -344,7 +347,7 @@ class VariantMap(HashableMap): changed = False for k in other: if k in self: - if self[k].enabled != other[k].enabled: + if self[k].value != other[k].value: raise UnsatisfiableVariantSpecError(self[k], other[k]) else: self[k] = other[k].copy() @@ -437,12 +440,20 @@ class Spec(object): self.versions.add(version) - def _add_variant(self, name, enabled): + def _add_variant(self, name, value): """Called by the parser to add a variant.""" if name in self.variants: raise DuplicateVariantError( "Cannot specify variant '%s' twice" % name) - self.variants[name] = VariantSpec(name, enabled) + self.variants[name] = VariantSpec(name, value) + def _add_flag(self, name, value): + """Called by the parser to add a known flag. + Known flags currently include "arch" + """ + if name == 'arch': + self._set_architecture(value) + else: + raise SpecError("Invalid flag specified") def _set_compiler(self, compiler): """Called by the parser to set the compiler.""" @@ -653,7 +664,7 @@ class Spec(object): def to_node_dict(self): d = { 'variants' : dict( - (name,v.enabled) for name, v in self.variants.items()), + (name,v.value) for name, v in self.variants.items()), 'arch' : self.architecture, 'dependencies' : dict((d, self.dependencies[d].dag_hash()) for d in sorted(self.dependencies)) @@ -690,8 +701,8 @@ class Spec(object): else: spec.compiler = CompilerSpec.from_dict(node) - for name, enabled in node['variants'].items(): - spec.variants[name] = VariantSpec(name, enabled) + for name, value in node['variants'].items(): + spec.variants[name] = VariantSpec(name, value) return spec @@ -804,6 +815,7 @@ class Spec(object): spec._replace_with(concrete) changed = True + # If there are duplicate providers or duplicate provider deps, this # consolidates them and merge constraints. changed |= self.normalize(force=True) @@ -1138,7 +1150,7 @@ class Spec(object): """ other = self._autospec(other) - if not self.name == other.name: + if not (self.name == other.name or self.name == "any-pkg-name" or other.name == "any-pkg-name"): raise UnsatisfiableSpecNameError(self.name, other.name) if not self.versions.overlaps(other.versions): @@ -1146,7 +1158,7 @@ class Spec(object): for v in other.variants: if (v in self.variants and - self.variants[v].enabled != other.variants[v].enabled): + self.variants[v].value != other.variants[v].value): raise UnsatisfiableVariantSpecError(self.variants[v], other.variants[v]) @@ -1228,7 +1240,10 @@ class Spec(object): return spec_like try: - return spack.spec.Spec(spec_like) + spec = spack.spec.Spec(spec_like) + if spec.name == "any-pkg-name": + raise SpecError("anonymous package -- this will always be handled") + return spec except SpecError: return parse_anonymous_spec(spec_like, self.name) @@ -1248,7 +1263,7 @@ class Spec(object): """ other = self._autospec(other) - # A concrete provider can satisfy a virtual dependency. + # A concrete provider can satisfy a virtual dependency. if not self.virtual and other.virtual: pkg = spack.db.get(self.name) if pkg.provides(other.name): @@ -1622,7 +1637,7 @@ class Spec(object): showid = kwargs.pop('ids', False) cover = kwargs.pop('cover', 'nodes') indent = kwargs.pop('indent', 0) - fmt = kwargs.pop('format', '$_$@$%@$+$=') + fmt = kwargs.pop('format', '$_$@$%@$+$+arch=') prefix = kwargs.pop('prefix', None) check_kwargs(kwargs, self.tree) @@ -1707,11 +1722,18 @@ class SpecParser(spack.parse.Parser): elif self.accept(ON): specs.append(self.empty_spec()) - specs[-1]._add_variant(self.variant(), True) + self.expect(ID) + self.check_identifier() + name = self.token.value + if self.accept(EQ): + self.expect(ID) + specs[-1]._add_flag(name,self.token.value) + else: + specs[-1]._add_variant(self.variant(name),True) elif self.accept(OFF): specs.append(self.empty_spec()) - specs[-1]._add_variant(self.variant(), False) + specs[-1]._add_variant(self.variant(),False) else: self.unexpected_token() @@ -1719,6 +1741,10 @@ class SpecParser(spack.parse.Parser): except spack.parse.ParseError, e: raise SpecParseError(e) + for top_spec in specs: + for spec in top_spec.traverse(): + if 'arch' in spec.variants: + spec.architecture = spec.variants['arch'] return specs @@ -1763,10 +1789,17 @@ class SpecParser(spack.parse.Parser): #Should we be able to add cflags eventually? while self.next: if self.accept(ON): - spec._add_variant(self.variant(), True) + self.expect(ID) + self.check_identifier() + name = self.token.value + if self.accept(EQ): + self.expect(ID) + spec._add_flag(name,self.token.value) + else: + spec._add_variant(self.variant(name),True) elif self.accept(OFF): - spec._add_variant(self.variant(), False) + spec._add_variant(self.variant(),False) elif self.accept(PCT): spec._set_compiler(self.compiler()) @@ -1805,18 +1838,23 @@ class SpecParser(spack.parse.Parser): spec._add_version(version) added_version = True + elif self.accept(ON): - spec._add_variant(self.variant(), True) + self.expect(ID) + self.check_identifier() + name = self.token.value + if self.accept(EQ): + self.expect(ID) + spec._add_flag(name,self.token.value) + else: + spec._add_variant(self.variant(name),True) elif self.accept(OFF): - spec._add_variant(self.variant(), False) + spec._add_variant(self.variant(),False) elif self.accept(PCT): spec._set_compiler(self.compiler()) - elif self.accept(EQ): - spec._set_architecture(self.architecture()) - else: break @@ -1827,13 +1865,17 @@ class SpecParser(spack.parse.Parser): return spec - def variant(self): - self.expect(ID) - self.check_identifier() - return self.token.value - + def variant(self,name=None): + #TODO: Make generalized variants possible + if name: + return name + else: + self.expect(ID) + self.check_identifier() + return self.token.value def architecture(self): + #TODO: Make this work properly as a subcase of variant (includes adding names to grammar) self.expect(ID) return self.token.value diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index b3a77d076a..a651e29718 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -38,7 +38,7 @@ class ConcretizeTest(MockPackagesTest): for name in abstract.variants: avariant = abstract.variants[name] cvariant = concrete.variants[name] - self.assertEqual(avariant.enabled, cvariant.enabled) + self.assertEqual(avariant.value, cvariant.value) for name in abstract.package.variants: self.assertTrue(name in concrete.variants) diff --git a/lib/spack/spack/test/multimethod.py b/lib/spack/spack/test/multimethod.py index cd5d9e625e..ead3010512 100644 --- a/lib/spack/spack/test/multimethod.py +++ b/lib/spack/spack/test/multimethod.py @@ -92,19 +92,19 @@ class MultiMethodTest(MockPackagesTest): def test_architecture_match(self): - pkg = spack.db.get('multimethod=x86_64') + pkg = spack.db.get('multimethod+arch=x86_64') self.assertEqual(pkg.different_by_architecture(), 'x86_64') - pkg = spack.db.get('multimethod=ppc64') + pkg = spack.db.get('multimethod+arch=ppc64') self.assertEqual(pkg.different_by_architecture(), 'ppc64') - pkg = spack.db.get('multimethod=ppc32') + pkg = spack.db.get('multimethod+arch=ppc32') self.assertEqual(pkg.different_by_architecture(), 'ppc32') - pkg = spack.db.get('multimethod=arm64') + pkg = spack.db.get('multimethod+arch=arm64') self.assertEqual(pkg.different_by_architecture(), 'arm64') - pkg = spack.db.get('multimethod=macos') + pkg = spack.db.get('multimethod+arch=macos') self.assertRaises(NoSuchMethodError, pkg.different_by_architecture) diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py index 549f829d3e..9d6e7bd2a4 100644 --- a/lib/spack/spack/test/spec_dag.py +++ b/lib/spack/spack/test/spec_dag.py @@ -241,8 +241,8 @@ class SpecDagTest(MockPackagesTest): def test_unsatisfiable_architecture(self): - set_pkg_dep('mpileaks', 'mpich=bgqos_0') - spec = Spec('mpileaks ^mpich=sles_10_ppc64 ^callpath ^dyninst ^libelf ^libdwarf') + set_pkg_dep('mpileaks', 'mpich+arch=bgqos_0') + spec = Spec('mpileaks ^mpich+arch=sles_10_ppc64 ^callpath ^dyninst ^libelf ^libdwarf') self.assertRaises(spack.spec.UnsatisfiableArchitectureSpecError, spec.normalize) @@ -426,6 +426,7 @@ class SpecDagTest(MockPackagesTest): orig.concretize() copy = orig.copy() + print orig self.check_links(copy) self.assertEqual(orig, copy) diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py index 6666dbbb52..5b2cebddef 100644 --- a/lib/spack/spack/test/spec_semantics.py +++ b/lib/spack/spack/test/spec_semantics.py @@ -111,11 +111,11 @@ class SpecSematicsTest(MockPackagesTest): def test_satisfies_architecture(self): - self.check_satisfies('foo=chaos_5_x86_64_ib', '=chaos_5_x86_64_ib') - self.check_satisfies('foo=bgqos_0', '=bgqos_0') + self.check_satisfies('foo+arch=chaos_5_x86_64_ib', '+arch=chaos_5_x86_64_ib') + self.check_satisfies('foo+arch=bgqos_0', '+arch=bgqos_0') - self.check_unsatisfiable('foo=bgqos_0', '=chaos_5_x86_64_ib') - self.check_unsatisfiable('foo=chaos_5_x86_64_ib', '=bgqos_0') + self.check_unsatisfiable('foo+arch=bgqos_0', '+arch=chaos_5_x86_64_ib') + self.check_unsatisfiable('foo+arch=chaos_5_x86_64_ib', '+arch=bgqos_0') def test_satisfies_dependencies(self): @@ -267,13 +267,13 @@ class SpecSematicsTest(MockPackagesTest): def test_constrain_arch(self): - self.check_constrain('libelf=bgqos_0', 'libelf=bgqos_0', 'libelf=bgqos_0') - self.check_constrain('libelf=bgqos_0', 'libelf', 'libelf=bgqos_0') + self.check_constrain('libelf+arch=bgqos_0', 'libelf+arch=bgqos_0', 'libelf+arch=bgqos_0') + self.check_constrain('libelf+arch=bgqos_0', 'libelf', 'libelf+arch=bgqos_0') def test_constrain_compiler(self): - self.check_constrain('libelf=bgqos_0', 'libelf=bgqos_0', 'libelf=bgqos_0') - self.check_constrain('libelf=bgqos_0', 'libelf', 'libelf=bgqos_0') + self.check_constrain('libelf+arch=bgqos_0', 'libelf+arch=bgqos_0', 'libelf+arch=bgqos_0') + self.check_constrain('libelf+arch=bgqos_0', 'libelf', 'libelf+arch=bgqos_0') def test_invalid_constraint(self): @@ -283,7 +283,7 @@ class SpecSematicsTest(MockPackagesTest): self.check_invalid_constraint('libelf+debug', 'libelf~debug') self.check_invalid_constraint('libelf+debug~foo', 'libelf+debug+foo') - self.check_invalid_constraint('libelf=bgqos_0', 'libelf=x86_54') + self.check_invalid_constraint('libelf+arch=bgqos_0', 'libelf+arch=x86_54') def test_constrain_changed(self): @@ -293,7 +293,7 @@ class SpecSematicsTest(MockPackagesTest): self.check_constrain_changed('libelf%gcc', '%gcc@4.5') self.check_constrain_changed('libelf', '+debug') self.check_constrain_changed('libelf', '~debug') - self.check_constrain_changed('libelf', '=bgqos_0') + self.check_constrain_changed('libelf', '+arch=bgqos_0') def test_constrain_not_changed(self): @@ -304,7 +304,7 @@ class SpecSematicsTest(MockPackagesTest): self.check_constrain_not_changed('libelf%gcc@4.5', '%gcc@4.5') self.check_constrain_not_changed('libelf+debug', '+debug') self.check_constrain_not_changed('libelf~debug', '~debug') - self.check_constrain_not_changed('libelf=bgqos_0', '=bgqos_0') + self.check_constrain_not_changed('libelf+arch=bgqos_0', '+arch=bgqos_0') self.check_constrain_not_changed('libelf^foo', 'libelf^foo') self.check_constrain_not_changed('libelf^foo^bar', 'libelf^foo^bar') @@ -316,7 +316,7 @@ class SpecSematicsTest(MockPackagesTest): self.check_constrain_changed('libelf^foo%gcc', 'libelf^foo%gcc@4.5') self.check_constrain_changed('libelf^foo', 'libelf^foo+debug') self.check_constrain_changed('libelf^foo', 'libelf^foo~debug') - self.check_constrain_changed('libelf^foo', 'libelf^foo=bgqos_0') + self.check_constrain_changed('libelf^foo', 'libelf^foo+arch=bgqos_0') def test_constrain_dependency_not_changed(self): @@ -326,5 +326,5 @@ class SpecSematicsTest(MockPackagesTest): self.check_constrain_not_changed('libelf^foo%gcc@4.5', 'libelf^foo%gcc@4.5') self.check_constrain_not_changed('libelf^foo+debug', 'libelf^foo+debug') self.check_constrain_not_changed('libelf^foo~debug', 'libelf^foo~debug') - self.check_constrain_not_changed('libelf^foo=bgqos_0', 'libelf^foo=bgqos_0') + self.check_constrain_not_changed('libelf^foo+arch=bgqos_0', 'libelf^foo+arch=bgqos_0') diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py index 404f38906e..4ad4d99d97 100644 --- a/lib/spack/spack/test/spec_syntax.py +++ b/lib/spack/spack/test/spec_syntax.py @@ -70,6 +70,7 @@ class SpecSyntaxTest(unittest.TestCase): spec = expected output = spack.spec.parse(spec) parsed = (" ".join(str(spec) for spec in output)) + print output, parsed self.assertEqual(expected, parsed) diff --git a/lib/spack/spack/variant.py b/lib/spack/spack/variant.py index 3d3e2b0f6d..c572560206 100644 --- a/lib/spack/spack/variant.py +++ b/lib/spack/spack/variant.py @@ -32,5 +32,5 @@ currently variants are just flags. class Variant(object): """Represents a variant on a build. Can be either on or off.""" def __init__(self, default, description): - self.default = bool(default) + self.default = default self.description = str(description) diff --git a/var/spack/mock_packages/multimethod/package.py b/var/spack/mock_packages/multimethod/package.py index 75b1606ffc..dc8dfc9cfb 100644 --- a/var/spack/mock_packages/multimethod/package.py +++ b/var/spack/mock_packages/multimethod/package.py @@ -103,19 +103,19 @@ class Multimethod(Package): # # Make sure we can switch methods on different architectures # - @when('=x86_64') + @when('+arch=x86_64') def different_by_architecture(self): return 'x86_64' - @when('=ppc64') + @when('+arch=ppc64') def different_by_architecture(self): return 'ppc64' - @when('=ppc32') + @when('+arch=ppc32') def different_by_architecture(self): return 'ppc32' - @when('=arm64') + @when('+arch=arm64') def different_by_architecture(self): return 'arm64' |