Repository: spack/spack

Issue:
__future__ breaks Spack
The package `hdf5-blosc` contains the line `from __future__ import print_function`. This seems to break Spack; the error message is

```
fullname= hdf5-blosc
spec_like= hdf5-blosc%gcc@6.3.0-spack  args= ()  kwargs= {}
spec_like= hdf5-blosc%gcc@6.3.0-spack  args= ()  kwargs= {}
spec_like= hdf5-blosc  args= ()  kwargs= {}
spec.name= hdf5-blosc
spec_like= hdf5-blosc  args= ()  kwargs= {}
spec_like= hdf5-blosc%gcc@6.3.0-spack  args= ()  kwargs= {}
spec_like= hdf5-blosc  args= ()  kwargs= {}
spec.name= hdf5-blosc
spec_like= hdf5-blosc  args= ()  kwargs= {}
spec_like= hdf5-blosc  args= ()  kwargs= {}
spec.name= hdf5-blosc
spec_like= hdf5-blosc  args= ()  kwargs= {}
spec_like= __future__  args= ()  kwargs= {}
spec.name= __future__
spec_like= __future__  args= ()  kwargs= {}
spec_like= __future_-  args= ()  kwargs= {}
spec.name= __future_-
spec_like= __future_-  args= ()  kwargs= {}
spec_like= __future-_  args= ()  kwargs= {}
spec.name= __future-_
spec_like= __future-_  args= ()  kwargs= {}
spec_like= __future--  args= ()  kwargs= {}
spec.name= __future--
spec_like= __future--  args= ()  kwargs= {}
spec_like= _-future__  args= ()  kwargs= {}
spec.name= _-future__
spec_like= _-future__  args= ()  kwargs= {}
spec_like= _-future_-  args= ()  kwargs= {}
spec.name= _-future_-
spec_like= _-future_-  args= ()  kwargs= {}
spec_like= _-future-_  args= ()  kwargs= {}
spec.name= _-future-_
spec_like= _-future-_  args= ()  kwargs= {}
spec_like= _-future--  args= ()  kwargs= {}
spec.name= _-future--
spec_like= _-future--  args= ()  kwargs= {}
spec_like= -_future__  args= ()  kwargs= {}
spec.name= None
spec_like= None  args= ()  kwargs= {}
Traceback (most recent call last):
  File "/Users/eschnett/src/spack/bin/spack", line 220, in <module>
    main(sys.argv)
  File "/Users/eschnett/src/spack/bin/spack", line 216, in main
    _main(args, unknown)
  File "/Users/eschnett/src/spack/bin/spack", line 183, in _main
    return_val = command(parser, args)
  File "/Users/eschnett/src/spack/lib/spack/spack/cmd/install.py", line 317, in install
    specs = spack.cmd.parse_specs(args.package, concretize=True)
  File "/Users/eschnett/src/spack/lib/spack/spack/cmd/__init__.py", line 116, in parse_specs
    spec.concretize()  # implies normalize
  File "/Users/eschnett/src/spack/lib/spack/spack/spec.py", line 1681, in concretize
    changes = (self.normalize(force),
  File "/Users/eschnett/src/spack/lib/spack/spack/spec.py", line 1991, in normalize
    any_change = self._normalize_helper(visited, spec_deps, provider_index)
  File "/Users/eschnett/src/spack/lib/spack/spack/spec.py", line 1945, in _normalize_helper
    pkg_dep, deptypes, visited, spec_deps, provider_index)
  File "/Users/eschnett/src/spack/lib/spack/spack/spec.py", line 1879, in _merge_dependency
    index = ProviderIndex([dep], restrict=True)
  File "/Users/eschnett/src/spack/lib/spack/spack/provider_index.py", line 88, in __init__
    self.update(spec)
  File "/Users/eschnett/src/spack/lib/spack/spack/provider_index.py", line 100, in update
    pkg = spec.package
  File "/Users/eschnett/src/spack/lib/spack/spack/spec.py", line 1121, in package
    return spack.repo.get(self)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 75, in converter
    return function(self, spec_like, *args, **kwargs)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 318, in get
    return self.repo_for_pkg(spec).get(spec)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 75, in converter
    return function(self, spec_like, *args, **kwargs)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 577, in get
    package_class = self.get_pkg_class(spec.name)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 832, in get_pkg_class
    module = self._get_pkg_module(pkg_name)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 812, in _get_pkg_module
    module = imp.load_source(fullname, file_path)
  File "/Users/eschnett/src/spack/var/spack/repos/builtin/packages/hdf5-blosc/package.py", line 25, in <module>
    from __future__ import print_function
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 263, in find_module
    if repo.real_name(module_name):
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 493, in real_name
    if name in self:
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 847, in __contains__
    return self.exists(pkg_name)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 781, in exists
    filename = self.filename_for_package_name(pkg_name)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 75, in converter
    return function(self, spec_like, *args, **kwargs)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 691, in filename_for_package_name
    pkg_dir = self.dirname_for_package_name(spec.name)
  File "/Users/eschnett/src/spack/lib/spack/spack/repository.py", line 74, in converter
    spec_like = spack.spec.Spec(spec_like)
  File "/Users/eschnett/src/spack/lib/spack/spack/spec.py", line 926, in __init__
    raise TypeError("Can't make spec out of %s" % type(spec_like))
TypeError: Can't make spec out of <type 'NoneType'>
```

where I've added a few `print` functions to find out what is going on. Apparently, Spack is trying to interpret `future` as a spec.

Remove the `import __future__` seems to make everything work again. The similar package `hdf5` does not contain such an import either, although both packages use the new `print` function.


Discussion:
I can reproduce this but I can't figure out the cause. Even if I comment out every print statement in `hdf5-blosc`, I still see this error message every time I run `spack info hdf5-blosc`. I wonder if one of the other modules that gets called isn't `print_function` compliant? That would cause problems for Python 3 support.
> I wonder if one of the other modules that gets called isn't print_function compliant? That would cause problems for Python 3 support.

I doubt that's the problem.  I believe that each source file gets to decide independently whether or not to use the updated print_function.

I'm still boggled by this error message. I determined that it has nothing to do with `hdf5-blosc` though. Even if you take the simplest package in Spack (I used `stress`) and add `from __future__ import print_function`, `spack info` breaks for that package.
It looks like RepoPath, which is a valid Python loader, is attempting to handle the `from __future__ import print_finction` statement.  You can see that in the strangely reentrant callstack -- notice it gets into repository.py, then the hdf5-blosc package, then back in repository [here](https://github.com/LLNL/spack/blob/develop/lib/spack/spack/repository.py#L256).

`find_module` is supposed to tell the import system whether this importer can handle the module, or whether it should move on and ask some other importer.

 I would look at what the namespace and module_name are in [that line](https://github.com/LLNL/spack/blob/develop/lib/spack/spack/repository.py#L256).  RepoPath is supposed to ignore things not in its namespaces, but I suspect that `__future__` is somehow being imported as a relative thing, I.e. Python is trying to import `spack.pkg.builtin.hdf5_blosc.__future__`, so RepoPath thinks it should handle the import. If that is the case, then RepoPath.find_module should probably return None when module_name is `__future__`, regardless of the namespace.

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/hdf5-blosc/package.py b/var/spack/repos/builtin/packages/hdf5-blosc/package.py
--- a/var/spack/repos/builtin/packages/hdf5-blosc/package.py
+++ b/var/spack/repos/builtin/packages/hdf5-blosc/package.py
@@ -22,7 +22,6 @@
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
-from __future__ import print_function
 import os
 import shutil
 import sys


Test patch: