From 6dff42be0973c5949d836eab51cfdffb0eda0a69 Mon Sep 17 00:00:00 2001
From: Todd Gamblin <tgamblin@llnl.gov>
Date: Thu, 17 Sep 2015 00:21:33 -0700
Subject: [PATCH] WIP for Matt's branch

---
 bin/spack                                  |  4 +--
 lib/spack/spack/directives.py              |  4 +--
 lib/spack/spack/package.py                 |  6 ++++
 lib/spack/spack/packages.py                | 18 +++++++----
 lib/spack/spack/patch.py                   |  6 +++-
 lib/spack/spack/spec.py                    | 21 +++++--------
 lib/spack/spack/test/mock_packages_test.py | 35 ++++++++++++++++------
 lib/spack/spack/test/package_sanity.py     |  2 +-
 lib/spack/spack/test/spec_dag.py           | 12 ++++----
 9 files changed, 68 insertions(+), 40 deletions(-)

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 <spec> 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)
 
-- 
GitLab