From 3dbde09747e98d5ee6ac2971c87c5c481a21e532 Mon Sep 17 00:00:00 2001 From: Elizabeth Fischer Date: Fri, 14 Oct 2016 19:09:54 -0400 Subject: [PATCH] Workaround for illegal package merging in py-matplotlib/py-basemap (#1964) * Workaround for illegal package merging in py-matplotlib/py-basemap # Conflicts: # var/spack/repos/builtin/packages/py-basemap/package.py * flake8 * flake8 * Be conservative: only apply the namespace package fix for Python >= 3.5.2 * flake8 * Bug fix --- .../builtin/packages/py-basemap/package.py | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/var/spack/repos/builtin/packages/py-basemap/package.py b/var/spack/repos/builtin/packages/py-basemap/package.py index 5b0026eda9..3f5bf989c1 100644 --- a/var/spack/repos/builtin/packages/py-basemap/package.py +++ b/var/spack/repos/builtin/packages/py-basemap/package.py @@ -23,6 +23,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## from spack import * +import os class PyBasemap(Package): @@ -37,10 +38,83 @@ class PyBasemap(Package): extends('python') depends_on('py-setuptools', type='build') depends_on('py-numpy', type=nolink) - depends_on('py-matplotlib+gui', type=nolink) + depends_on('py-matplotlib', type=nolink) depends_on('pil', type=nolink) depends_on("geos") def install(self, spec, prefix): env['GEOS_DIR'] = spec['geos'].prefix setup_py('install', '--prefix=%s' % prefix) + + # We are not sure if this fix is needed before Python 3.5.2. + # If it is needed, this test should be changed. + # See: https://github.com/LLNL/spack/pull/1964 + if spec['python'].version >= Version('3.5.2'): + # Use symlinks to join the two mpl_toolkits/ directories into + # one, inside of basemap. This is because Basemap tries to + # "add to" an existing package in Matplotlib, which is only + # legal Python for "Implicit Namespace Packages": + # https://www.python.org/dev/peps/pep-0420/ + # https://github.com/Homebrew/homebrew-python/issues/112 + # In practice, Python will see only the basemap version of + # mpl_toolkits + path_m = find_package_dir( + spec['py-matplotlib'].prefix, 'mpl_toolkits') + path_b = find_package_dir(spec.prefix, 'mpl_toolkits') + link_dir(path_m, path_b) + + +def find_package_dir(spack_package_root, name): + + """Finds directory with a specific name, somewhere inside a Spack + package. + + spack_package_root: + Root directory to start searching + oldname: + Original name of package (not fully qualified, just the leaf) + newname: + What to rename it to + + """ + for root, dirs, files in os.walk(spack_package_root): + path = os.path.join(root, name) + + # Make sure it's a directory + if not os.path.isdir(path): + continue + + # Make sure it's really a package + if not os.path.exists(os.path.join(path, '__init__.py')): + continue + + return path + + return None + + +def link_dir(src_root, dest_root, link=os.symlink): + """Link all files in src_root into directory dest_root""" + + for src_path, dirnames, filenames in os.walk(src_root): + if not filenames: + continue # avoid explicitly making empty dirs + + # Avoid internal Python stuff + src_leaf = os.path.split(src_path)[1] + if src_leaf.startswith('__'): + continue + + # Make sure the destination directory exists + dest_path = os.path.join(dest_root, src_path[len(src_root) + 1:]) + try: + os.makedirs(dest_path) + except: + pass + + # Link all files from src to dest directory + for fname in filenames: + src = os.path.join(src_path, fname) + dst = os.path.join(dest_path, fname) + if not os.path.exists(dst): + link(src, dst)