Refactor utils into separate modules.
This commit is contained in:
		@@ -2,9 +2,9 @@
 | 
				
			|||||||
import platform as py_platform
 | 
					import platform as py_platform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import spack
 | 
					import spack
 | 
				
			||||||
import error as serr
 | 
					import spack.error as serr
 | 
				
			||||||
from version import Version
 | 
					from spack.version import Version
 | 
				
			||||||
from util import memoized
 | 
					from spack.util.lang import memoized
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class InvalidSysTypeError(serr.SpackError):
 | 
					class InvalidSysTypeError(serr.SpackError):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import spack
 | 
					import spack
 | 
				
			||||||
import spack.packages as packages
 | 
					import spack.packages as packages
 | 
				
			||||||
import spack.test
 | 
					import spack.test
 | 
				
			||||||
from spack.util import list_modules
 | 
					from spack.util.lang import list_modules
 | 
				
			||||||
from spack.colify import colify
 | 
					from spack.colify import colify
 | 
				
			||||||
from pprint import pprint
 | 
					from pprint import pprint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,8 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import spack
 | 
					import spack
 | 
				
			||||||
import spack.compilers.gcc
 | 
					import spack.compilers.gcc
 | 
				
			||||||
from spack.util import list_modules, memoized
 | 
					from spack.util.lang import memoized, list_modules
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@memoized
 | 
					@memoized
 | 
				
			||||||
def supported_compilers():
 | 
					def supported_compilers():
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,10 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
from version import Version
 | 
					
 | 
				
			||||||
from util import *
 | 
					import spack.arch as arch
 | 
				
			||||||
import arch
 | 
					from spack.version import Version
 | 
				
			||||||
from directory_layout import DefaultDirectoryLayout
 | 
					from spack.util.filesystem import *
 | 
				
			||||||
 | 
					from spack.util.executable import *
 | 
				
			||||||
 | 
					from spack.directory_layout import DefaultDirectoryLayout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# This lives in $prefix/lib/spac/spack/__file__
 | 
					# This lives in $prefix/lib/spac/spack/__file__
 | 
				
			||||||
prefix = ancestor(__file__, 4)
 | 
					prefix = ancestor(__file__, 4)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,11 +24,11 @@
 | 
				
			|||||||
import validate
 | 
					import validate
 | 
				
			||||||
import url
 | 
					import url
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
from spec import Compiler
 | 
					from spec import Compiler
 | 
				
			||||||
from version import *
 | 
					from version import *
 | 
				
			||||||
from multi_function import platform
 | 
					from multi_function import platform
 | 
				
			||||||
from stage import Stage
 | 
					from stage import Stage
 | 
				
			||||||
 | 
					from spack.util.lang import memoized, list_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Package(object):
 | 
					class Package(object):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
import spack
 | 
					import spack
 | 
				
			||||||
import spack.error
 | 
					import spack.error
 | 
				
			||||||
import spack.spec
 | 
					import spack.spec
 | 
				
			||||||
from spack.util import *
 | 
					from spack.util.filesystem import new_path
 | 
				
			||||||
import spack.arch as arch
 | 
					import spack.arch as arch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Valid package names can contain '-' but can't start with it.
 | 
					# Valid package names can contain '-' but can't start with it.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@
 | 
				
			|||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import spack.error
 | 
					import spack.error
 | 
				
			||||||
import spack.util
 | 
					import spack.util.filesystem as fs
 | 
				
			||||||
from spack.version import Version
 | 
					from spack.version import Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@@ -61,9 +61,9 @@ def parse_version_string_with_indices(path):
 | 
				
			|||||||
    if os.path.isdir(path):
 | 
					    if os.path.isdir(path):
 | 
				
			||||||
        stem = os.path.basename(path)
 | 
					        stem = os.path.basename(path)
 | 
				
			||||||
    elif re.search(r'((?:sourceforge.net|sf.net)/.*)/download$', path):
 | 
					    elif re.search(r'((?:sourceforge.net|sf.net)/.*)/download$', path):
 | 
				
			||||||
        stem = spack.util.stem(os.path.dirname(path))
 | 
					        stem = fs.stem(os.path.dirname(path))
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        stem = spack.util.stem(path)
 | 
					        stem = fs.stem(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    version_types = [
 | 
					    version_types = [
 | 
				
			||||||
        # GitHub tarballs, e.g. v1.2.3
 | 
					        # GitHub tarballs, e.g. v1.2.3
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,209 +0,0 @@
 | 
				
			|||||||
import os
 | 
					 | 
				
			||||||
import re
 | 
					 | 
				
			||||||
import errno
 | 
					 | 
				
			||||||
import shutil
 | 
					 | 
				
			||||||
import subprocess
 | 
					 | 
				
			||||||
import multiprocessing
 | 
					 | 
				
			||||||
from itertools import product
 | 
					 | 
				
			||||||
import functools
 | 
					 | 
				
			||||||
from contextlib import closing, contextmanager
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import tty
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Supported archvie extensions.
 | 
					 | 
				
			||||||
PRE_EXTS = ["tar"]
 | 
					 | 
				
			||||||
EXTS     = ["gz", "bz2", "xz", "Z", "zip", "tgz"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Add EXTS last so that .tar.gz is matched *before* tar.gz
 | 
					 | 
				
			||||||
ALLOWED_ARCHIVE_TYPES = [".".join(l) for l in product(PRE_EXTS, EXTS)] + EXTS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def memoized(obj):
 | 
					 | 
				
			||||||
    """Decorator that caches the results of a function, storing them
 | 
					 | 
				
			||||||
       in an attribute of that function."""
 | 
					 | 
				
			||||||
    cache = obj.cache = {}
 | 
					 | 
				
			||||||
    @functools.wraps(obj)
 | 
					 | 
				
			||||||
    def memoizer(*args, **kwargs):
 | 
					 | 
				
			||||||
        if args not in cache:
 | 
					 | 
				
			||||||
            cache[args] = obj(*args, **kwargs)
 | 
					 | 
				
			||||||
        return cache[args]
 | 
					 | 
				
			||||||
    return memoizer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def install(src, dest):
 | 
					 | 
				
			||||||
    tty.info("Installing %s to %s" % (src, dest))
 | 
					 | 
				
			||||||
    shutil.copy(src, dest)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def list_modules(directory):
 | 
					 | 
				
			||||||
    """Lists all of the modules, excluding __init__.py, in
 | 
					 | 
				
			||||||
       a particular directory."""
 | 
					 | 
				
			||||||
    for name in os.listdir(directory):
 | 
					 | 
				
			||||||
        if name == '__init__.py':
 | 
					 | 
				
			||||||
            continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        path = new_path(directory, name)
 | 
					 | 
				
			||||||
        if os.path.isdir(path):
 | 
					 | 
				
			||||||
            init_py = new_path(path, '__init__.py')
 | 
					 | 
				
			||||||
            if os.path.isfile(init_py):
 | 
					 | 
				
			||||||
                yield name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        elif name.endswith('.py'):
 | 
					 | 
				
			||||||
            yield re.sub('.py$', '', name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@contextmanager
 | 
					 | 
				
			||||||
def working_dir(dirname):
 | 
					 | 
				
			||||||
    orig_dir = os.getcwd()
 | 
					 | 
				
			||||||
    os.chdir(dirname)
 | 
					 | 
				
			||||||
    yield
 | 
					 | 
				
			||||||
    os.chdir(orig_dir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def mkdirp(*paths):
 | 
					 | 
				
			||||||
    for path in paths:
 | 
					 | 
				
			||||||
        if not os.path.exists(path):
 | 
					 | 
				
			||||||
            os.makedirs(path)
 | 
					 | 
				
			||||||
        elif not os.path.isdir(path):
 | 
					 | 
				
			||||||
            raise OSError(errno.EEXIST, "File alredy exists", path)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def env_flag(name):
 | 
					 | 
				
			||||||
    if name in os.environ:
 | 
					 | 
				
			||||||
        return os.environ[name].lower() == "true"
 | 
					 | 
				
			||||||
    return False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def path_set(var_name, directories):
 | 
					 | 
				
			||||||
    path_str = ":".join(str(dir) for dir in directories)
 | 
					 | 
				
			||||||
    os.environ[var_name] = path_str
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def path_put_first(var_name, directories):
 | 
					 | 
				
			||||||
    """Puts the provided directories first in the path, adding them
 | 
					 | 
				
			||||||
       if they're not already there.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    path = os.environ.get(var_name, "").split(':')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for dir in directories:
 | 
					 | 
				
			||||||
        if dir in path:
 | 
					 | 
				
			||||||
            path.remove(dir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    new_path = tuple(directories) + tuple(path)
 | 
					 | 
				
			||||||
    path_set(var_name, new_path)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def pop_keys(dictionary, *keys):
 | 
					 | 
				
			||||||
    for key in keys:
 | 
					 | 
				
			||||||
        if key in dictionary:
 | 
					 | 
				
			||||||
            dictionary.pop(key)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def remove_items(item_list, *items):
 | 
					 | 
				
			||||||
    for item in items:
 | 
					 | 
				
			||||||
        if item in item_list:
 | 
					 | 
				
			||||||
            item_list.remove(item)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def has_whitespace(string):
 | 
					 | 
				
			||||||
    return re.search(r'\s', string)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def new_path(prefix, *args):
 | 
					 | 
				
			||||||
    path=str(prefix)
 | 
					 | 
				
			||||||
    for elt in args:
 | 
					 | 
				
			||||||
        path = os.path.join(path, str(elt))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if has_whitespace(path):
 | 
					 | 
				
			||||||
        tty.die("Invalid path: '%s'.  Use a path without whitespace." % path)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return path
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def ancestor(dir, n=1):
 | 
					 | 
				
			||||||
    """Get the nth ancestor of a directory."""
 | 
					 | 
				
			||||||
    parent = os.path.abspath(dir)
 | 
					 | 
				
			||||||
    for i in range(n):
 | 
					 | 
				
			||||||
        parent = os.path.dirname(parent)
 | 
					 | 
				
			||||||
    return parent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Executable(object):
 | 
					 | 
				
			||||||
    """Class representing a program that can be run on the command line."""
 | 
					 | 
				
			||||||
    def __init__(self, name):
 | 
					 | 
				
			||||||
        self.exe = name.split(' ')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def add_default_arg(self, arg):
 | 
					 | 
				
			||||||
        self.exe.append(arg)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __call__(self, *args, **kwargs):
 | 
					 | 
				
			||||||
        """Run the executable with subprocess.check_output, return output."""
 | 
					 | 
				
			||||||
        return_output = kwargs.get("return_output", False)
 | 
					 | 
				
			||||||
        fail_on_error = kwargs.get("fail_on_error", True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        quoted_args = [arg for arg in args if re.search(r'^"|^\'|"$|\'$', arg)]
 | 
					 | 
				
			||||||
        if quoted_args:
 | 
					 | 
				
			||||||
            tty.warn("Quotes in package command arguments can confuse shell scripts like configure.",
 | 
					 | 
				
			||||||
                     "The following arguments may cause problems when executed:",
 | 
					 | 
				
			||||||
                     str("\n".join(["    "+arg for arg in quoted_args])),
 | 
					 | 
				
			||||||
                     "Quotes aren't needed because spack doesn't use a shell.  Consider removing them")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        cmd = self.exe + list(args)
 | 
					 | 
				
			||||||
        tty.verbose(" ".join(cmd))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if return_output:
 | 
					 | 
				
			||||||
            return subprocess.check_output(cmd)
 | 
					 | 
				
			||||||
        elif fail_on_error:
 | 
					 | 
				
			||||||
            return subprocess.check_call(cmd)
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return subprocess.call(cmd)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __repr__(self):
 | 
					 | 
				
			||||||
        return "<exe: %s>" % self.exe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def which(name, **kwargs):
 | 
					 | 
				
			||||||
    """Finds an executable in the path like command-line which."""
 | 
					 | 
				
			||||||
    path     = kwargs.get('path', os.environ.get('PATH', '').split(os.pathsep))
 | 
					 | 
				
			||||||
    required = kwargs.get('required', False)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if not path:
 | 
					 | 
				
			||||||
        path = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for dir in path:
 | 
					 | 
				
			||||||
        exe = os.path.join(dir, name)
 | 
					 | 
				
			||||||
        if os.access(exe, os.X_OK):
 | 
					 | 
				
			||||||
            return Executable(exe)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if required:
 | 
					 | 
				
			||||||
        tty.die("spack requires %s.  Make sure it is in your path." % name)
 | 
					 | 
				
			||||||
    return None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def stem(path):
 | 
					 | 
				
			||||||
    """Get the part of a path that does not include its compressed
 | 
					 | 
				
			||||||
       type extension."""
 | 
					 | 
				
			||||||
    for type in ALLOWED_ARCHIVE_TYPES:
 | 
					 | 
				
			||||||
        suffix = r'\.%s$' % type
 | 
					 | 
				
			||||||
        if re.search(suffix, path):
 | 
					 | 
				
			||||||
            return re.sub(suffix, "", path)
 | 
					 | 
				
			||||||
    return path
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def decompressor_for(path):
 | 
					 | 
				
			||||||
    """Get the appropriate decompressor for a path."""
 | 
					 | 
				
			||||||
    tar = which('tar', required=True)
 | 
					 | 
				
			||||||
    tar.add_default_arg('-xf')
 | 
					 | 
				
			||||||
    return tar
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def md5(filename, block_size=2**20):
 | 
					 | 
				
			||||||
    import hashlib
 | 
					 | 
				
			||||||
    md5 = hashlib.md5()
 | 
					 | 
				
			||||||
    with closing(open(filename)) as file:
 | 
					 | 
				
			||||||
        while True:
 | 
					 | 
				
			||||||
            data = file.read(block_size)
 | 
					 | 
				
			||||||
            if not data:
 | 
					 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
            md5.update(data)
 | 
					 | 
				
			||||||
        return md5.hexdigest()
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								lib/spack/spack/util/compression.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								lib/spack/spack/util/compression.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					from itertools import product
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Supported archvie extensions.
 | 
				
			||||||
 | 
					PRE_EXTS = ["tar"]
 | 
				
			||||||
 | 
					EXTS     = ["gz", "bz2", "xz", "Z", "zip", "tgz"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add EXTS last so that .tar.gz is matched *before* tar.gz
 | 
				
			||||||
 | 
					ALLOWED_ARCHIVE_TYPES = [".".join(l) for l in product(PRE_EXTS, EXTS)] + EXTS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def decompressor_for(path):
 | 
				
			||||||
 | 
					    """Get the appropriate decompressor for a path."""
 | 
				
			||||||
 | 
					    tar = which('tar', required=True)
 | 
				
			||||||
 | 
					    tar.add_default_arg('-xf')
 | 
				
			||||||
 | 
					    return tar
 | 
				
			||||||
							
								
								
									
										30
									
								
								lib/spack/spack/util/environment.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								lib/spack/spack/util/environment.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					def env_flag(name):
 | 
				
			||||||
 | 
					    if name in os.environ:
 | 
				
			||||||
 | 
					        return os.environ[name].lower() == "true"
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def path_set(var_name, directories):
 | 
				
			||||||
 | 
					    path_str = ":".join(str(dir) for dir in directories)
 | 
				
			||||||
 | 
					    os.environ[var_name] = path_str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def path_put_first(var_name, directories):
 | 
				
			||||||
 | 
					    """Puts the provided directories first in the path, adding them
 | 
				
			||||||
 | 
					       if they're not already there.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    path = os.environ.get(var_name, "").split(':')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for dir in directories:
 | 
				
			||||||
 | 
					        if dir in path:
 | 
				
			||||||
 | 
					            path.remove(dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    new_path = tuple(directories) + tuple(path)
 | 
				
			||||||
 | 
					    path_set(var_name, new_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def pop_keys(dictionary, *keys):
 | 
				
			||||||
 | 
					    for key in keys:
 | 
				
			||||||
 | 
					        if key in dictionary:
 | 
				
			||||||
 | 
					            dictionary.pop(key)
 | 
				
			||||||
							
								
								
									
										55
									
								
								lib/spack/spack/util/executable.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								lib/spack/spack/util/executable.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					import os
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import spack.tty as tty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Executable(object):
 | 
				
			||||||
 | 
					    """Class representing a program that can be run on the command line."""
 | 
				
			||||||
 | 
					    def __init__(self, name):
 | 
				
			||||||
 | 
					        self.exe = name.split(' ')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_default_arg(self, arg):
 | 
				
			||||||
 | 
					        self.exe.append(arg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __call__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        """Run the executable with subprocess.check_output, return output."""
 | 
				
			||||||
 | 
					        return_output = kwargs.get("return_output", False)
 | 
				
			||||||
 | 
					        fail_on_error = kwargs.get("fail_on_error", True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        quoted_args = [arg for arg in args if re.search(r'^"|^\'|"$|\'$', arg)]
 | 
				
			||||||
 | 
					        if quoted_args:
 | 
				
			||||||
 | 
					            tty.warn("Quotes in package command arguments can confuse shell scripts like configure.",
 | 
				
			||||||
 | 
					                     "The following arguments may cause problems when executed:",
 | 
				
			||||||
 | 
					                     str("\n".join(["    "+arg for arg in quoted_args])),
 | 
				
			||||||
 | 
					                     "Quotes aren't needed because spack doesn't use a shell.  Consider removing them")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cmd = self.exe + list(args)
 | 
				
			||||||
 | 
					        tty.verbose(" ".join(cmd))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if return_output:
 | 
				
			||||||
 | 
					            return subprocess.check_output(cmd)
 | 
				
			||||||
 | 
					        elif fail_on_error:
 | 
				
			||||||
 | 
					            return subprocess.check_call(cmd)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return subprocess.call(cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return "<exe: %s>" % self.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def which(name, **kwargs):
 | 
				
			||||||
 | 
					    """Finds an executable in the path like command-line which."""
 | 
				
			||||||
 | 
					    path     = kwargs.get('path', os.environ.get('PATH', '').split(os.pathsep))
 | 
				
			||||||
 | 
					    required = kwargs.get('required', False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not path:
 | 
				
			||||||
 | 
					        path = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for dir in path:
 | 
				
			||||||
 | 
					        exe = os.path.join(dir, name)
 | 
				
			||||||
 | 
					        if os.access(exe, os.X_OK):
 | 
				
			||||||
 | 
					            return Executable(exe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if required:
 | 
				
			||||||
 | 
					        tty.die("spack requires %s.  Make sure it is in your path." % name)
 | 
				
			||||||
 | 
					    return None
 | 
				
			||||||
							
								
								
									
										71
									
								
								lib/spack/spack/util/filesystem.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								lib/spack/spack/util/filesystem.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					import errno
 | 
				
			||||||
 | 
					from contextlib import contextmanager, closing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import spack.tty as tty
 | 
				
			||||||
 | 
					from spack.util.compression import ALLOWED_ARCHIVE_TYPES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def install(src, dest):
 | 
				
			||||||
 | 
					    """Manually install a file to a particular location."""
 | 
				
			||||||
 | 
					    tty.info("Installing %s to %s" % (src, dest))
 | 
				
			||||||
 | 
					    shutil.copy(src, dest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@contextmanager
 | 
				
			||||||
 | 
					def working_dir(dirname):
 | 
				
			||||||
 | 
					    orig_dir = os.getcwd()
 | 
				
			||||||
 | 
					    os.chdir(dirname)
 | 
				
			||||||
 | 
					    yield
 | 
				
			||||||
 | 
					    os.chdir(orig_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mkdirp(*paths):
 | 
				
			||||||
 | 
					    for path in paths:
 | 
				
			||||||
 | 
					        if not os.path.exists(path):
 | 
				
			||||||
 | 
					            os.makedirs(path)
 | 
				
			||||||
 | 
					        elif not os.path.isdir(path):
 | 
				
			||||||
 | 
					            raise OSError(errno.EEXIST, "File alredy exists", path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def new_path(prefix, *args):
 | 
				
			||||||
 | 
					    path=str(prefix)
 | 
				
			||||||
 | 
					    for elt in args:
 | 
				
			||||||
 | 
					        path = os.path.join(path, str(elt))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if re.search(r'\s', path):
 | 
				
			||||||
 | 
					        tty.die("Invalid path: '%s'.  Use a path without whitespace." % path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ancestor(dir, n=1):
 | 
				
			||||||
 | 
					    """Get the nth ancestor of a directory."""
 | 
				
			||||||
 | 
					    parent = os.path.abspath(dir)
 | 
				
			||||||
 | 
					    for i in range(n):
 | 
				
			||||||
 | 
					        parent = os.path.dirname(parent)
 | 
				
			||||||
 | 
					    return parent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def stem(path):
 | 
				
			||||||
 | 
					    """Get the part of a path that does not include its compressed
 | 
				
			||||||
 | 
					       type extension."""
 | 
				
			||||||
 | 
					    for type in ALLOWED_ARCHIVE_TYPES:
 | 
				
			||||||
 | 
					        suffix = r'\.%s$' % type
 | 
				
			||||||
 | 
					        if re.search(suffix, path):
 | 
				
			||||||
 | 
					            return re.sub(suffix, "", path)
 | 
				
			||||||
 | 
					    return path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def md5(filename, block_size=2**20):
 | 
				
			||||||
 | 
					    """Computes the md5 hash of a file."""
 | 
				
			||||||
 | 
					    import hashlib
 | 
				
			||||||
 | 
					    md5 = hashlib.md5()
 | 
				
			||||||
 | 
					    with closing(open(filename)) as file:
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            data = file.read(block_size)
 | 
				
			||||||
 | 
					            if not data:
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					            md5.update(data)
 | 
				
			||||||
 | 
					        return md5.hexdigest()
 | 
				
			||||||
							
								
								
									
										32
									
								
								lib/spack/spack/util/lang.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								lib/spack/spack/util/lang.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import functools
 | 
				
			||||||
 | 
					from spack.util.filesystem import new_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def memoized(obj):
 | 
				
			||||||
 | 
					    """Decorator that caches the results of a function, storing them
 | 
				
			||||||
 | 
					       in an attribute of that function."""
 | 
				
			||||||
 | 
					    cache = obj.cache = {}
 | 
				
			||||||
 | 
					    @functools.wraps(obj)
 | 
				
			||||||
 | 
					    def memoizer(*args, **kwargs):
 | 
				
			||||||
 | 
					        if args not in cache:
 | 
				
			||||||
 | 
					            cache[args] = obj(*args, **kwargs)
 | 
				
			||||||
 | 
					        return cache[args]
 | 
				
			||||||
 | 
					    return memoizer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def list_modules(directory):
 | 
				
			||||||
 | 
					    """Lists all of the modules, excluding __init__.py, in
 | 
				
			||||||
 | 
					       a particular directory."""
 | 
				
			||||||
 | 
					    for name in os.listdir(directory):
 | 
				
			||||||
 | 
					        if name == '__init__.py':
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        path = new_path(directory, name)
 | 
				
			||||||
 | 
					        if os.path.isdir(path):
 | 
				
			||||||
 | 
					            init_py = new_path(path, '__init__.py')
 | 
				
			||||||
 | 
					            if os.path.isfile(init_py):
 | 
				
			||||||
 | 
					                yield name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif name.endswith('.py'):
 | 
				
			||||||
 | 
					            yield re.sub('.py$', '', name)
 | 
				
			||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
import tty
 | 
					import tty
 | 
				
			||||||
from util import ALLOWED_ARCHIVE_TYPES
 | 
					 | 
				
			||||||
from urlparse import urlparse
 | 
					from urlparse import urlparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from spack.util.compression import ALLOWED_ARCHIVE_TYPES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ALLOWED_SCHEMES    = ["http", "https", "ftp"]
 | 
					ALLOWED_SCHEMES    = ["http", "https", "ftp"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def url(url_string):
 | 
					def url(url_string):
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user