diff --git a/bin/spack b/bin/spack index 5c042edd2d..baf08d1481 100755 --- a/bin/spack +++ b/bin/spack @@ -113,8 +113,8 @@ def main(): spack.spack_working_dir = working_dir if args.mock: - from spack.packages import PackageDB - spack.db = PackageDB(spack.mock_packages_path) + from spack.packages import PackageFinder + spack.db.swap(PackageFinder(spack.mock_packages_path)) # If the user asked for it, don't check ssl certs. if args.insecure: diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py index 9297d6dac3..aa2cfd2846 100644 --- a/lib/spack/spack/directives.py +++ b/lib/spack/spack/directives.py @@ -240,11 +240,11 @@ def patch(pkg, url_or_filename, level=1, when=None): when_spec = parse_anonymous_spec(when, pkg.name) if when_spec not in pkg.patches: - pkg.patches[when_spec] = [Patch(pkg.name, url_or_filename, level)] + pkg.patches[when_spec] = [Patch(pkg, pkg.name, url_or_filename, level)] else: # if this spec is identical to some other, then append this # patch to the existing list. - pkg.patches[when_spec].append(Patch(pkg.name, url_or_filename, level)) + pkg.patches[when_spec].append(Patch(pkg, pkg.name, url_or_filename, level)) @directive('variants') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 3507807373..090349685b 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -712,6 +712,12 @@ def do_patch(self): tty.msg("Patched %s" % self.name) + @property + def namespace(self): + namespace, dot, module = self.__module__.rpartition('.') + return namespace + + def do_fake_install(self): """Make a fake install directory contaiing a 'fake' file in bin.""" mkdirp(self.prefix.bin) diff --git a/lib/spack/spack/packages.py b/lib/spack/spack/packages.py index df54b12324..b21316ebf7 100644 --- a/lib/spack/spack/packages.py +++ b/lib/spack/spack/packages.py @@ -172,7 +172,7 @@ def all_packages(self): def providers_for(self, vpkg_name): - # TODO: USE MORE THAN FIRST REPO + # TODO: THIS IS WRONG; shoudl use more than first repo return self.repos[0].providers_for(vpkg_name) @@ -252,14 +252,22 @@ def load_module(self, fullname): return module - @_autospec - def get(self, spec, new=False): + def _find_repo_for_spec(self, spec): + """Find a repo that contains the supplied spec's package. + + Raises UnknownPackageErrorfor if not found. + """ for repo in self.repos: if spec.name in repo: - return repo.get(spec, new) + return repo raise UnknownPackageError(spec.name) + @_autospec + def get(self, spec, new=False): + return self._find_repo_for_spec(spec).get(spec, new) + + def get_repo(self, namespace): if namespace in self.by_namespace: repo = self.by_namespace[namespace] @@ -343,7 +351,7 @@ def get(self, spec, new=False): del self._instances[spec] if not spec in self._instances: - package_class = self.get_class_for_package_name(spec.name, spec.repo) + package_class = self.get_class_for_package_name(spec.name, spec.namespace) try: copy = spec.copy() self._instances[copy] = package_class(copy) diff --git a/lib/spack/spack/patch.py b/lib/spack/spack/patch.py index b1b6e07738..e89cf11b2f 100644 --- a/lib/spack/spack/patch.py +++ b/lib/spack/spack/patch.py @@ -41,7 +41,11 @@ class Patch(object): """This class describes a patch to be applied to some expanded source code.""" - def __init__(self, pkg_name, path_or_url, level): + def __init__(self, pkg, pkg_name, path_or_url, level): + print pkg, pkg.name, type(pkg) + print "pkg:", dir(pkg.__module__) + print "NAMESPACE", pkg.namespace() + self.pkg_name = pkg_name self.path_or_url = path_or_url self.path = None diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 1666457502..0d49b1fa95 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -112,7 +112,6 @@ from spack.util.string import * from spack.util.prefix import Prefix from spack.virtual import ProviderIndex -from spack.repo_loader import imported_packages_module # Valid pattern for an identifier in Spack identifier_re = r'\w[\w-]*' @@ -413,7 +412,7 @@ def __init__(self, spec_like, *dep_like, **kwargs): self.dependencies = other.dependencies self.variants = other.variants self.variants.spec = self - self.repo = other.repo + self.namespace = other.namespace # Specs are by default not assumed to be normal, but in some # cases we've read them from a file want to assume normal. @@ -1357,7 +1356,7 @@ def _dup(self, other, **kwargs): self.dependencies = DependencyMap() self.variants = other.variants.copy() self.variants.spec = self - self.repo = other.repo + self.namespace = other.namespace # If we copy dependencies, preserve DAG structure in the new spec if kwargs.get('deps', True): @@ -1555,7 +1554,7 @@ def write(s, c): if c == '_': out.write(fmt % self.name) elif c == '.': - longname = '%s.%s.%s' % (imported_packages_module, self.repo, self.name) if self.repo else self.name + longname = '%s.%s.%s' % (self.namespace, self.name) if self.namespace else self.name out.write(fmt % longname) elif c == '@': if self.versions and self.versions != _any_version: @@ -1706,15 +1705,9 @@ def spec(self): """Parse a spec out of the input. If a spec is supplied, then initialize and return it instead of creating a new one.""" - spec_name = None - spec_repo = None - if self.token.value.startswith(imported_packages_module): - lst = self.token.value.split('.') - spec_name = lst[-1] - spec_repo = lst[-2] - else: - spec_name = self.token.value - spec_repo = 'gov.llnl.spack' + spec_namespace, dot, spec_name = self.token.value.rpartition('.') + if not spec_namespace: + spec_namespace = None self.check_identifier(spec_name) @@ -1727,7 +1720,7 @@ def spec(self): spec.compiler = None spec.dependents = DependencyMap() spec.dependencies = DependencyMap() - spec.repo = spec_repo + spec.namespace = spec_namespace spec._normal = False spec._concrete = False diff --git a/lib/spack/spack/test/mock_packages_test.py b/lib/spack/spack/test/mock_packages_test.py index 1f46d65790..071c21b7e0 100644 --- a/lib/spack/spack/test/mock_packages_test.py +++ b/lib/spack/spack/test/mock_packages_test.py @@ -31,14 +31,6 @@ from spack.spec import Spec -def set_pkg_dep(pkg, spec): - """Alters dependence information for a package. - Use this to mock up constraints. - """ - spec = Spec(spec) - spack.db.get(pkg).dependencies[spec.name] = { Spec(pkg) : spec } - - class MockPackagesTest(unittest.TestCase): def initmock(self): # Use the mock packages database for these tests. This allows @@ -53,14 +45,39 @@ def initmock(self): ('site', spack.mock_site_config), ('user', spack.mock_user_config)] + # Store changes to the package's dependencies so we can + # restore later. + self.saved_deps = {} + + + def set_pkg_dep(self, pkg_name, spec): + """Alters dependence information for a package. + + Adds a dependency on to pkg. + Use this to mock up constraints. + """ + spec = Spec(spec) + + # Save original dependencies before making any changes. + pkg = spack.db.get(pkg_name) + if pkg_name not in self.saved_deps: + self.saved_deps[pkg_name] = (pkg, pkg.dependencies.copy()) + + # Change dep spec + pkg.dependencies[spec.name] = { Spec(pkg_name) : spec } + def cleanmock(self): """Restore the real packages path after any test.""" spack.db.swap(self.db) - spack.config.config_scopes = self.real_scopes spack.config.clear_config_caches() + # Restore dependency changes that happened during the test + for pkg_name, (pkg, deps) in self.saved_deps.items(): + pkg.dependencies.clear() + pkg.dependencies.update(deps) + def setUp(self): self.initmock() diff --git a/lib/spack/spack/test/package_sanity.py b/lib/spack/spack/test/package_sanity.py index 70b5d6a478..a5925ea066 100644 --- a/lib/spack/spack/test/package_sanity.py +++ b/lib/spack/spack/test/package_sanity.py @@ -29,7 +29,7 @@ import spack import spack.url as url -from spack.packages import PackageDB +from spack.packages import PackageFinder class PackageSanityTest(unittest.TestCase): diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py index 549f829d3e..a71026d183 100644 --- a/lib/spack/spack/test/spec_dag.py +++ b/lib/spack/spack/test/spec_dag.py @@ -40,8 +40,8 @@ class SpecDagTest(MockPackagesTest): def test_conflicting_package_constraints(self): - set_pkg_dep('mpileaks', 'mpich@1.0') - set_pkg_dep('callpath', 'mpich@2.0') + self.set_pkg_dep('mpileaks', 'mpich@1.0') + self.set_pkg_dep('callpath', 'mpich@2.0') spec = Spec('mpileaks ^mpich ^callpath ^dyninst ^libelf ^libdwarf') @@ -223,25 +223,25 @@ def test_dependents_and_dependencies_are_correct(self): def test_unsatisfiable_version(self): - set_pkg_dep('mpileaks', 'mpich@1.0') + self.set_pkg_dep('mpileaks', 'mpich@1.0') spec = Spec('mpileaks ^mpich@2.0 ^callpath ^dyninst ^libelf ^libdwarf') self.assertRaises(spack.spec.UnsatisfiableVersionSpecError, spec.normalize) def test_unsatisfiable_compiler(self): - set_pkg_dep('mpileaks', 'mpich%gcc') + self.set_pkg_dep('mpileaks', 'mpich%gcc') spec = Spec('mpileaks ^mpich%intel ^callpath ^dyninst ^libelf ^libdwarf') self.assertRaises(spack.spec.UnsatisfiableCompilerSpecError, spec.normalize) def test_unsatisfiable_compiler_version(self): - set_pkg_dep('mpileaks', 'mpich%gcc@4.6') + self.set_pkg_dep('mpileaks', 'mpich%gcc@4.6') spec = Spec('mpileaks ^mpich%gcc@4.5 ^callpath ^dyninst ^libelf ^libdwarf') self.assertRaises(spack.spec.UnsatisfiableCompilerSpecError, spec.normalize) def test_unsatisfiable_architecture(self): - set_pkg_dep('mpileaks', 'mpich=bgqos_0') + self.set_pkg_dep('mpileaks', 'mpich=bgqos_0') spec = Spec('mpileaks ^mpich=sles_10_ppc64 ^callpath ^dyninst ^libelf ^libdwarf') self.assertRaises(spack.spec.UnsatisfiableArchitectureSpecError, spec.normalize)