Compare commits
4 Commits
prerelease
...
no-circula
Author | SHA1 | Date | |
---|---|---|---|
![]() |
50396b41b4 | ||
![]() |
b4a2e2b82c | ||
![]() |
d3f8bf1b96 | ||
![]() |
fd5cf345e1 |
982
lib/spack/llnl/util/envmod.py
Normal file
982
lib/spack/llnl/util/envmod.py
Normal file
@@ -0,0 +1,982 @@
|
||||
# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
"""Utilities for setting and modifying environment variables."""
|
||||
import collections
|
||||
import contextlib
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
import llnl.util.executable as executable
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.path import path_to_os_path
|
||||
|
||||
is_windows = sys.platform == "win32"
|
||||
|
||||
system_paths = (
|
||||
["/", "/usr", "/usr/local"]
|
||||
if not is_windows
|
||||
else ["C:\\", "C:\\Program Files", "C:\\Program Files (x86)", "C:\\Users", "C:\\ProgramData"]
|
||||
)
|
||||
suffixes = ["bin", "bin64", "include", "lib", "lib64"] if not is_windows else []
|
||||
system_dirs = [os.path.join(p, s) for s in suffixes for p in system_paths] + system_paths
|
||||
|
||||
|
||||
def is_system_path(path):
|
||||
"""Predicate that given a path returns True if it is a system path,
|
||||
False otherwise.
|
||||
|
||||
Args:
|
||||
path (str): path to a directory
|
||||
|
||||
Returns:
|
||||
True or False
|
||||
"""
|
||||
return path and os.path.normpath(path) in system_dirs
|
||||
|
||||
|
||||
def filter_system_paths(paths):
|
||||
"""Return only paths that are not system paths."""
|
||||
return [p for p in paths if not is_system_path(p)]
|
||||
|
||||
|
||||
def deprioritize_system_paths(paths):
|
||||
"""Put system paths at the end of paths, otherwise preserving order."""
|
||||
filtered_paths = filter_system_paths(paths)
|
||||
fp = set(filtered_paths)
|
||||
return filtered_paths + [p for p in paths if p not in fp]
|
||||
|
||||
|
||||
_shell_set_strings = {
|
||||
"sh": "export {0}={1};\n",
|
||||
"csh": "setenv {0} {1};\n",
|
||||
"fish": "set -gx {0} {1};\n",
|
||||
"bat": 'set "{0}={1}"\n',
|
||||
}
|
||||
|
||||
|
||||
_shell_unset_strings = {
|
||||
"sh": "unset {0};\n",
|
||||
"csh": "unsetenv {0};\n",
|
||||
"fish": "set -e {0};\n",
|
||||
"bat": 'set "{0}="\n',
|
||||
}
|
||||
|
||||
|
||||
tracing_enabled = False
|
||||
|
||||
|
||||
def prune_duplicate_paths(paths):
|
||||
"""Returns the paths with duplicates removed, order preserved."""
|
||||
return list(llnl.util.lang.dedupe(paths))
|
||||
|
||||
|
||||
def get_path(name):
|
||||
path = os.environ.get(name, "").strip()
|
||||
if path:
|
||||
return path.split(os.pathsep)
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def env_flag(name):
|
||||
if name in os.environ:
|
||||
value = os.environ[name].lower()
|
||||
return value == "true" or value == "1"
|
||||
return False
|
||||
|
||||
|
||||
def path_set(var_name, directories):
|
||||
path_str = os.pathsep.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(os.pathsep)
|
||||
|
||||
for dir in directories:
|
||||
if dir in path:
|
||||
path.remove(dir)
|
||||
|
||||
new_path = tuple(directories) + tuple(path)
|
||||
path_set(var_name, new_path)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def set_env(**kwargs):
|
||||
"""Temporarily sets and restores environment variables.
|
||||
|
||||
Variables can be set as keyword arguments to this function.
|
||||
"""
|
||||
saved = {}
|
||||
for var, value in kwargs.items():
|
||||
if var in os.environ:
|
||||
saved[var] = os.environ[var]
|
||||
|
||||
if value is None:
|
||||
if var in os.environ:
|
||||
del os.environ[var]
|
||||
else:
|
||||
os.environ[var] = value
|
||||
|
||||
yield
|
||||
|
||||
for var, value in kwargs.items():
|
||||
if var in saved:
|
||||
os.environ[var] = saved[var]
|
||||
else:
|
||||
if var in os.environ:
|
||||
del os.environ[var]
|
||||
|
||||
|
||||
class NameModifier(object):
|
||||
def __init__(self, name, **kwargs):
|
||||
self.name = name
|
||||
self.separator = kwargs.get("separator", os.pathsep)
|
||||
self.args = {"name": name, "separator": self.separator}
|
||||
|
||||
self.args.update(kwargs)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, NameModifier):
|
||||
return False
|
||||
return self.name == other.name
|
||||
|
||||
def update_args(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
self.args.update(kwargs)
|
||||
|
||||
|
||||
class NameValueModifier(object):
|
||||
def __init__(self, name, value, **kwargs):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.separator = kwargs.get("separator", os.pathsep)
|
||||
self.args = {"name": name, "value": value, "separator": self.separator}
|
||||
self.args.update(kwargs)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, NameValueModifier):
|
||||
return False
|
||||
return (
|
||||
self.name == other.name
|
||||
and self.value == other.value
|
||||
and self.separator == other.separator
|
||||
)
|
||||
|
||||
def update_args(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
self.args.update(kwargs)
|
||||
|
||||
|
||||
class SetEnv(NameValueModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("SetEnv: {0}={1}".format(self.name, str(self.value)), level=3)
|
||||
env[self.name] = str(self.value)
|
||||
|
||||
|
||||
class AppendFlagsEnv(NameValueModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("AppendFlagsEnv: {0}={1}".format(self.name, str(self.value)), level=3)
|
||||
if self.name in env and env[self.name]:
|
||||
env[self.name] += self.separator + str(self.value)
|
||||
else:
|
||||
env[self.name] = str(self.value)
|
||||
|
||||
|
||||
class UnsetEnv(NameModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("UnsetEnv: {0}".format(self.name), level=3)
|
||||
# Avoid throwing if the variable was not set
|
||||
env.pop(self.name, None)
|
||||
|
||||
|
||||
class RemoveFlagsEnv(NameValueModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("RemoveFlagsEnv: {0}-{1}".format(self.name, str(self.value)), level=3)
|
||||
environment_value = env.get(self.name, "")
|
||||
flags = environment_value.split(self.separator) if environment_value else []
|
||||
flags = [f for f in flags if f != self.value]
|
||||
env[self.name] = self.separator.join(flags)
|
||||
|
||||
|
||||
class SetPath(NameValueModifier):
|
||||
def execute(self, env):
|
||||
string_path = concatenate_paths(self.value, separator=self.separator)
|
||||
tty.debug("SetPath: {0}={1}".format(self.name, string_path), level=3)
|
||||
env[self.name] = string_path
|
||||
|
||||
|
||||
class AppendPath(NameValueModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("AppendPath: {0}+{1}".format(self.name, str(self.value)), level=3)
|
||||
environment_value = env.get(self.name, "")
|
||||
directories = environment_value.split(self.separator) if environment_value else []
|
||||
directories.append(path_to_os_path(os.path.normpath(self.value)).pop())
|
||||
env[self.name] = self.separator.join(directories)
|
||||
|
||||
|
||||
class PrependPath(NameValueModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("PrependPath: {0}+{1}".format(self.name, str(self.value)), level=3)
|
||||
environment_value = env.get(self.name, "")
|
||||
directories = environment_value.split(self.separator) if environment_value else []
|
||||
directories = [path_to_os_path(os.path.normpath(self.value)).pop()] + directories
|
||||
env[self.name] = self.separator.join(directories)
|
||||
|
||||
|
||||
class RemovePath(NameValueModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("RemovePath: {0}-{1}".format(self.name, str(self.value)), level=3)
|
||||
environment_value = env.get(self.name, "")
|
||||
directories = environment_value.split(self.separator) if environment_value else []
|
||||
directories = [
|
||||
path_to_os_path(os.path.normpath(x)).pop()
|
||||
for x in directories
|
||||
if x != path_to_os_path(os.path.normpath(self.value)).pop()
|
||||
]
|
||||
env[self.name] = self.separator.join(directories)
|
||||
|
||||
|
||||
class DeprioritizeSystemPaths(NameModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("DeprioritizeSystemPaths: {0}".format(self.name), level=3)
|
||||
environment_value = env.get(self.name, "")
|
||||
directories = environment_value.split(self.separator) if environment_value else []
|
||||
directories = deprioritize_system_paths(
|
||||
[path_to_os_path(os.path.normpath(x)).pop() for x in directories]
|
||||
)
|
||||
env[self.name] = self.separator.join(directories)
|
||||
|
||||
|
||||
class PruneDuplicatePaths(NameModifier):
|
||||
def execute(self, env):
|
||||
tty.debug("PruneDuplicatePaths: {0}".format(self.name), level=3)
|
||||
environment_value = env.get(self.name, "")
|
||||
directories = environment_value.split(self.separator) if environment_value else []
|
||||
directories = prune_duplicate_paths(
|
||||
[path_to_os_path(os.path.normpath(x)).pop() for x in directories]
|
||||
)
|
||||
env[self.name] = self.separator.join(directories)
|
||||
|
||||
|
||||
class EnvironmentModifications(object):
|
||||
"""Keeps track of requests to modify the current environment.
|
||||
|
||||
Each call to a method to modify the environment stores the extra
|
||||
information on the caller in the request:
|
||||
|
||||
* 'filename' : filename of the module where the caller is defined
|
||||
* 'lineno': line number where the request occurred
|
||||
* 'context' : line of code that issued the request that failed
|
||||
"""
|
||||
|
||||
def __init__(self, other=None, traced=None):
|
||||
"""Initializes a new instance, copying commands from 'other'
|
||||
if it is not None.
|
||||
|
||||
Args:
|
||||
other (EnvironmentModifications): list of environment modifications
|
||||
to be extended (optional)
|
||||
traced (bool): enable or disable stack trace inspection to log the origin
|
||||
of the environment modifications.
|
||||
"""
|
||||
self.traced = tracing_enabled if traced is None else bool(traced)
|
||||
self.env_modifications = []
|
||||
if other is not None:
|
||||
self.extend(other)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.env_modifications)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.env_modifications)
|
||||
|
||||
def extend(self, other):
|
||||
self._check_other(other)
|
||||
self.env_modifications.extend(other.env_modifications)
|
||||
|
||||
@staticmethod
|
||||
def _check_other(other):
|
||||
if not isinstance(other, EnvironmentModifications):
|
||||
raise TypeError("other must be an instance of EnvironmentModifications")
|
||||
|
||||
def _maybe_trace(self, kwargs):
|
||||
"""Provide the modification with stack trace info so that we can track its
|
||||
origin to find issues in packages. This is very slow and expensive."""
|
||||
if not self.traced:
|
||||
return
|
||||
|
||||
stack = inspect.stack()
|
||||
try:
|
||||
_, filename, lineno, _, context, index = stack[2]
|
||||
context = context[index].strip()
|
||||
except Exception:
|
||||
filename = "unknown file"
|
||||
lineno = "unknown line"
|
||||
context = "unknown context"
|
||||
kwargs.update({"filename": filename, "lineno": lineno, "context": context})
|
||||
|
||||
def set(self, name, value, **kwargs):
|
||||
"""Stores a request to set an environment variable.
|
||||
|
||||
Args:
|
||||
name: name of the environment variable to be set
|
||||
value: value of the environment variable
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = SetEnv(name, value, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def append_flags(self, name, value, sep=" ", **kwargs):
|
||||
"""
|
||||
Stores in the current object a request to append to an env variable
|
||||
|
||||
Args:
|
||||
name: name of the environment variable to be appended to
|
||||
value: value to append to the environment variable
|
||||
Appends with spaces separating different additions to the variable
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
kwargs.update({"separator": sep})
|
||||
item = AppendFlagsEnv(name, value, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def unset(self, name, **kwargs):
|
||||
"""Stores a request to unset an environment variable.
|
||||
|
||||
Args:
|
||||
name: name of the environment variable to be unset
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = UnsetEnv(name, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def remove_flags(self, name, value, sep=" ", **kwargs):
|
||||
"""
|
||||
Stores in the current object a request to remove flags from an
|
||||
env variable
|
||||
|
||||
Args:
|
||||
name: name of the environment variable to be removed from
|
||||
value: value to remove to the environment variable
|
||||
sep: separator to assume for environment variable
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
kwargs.update({"separator": sep})
|
||||
item = RemoveFlagsEnv(name, value, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def set_path(self, name, elements, **kwargs):
|
||||
"""Stores a request to set a path generated from a list.
|
||||
|
||||
Args:
|
||||
name: name o the environment variable to be set.
|
||||
elements: elements of the path to set.
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = SetPath(name, elements, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def append_path(self, name, path, **kwargs):
|
||||
"""Stores a request to append a path to a path list.
|
||||
|
||||
Args:
|
||||
name: name of the path list in the environment
|
||||
path: path to be appended
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = AppendPath(name, path, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def prepend_path(self, name, path, **kwargs):
|
||||
"""Same as `append_path`, but the path is pre-pended.
|
||||
|
||||
Args:
|
||||
name: name of the path list in the environment
|
||||
path: path to be pre-pended
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = PrependPath(name, path, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def remove_path(self, name, path, **kwargs):
|
||||
"""Stores a request to remove a path from a path list.
|
||||
|
||||
Args:
|
||||
name: name of the path list in the environment
|
||||
path: path to be removed
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = RemovePath(name, path, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def deprioritize_system_paths(self, name, **kwargs):
|
||||
"""Stores a request to deprioritize system paths in a path list,
|
||||
otherwise preserving the order.
|
||||
|
||||
Args:
|
||||
name: name of the path list in the environment.
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = DeprioritizeSystemPaths(name, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def prune_duplicate_paths(self, name, **kwargs):
|
||||
"""Stores a request to remove duplicates from a path list, otherwise
|
||||
preserving the order.
|
||||
|
||||
Args:
|
||||
name: name of the path list in the environment.
|
||||
"""
|
||||
self._maybe_trace(kwargs)
|
||||
item = PruneDuplicatePaths(name, **kwargs)
|
||||
self.env_modifications.append(item)
|
||||
|
||||
def group_by_name(self):
|
||||
"""Returns a dict of the modifications grouped by variable name.
|
||||
|
||||
Returns:
|
||||
dict mapping the environment variable name to the modifications to
|
||||
be done on it
|
||||
"""
|
||||
modifications = collections.defaultdict(list)
|
||||
for item in self:
|
||||
modifications[item.name].append(item)
|
||||
return modifications
|
||||
|
||||
def is_unset(self, var_name):
|
||||
modifications = self.group_by_name()
|
||||
var_updates = modifications.get(var_name, None)
|
||||
if not var_updates:
|
||||
# We did not explicitly unset it
|
||||
return False
|
||||
|
||||
# The last modification must unset the variable for it to be considered
|
||||
# unset
|
||||
return type(var_updates[-1]) == UnsetEnv
|
||||
|
||||
def clear(self):
|
||||
"""
|
||||
Clears the current list of modifications
|
||||
"""
|
||||
self.env_modifications = []
|
||||
|
||||
def reversed(self):
|
||||
"""
|
||||
Returns the EnvironmentModifications object that will reverse self
|
||||
|
||||
Only creates reversals for additions to the environment, as reversing
|
||||
``unset`` and ``remove_path`` modifications is impossible.
|
||||
|
||||
Reversable operations are set(), prepend_path(), append_path(),
|
||||
set_path(), and append_flags().
|
||||
"""
|
||||
rev = EnvironmentModifications()
|
||||
|
||||
for envmod in reversed(self.env_modifications):
|
||||
if type(envmod) == SetEnv:
|
||||
tty.debug("Reversing `Set` environment operation may lose " "original value")
|
||||
rev.unset(envmod.name)
|
||||
elif type(envmod) == AppendPath:
|
||||
rev.remove_path(envmod.name, envmod.value)
|
||||
elif type(envmod) == PrependPath:
|
||||
rev.remove_path(envmod.name, envmod.value)
|
||||
elif type(envmod) == SetPath:
|
||||
tty.debug("Reversing `SetPath` environment operation may lose " "original value")
|
||||
rev.unset(envmod.name)
|
||||
elif type(envmod) == AppendFlagsEnv:
|
||||
rev.remove_flags(envmod.name, envmod.value)
|
||||
else:
|
||||
# This is an un-reversable operation
|
||||
tty.warn(
|
||||
"Skipping reversal of unreversable operation"
|
||||
"%s %s" % (type(envmod), envmod.name)
|
||||
)
|
||||
|
||||
return rev
|
||||
|
||||
def apply_modifications(self, env=None):
|
||||
"""Applies the modifications and clears the list."""
|
||||
# Use os.environ if not specified
|
||||
# Do not copy, we want to modify it in place
|
||||
if env is None:
|
||||
env = os.environ
|
||||
|
||||
modifications = self.group_by_name()
|
||||
# Apply modifications one variable at a time
|
||||
for name, actions in sorted(modifications.items()):
|
||||
for x in actions:
|
||||
x.execute(env)
|
||||
|
||||
def shell_modifications(self, shell="sh", explicit=False, env=None):
|
||||
"""Return shell code to apply the modifications and clears the list."""
|
||||
modifications = self.group_by_name()
|
||||
|
||||
if env is None:
|
||||
env = os.environ
|
||||
|
||||
new_env = env.copy()
|
||||
|
||||
for name, actions in sorted(modifications.items()):
|
||||
for x in actions:
|
||||
x.execute(new_env)
|
||||
|
||||
if "MANPATH" in new_env and not new_env.get("MANPATH").endswith(":"):
|
||||
new_env["MANPATH"] += ":"
|
||||
|
||||
cmds = ""
|
||||
|
||||
for name in sorted(set(modifications)):
|
||||
new = new_env.get(name, None)
|
||||
old = env.get(name, None)
|
||||
if explicit or new != old:
|
||||
if new is None:
|
||||
cmds += _shell_unset_strings[shell].format(name)
|
||||
else:
|
||||
if sys.platform != "win32":
|
||||
cmd = _shell_set_strings[shell].format(name, shlex.quote(new_env[name]))
|
||||
else:
|
||||
cmd = _shell_set_strings[shell].format(name, new_env[name])
|
||||
cmds += cmd
|
||||
return cmds
|
||||
|
||||
@staticmethod
|
||||
def from_sourcing_file(filename, *arguments, **kwargs):
|
||||
"""Constructs an instance of a
|
||||
:py:class:`llnl.util.envmod.EnvironmentModifications` object
|
||||
that has the same effect as sourcing a file.
|
||||
|
||||
Args:
|
||||
filename (str): the file to be sourced
|
||||
*arguments (list): arguments to pass on the command line
|
||||
|
||||
Keyword Args:
|
||||
shell (str): the shell to use (default: ``bash``)
|
||||
shell_options (str): options passed to the shell (default: ``-c``)
|
||||
source_command (str): the command to run (default: ``source``)
|
||||
suppress_output (str): redirect used to suppress output of command
|
||||
(default: ``&> /dev/null``)
|
||||
concatenate_on_success (str): operator used to execute a command
|
||||
only when the previous command succeeds (default: ``&&``)
|
||||
exclude ([str or re]): ignore any modifications of these
|
||||
variables (default: [])
|
||||
include ([str or re]): always respect modifications of these
|
||||
variables (default: []). Supersedes any excluded variables.
|
||||
clean (bool): in addition to removing empty entries,
|
||||
also remove duplicate entries (default: False).
|
||||
"""
|
||||
tty.debug("EnvironmentModifications.from_sourcing_file: {0}".format(filename))
|
||||
# Check if the file actually exists
|
||||
if not os.path.isfile(filename):
|
||||
msg = "Trying to source non-existing file: {0}".format(filename)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
# Prepare include and exclude lists of environment variable names
|
||||
exclude = kwargs.get("exclude", [])
|
||||
include = kwargs.get("include", [])
|
||||
clean = kwargs.get("clean", False)
|
||||
|
||||
# Other variables unrelated to sourcing a file
|
||||
exclude.extend(
|
||||
[
|
||||
# Bash internals
|
||||
"SHLVL",
|
||||
"_",
|
||||
"PWD",
|
||||
"OLDPWD",
|
||||
"PS1",
|
||||
"PS2",
|
||||
"ENV",
|
||||
# Environment modules v4
|
||||
"LOADEDMODULES",
|
||||
"_LMFILES_",
|
||||
"BASH_FUNC_module()",
|
||||
"MODULEPATH",
|
||||
"MODULES_(.*)",
|
||||
r"(\w*)_mod(quar|share)",
|
||||
# Lmod configuration
|
||||
r"LMOD_(.*)",
|
||||
"MODULERCFILE",
|
||||
]
|
||||
)
|
||||
|
||||
# Compute the environments before and after sourcing
|
||||
before = sanitize(
|
||||
environment_after_sourcing_files(os.devnull, **kwargs),
|
||||
exclude=exclude,
|
||||
include=include,
|
||||
)
|
||||
file_and_args = (filename,) + arguments
|
||||
after = sanitize(
|
||||
environment_after_sourcing_files(file_and_args, **kwargs),
|
||||
exclude=exclude,
|
||||
include=include,
|
||||
)
|
||||
|
||||
# Delegate to the other factory
|
||||
return EnvironmentModifications.from_environment_diff(before, after, clean)
|
||||
|
||||
@staticmethod
|
||||
def from_environment_diff(before, after, clean=False):
|
||||
"""Constructs an instance of a
|
||||
:py:class:`llnl.util.envmod.EnvironmentModifications` object
|
||||
from the diff of two dictionaries.
|
||||
|
||||
Args:
|
||||
before (dict): environment before the modifications are applied
|
||||
after (dict): environment after the modifications are applied
|
||||
clean (bool): in addition to removing empty entries, also remove
|
||||
duplicate entries
|
||||
"""
|
||||
# Fill the EnvironmentModifications instance
|
||||
env = EnvironmentModifications()
|
||||
# New variables
|
||||
new_variables = list(set(after) - set(before))
|
||||
# Variables that have been unset
|
||||
unset_variables = list(set(before) - set(after))
|
||||
# Variables that have been modified
|
||||
common_variables = set(before).intersection(set(after))
|
||||
modified_variables = [x for x in common_variables if before[x] != after[x]]
|
||||
# Consistent output order - looks nicer, easier comparison...
|
||||
new_variables.sort()
|
||||
unset_variables.sort()
|
||||
modified_variables.sort()
|
||||
|
||||
def return_separator_if_any(*args):
|
||||
separators = ":", ";"
|
||||
for separator in separators:
|
||||
for arg in args:
|
||||
if separator in arg:
|
||||
return separator
|
||||
return None
|
||||
|
||||
# Add variables to env.
|
||||
# Assume that variables with 'PATH' in the name or that contain
|
||||
# separators like ':' or ';' are more likely to be paths
|
||||
for x in new_variables:
|
||||
sep = return_separator_if_any(after[x])
|
||||
if sep:
|
||||
env.prepend_path(x, after[x], separator=sep)
|
||||
elif "PATH" in x:
|
||||
env.prepend_path(x, after[x])
|
||||
else:
|
||||
# We just need to set the variable to the new value
|
||||
env.set(x, after[x])
|
||||
|
||||
for x in unset_variables:
|
||||
env.unset(x)
|
||||
|
||||
for x in modified_variables:
|
||||
value_before = before[x]
|
||||
value_after = after[x]
|
||||
sep = return_separator_if_any(value_before, value_after)
|
||||
if sep:
|
||||
before_list = value_before.split(sep)
|
||||
after_list = value_after.split(sep)
|
||||
|
||||
# Filter out empty strings
|
||||
before_list = list(filter(None, before_list))
|
||||
after_list = list(filter(None, after_list))
|
||||
|
||||
# Remove duplicate entries (worse matching, bloats env)
|
||||
if clean:
|
||||
before_list = list(llnl.util.lang.dedupe(before_list))
|
||||
after_list = list(llnl.util.lang.dedupe(after_list))
|
||||
# The reassembled cleaned entries
|
||||
value_before = sep.join(before_list)
|
||||
value_after = sep.join(after_list)
|
||||
|
||||
# Paths that have been removed
|
||||
remove_list = [ii for ii in before_list if ii not in after_list]
|
||||
# Check that nothing has been added in the middle of
|
||||
# before_list
|
||||
remaining_list = [ii for ii in before_list if ii in after_list]
|
||||
try:
|
||||
start = after_list.index(remaining_list[0])
|
||||
end = after_list.index(remaining_list[-1])
|
||||
search = sep.join(after_list[start : end + 1])
|
||||
except IndexError:
|
||||
env.prepend_path(x, value_after)
|
||||
continue
|
||||
|
||||
if search not in value_before:
|
||||
# We just need to set the variable to the new value
|
||||
env.prepend_path(x, value_after)
|
||||
else:
|
||||
try:
|
||||
prepend_list = after_list[:start]
|
||||
prepend_list.reverse() # Preserve order after prepend
|
||||
except KeyError:
|
||||
prepend_list = []
|
||||
try:
|
||||
append_list = after_list[end + 1 :]
|
||||
except KeyError:
|
||||
append_list = []
|
||||
|
||||
for item in remove_list:
|
||||
env.remove_path(x, item)
|
||||
for item in append_list:
|
||||
env.append_path(x, item)
|
||||
for item in prepend_list:
|
||||
env.prepend_path(x, item)
|
||||
else:
|
||||
# We just need to set the variable to the new value
|
||||
env.set(x, value_after)
|
||||
|
||||
return env
|
||||
|
||||
|
||||
def concatenate_paths(paths, separator=os.pathsep):
|
||||
"""Concatenates an iterable of paths into a string of paths separated by
|
||||
separator, defaulting to colon.
|
||||
|
||||
Args:
|
||||
paths: iterable of paths
|
||||
separator: the separator to use, default ';' windows, ':' otherwise
|
||||
|
||||
Returns:
|
||||
string
|
||||
"""
|
||||
return separator.join(str(item) for item in paths)
|
||||
|
||||
|
||||
def set_or_unset_not_first(variable, changes, errstream):
|
||||
"""Check if we are going to set or unset something after other
|
||||
modifications have already been requested.
|
||||
"""
|
||||
indexes = [
|
||||
ii
|
||||
for ii, item in enumerate(changes)
|
||||
if ii != 0 and not item.args.get("force", False) and type(item) in [SetEnv, UnsetEnv]
|
||||
]
|
||||
if indexes:
|
||||
good = "\t \t{context} at {filename}:{lineno}"
|
||||
nogood = "\t--->\t{context} at {filename}:{lineno}"
|
||||
message = "Suspicious requests to set or unset '{var}' found"
|
||||
errstream(message.format(var=variable))
|
||||
for ii, item in enumerate(changes):
|
||||
print_format = nogood if ii in indexes else good
|
||||
errstream(print_format.format(**item.args))
|
||||
|
||||
|
||||
def validate(env, errstream):
|
||||
"""Validates the environment modifications to check for the presence of
|
||||
suspicious patterns. Prompts a warning for everything that was found.
|
||||
|
||||
Current checks:
|
||||
- set or unset variables after other changes on the same variable
|
||||
|
||||
Args:
|
||||
env: list of environment modifications
|
||||
"""
|
||||
if not env.traced:
|
||||
return
|
||||
modifications = env.group_by_name()
|
||||
for variable, list_of_changes in sorted(modifications.items()):
|
||||
set_or_unset_not_first(variable, list_of_changes, errstream)
|
||||
|
||||
|
||||
def inspect_path(root, inspections, exclude=None):
|
||||
"""Inspects ``root`` to search for the subdirectories in ``inspections``.
|
||||
Adds every path found to a list of prepend-path commands and returns it.
|
||||
|
||||
Args:
|
||||
root (str): absolute path where to search for subdirectories
|
||||
|
||||
inspections (dict): maps relative paths to a list of environment
|
||||
variables that will be modified if the path exists. The
|
||||
modifications are not performed immediately, but stored in a
|
||||
command object that is returned to client
|
||||
|
||||
exclude (typing.Callable): optional callable. If present it must accept an
|
||||
absolute path and return True if it should be excluded from the
|
||||
inspection
|
||||
|
||||
Examples:
|
||||
|
||||
The following lines execute an inspection in ``/usr`` to search for
|
||||
``/usr/include`` and ``/usr/lib64``. If found we want to prepend
|
||||
``/usr/include`` to ``CPATH`` and ``/usr/lib64`` to ``MY_LIB64_PATH``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Set up the dictionary containing the inspection
|
||||
inspections = {
|
||||
'include': ['CPATH'],
|
||||
'lib64': ['MY_LIB64_PATH']
|
||||
}
|
||||
|
||||
# Get back the list of command needed to modify the environment
|
||||
env = inspect_path('/usr', inspections)
|
||||
|
||||
# Eventually execute the commands
|
||||
env.apply_modifications()
|
||||
|
||||
Returns:
|
||||
instance of EnvironmentModifications containing the requested
|
||||
modifications
|
||||
"""
|
||||
if exclude is None:
|
||||
exclude = lambda x: False
|
||||
|
||||
env = EnvironmentModifications()
|
||||
# Inspect the prefix to check for the existence of common directories
|
||||
for relative_path, variables in inspections.items():
|
||||
expected = os.path.join(root, relative_path)
|
||||
|
||||
if os.path.isdir(expected) and not exclude(expected):
|
||||
for variable in variables:
|
||||
env.prepend_path(variable, expected)
|
||||
|
||||
return env
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def preserve_environment(*variables):
|
||||
"""Ensures that the value of the environment variables passed as
|
||||
arguments is the same before entering to the context manager and after
|
||||
exiting it.
|
||||
|
||||
Variables that are unset before entering the context manager will be
|
||||
explicitly unset on exit.
|
||||
|
||||
Args:
|
||||
variables (list): list of environment variables to be preserved
|
||||
"""
|
||||
cache = {}
|
||||
for var in variables:
|
||||
# The environment variable to be preserved might not be there.
|
||||
# In that case store None as a placeholder.
|
||||
cache[var] = os.environ.get(var, None)
|
||||
|
||||
yield
|
||||
|
||||
for var in variables:
|
||||
value = cache[var]
|
||||
msg = "[PRESERVE_ENVIRONMENT]"
|
||||
if value is not None:
|
||||
# Print a debug statement if the value changed
|
||||
if var not in os.environ:
|
||||
msg += ' {0} was unset, will be reset to "{1}"'
|
||||
tty.debug(msg.format(var, value))
|
||||
elif os.environ[var] != value:
|
||||
msg += ' {0} was set to "{1}", will be reset to "{2}"'
|
||||
tty.debug(msg.format(var, os.environ[var], value))
|
||||
os.environ[var] = value
|
||||
elif var in os.environ:
|
||||
msg += ' {0} was set to "{1}", will be unset'
|
||||
tty.debug(msg.format(var, os.environ[var]))
|
||||
del os.environ[var]
|
||||
|
||||
|
||||
def environment_after_sourcing_files(*files, **kwargs):
|
||||
"""Returns a dictionary with the environment that one would have
|
||||
after sourcing the files passed as argument.
|
||||
|
||||
Args:
|
||||
*files: each item can either be a string containing the path
|
||||
of the file to be sourced or a sequence, where the first element
|
||||
is the file to be sourced and the remaining are arguments to be
|
||||
passed to the command line
|
||||
|
||||
Keyword Args:
|
||||
env (dict): the initial environment (default: current environment)
|
||||
shell (str): the shell to use (default: ``/bin/bash``)
|
||||
shell_options (str): options passed to the shell (default: ``-c``)
|
||||
source_command (str): the command to run (default: ``source``)
|
||||
suppress_output (str): redirect used to suppress output of command
|
||||
(default: ``&> /dev/null``)
|
||||
concatenate_on_success (str): operator used to execute a command
|
||||
only when the previous command succeeds (default: ``&&``)
|
||||
"""
|
||||
# Set the shell executable that will be used to source files
|
||||
shell_cmd = kwargs.get("shell", "/bin/bash")
|
||||
shell_options = kwargs.get("shell_options", "-c")
|
||||
source_command = kwargs.get("source_command", "source")
|
||||
suppress_output = kwargs.get("suppress_output", "&> /dev/null")
|
||||
concatenate_on_success = kwargs.get("concatenate_on_success", "&&")
|
||||
|
||||
shell = executable.Executable(" ".join([shell_cmd, shell_options]))
|
||||
|
||||
def _source_single_file(file_and_args, environment):
|
||||
source_file = [source_command]
|
||||
source_file.extend(x for x in file_and_args)
|
||||
source_file = " ".join(source_file)
|
||||
|
||||
# If the environment contains 'python' use it, if not
|
||||
# go with sys.executable. Below we just need a working
|
||||
# Python interpreter, not necessarily sys.executable.
|
||||
python_cmd = executable.which("python3", "python", "python2")
|
||||
python_cmd = python_cmd.path if python_cmd else sys.executable
|
||||
|
||||
dump_cmd = "import os, json; print(json.dumps(dict(os.environ)))"
|
||||
dump_environment = python_cmd + ' -E -c "{0}"'.format(dump_cmd)
|
||||
|
||||
# Try to source the file
|
||||
source_file_arguments = " ".join(
|
||||
[
|
||||
source_file,
|
||||
suppress_output,
|
||||
concatenate_on_success,
|
||||
dump_environment,
|
||||
]
|
||||
)
|
||||
output = shell(source_file_arguments, output=str, env=environment, ignore_quotes=True)
|
||||
return json.loads(output)
|
||||
|
||||
current_environment = kwargs.get("env", dict(os.environ))
|
||||
for f in files:
|
||||
# Normalize the input to the helper function
|
||||
if isinstance(f, str):
|
||||
f = [f]
|
||||
|
||||
current_environment = _source_single_file(f, environment=current_environment)
|
||||
|
||||
return current_environment
|
||||
|
||||
|
||||
def sanitize(environment, exclude, include):
|
||||
"""Returns a copy of the input dictionary where all the keys that
|
||||
match an excluded pattern and don't match an included pattern are
|
||||
removed.
|
||||
|
||||
Args:
|
||||
environment (dict): input dictionary
|
||||
exclude (list): literals or regex patterns to be excluded
|
||||
include (list): literals or regex patterns to be included
|
||||
"""
|
||||
|
||||
def set_intersection(fullset, *args):
|
||||
# A set intersection using string literals and regexs
|
||||
meta = "[" + re.escape("[$()*?[]^{|}") + "]"
|
||||
subset = fullset & set(args) # As literal
|
||||
for name in args:
|
||||
if re.search(meta, name):
|
||||
pattern = re.compile(name)
|
||||
for k in fullset:
|
||||
if re.match(pattern, k):
|
||||
subset.add(k)
|
||||
return subset
|
||||
|
||||
# Don't modify input, make a copy instead
|
||||
environment = dict(environment)
|
||||
|
||||
# include supersedes any excluded items
|
||||
prune = set_intersection(set(environment), *exclude)
|
||||
prune -= set_intersection(prune, *include)
|
||||
for k in prune:
|
||||
environment.pop(k, None)
|
||||
|
||||
return environment
|
@@ -8,11 +8,10 @@
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import List, Optional, Union
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.error
|
||||
from spack.util.path import Path, format_os_path, path_to_os_path, system_path_filter
|
||||
from llnl.util.path import Path, format_os_path, path_to_os_path, system_path_filter
|
||||
|
||||
__all__ = ["Executable", "which", "ProcessError"]
|
||||
|
||||
@@ -27,13 +26,20 @@ def __init__(self, name):
|
||||
# filter back to platform dependent path
|
||||
self.exe = path_to_os_path(*self.exe)
|
||||
self.default_env = {}
|
||||
from spack.util.environment import EnvironmentModifications # no cycle
|
||||
|
||||
self.default_envmod = EnvironmentModifications()
|
||||
self._default_envmod = None
|
||||
self.returncode = None
|
||||
|
||||
if not self.exe:
|
||||
raise ProcessError("Cannot construct executable for '%s'" % name)
|
||||
raise ProcessError(f"Cannot construct executable for '{name}'")
|
||||
|
||||
@property
|
||||
def default_envmod(self):
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
|
||||
if self._default_envmod is None:
|
||||
self._default_envmod = EnvironmentModifications()
|
||||
|
||||
return self._default_envmod
|
||||
|
||||
@system_path_filter
|
||||
def add_default_arg(self, arg):
|
||||
@@ -122,6 +128,8 @@ def __call__(self, *args, **kwargs):
|
||||
By default, the subprocess inherits the parent's file descriptors.
|
||||
|
||||
"""
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
|
||||
# Environment
|
||||
env_arg = kwargs.get("env", None)
|
||||
|
||||
@@ -130,8 +138,6 @@ def __call__(self, *args, **kwargs):
|
||||
self.default_envmod.apply_modifications(env)
|
||||
env.update(self.default_env)
|
||||
|
||||
from spack.util.environment import EnvironmentModifications # no cycle
|
||||
|
||||
# Apply env argument
|
||||
if isinstance(env_arg, EnvironmentModifications):
|
||||
env_arg.apply_modifications(env)
|
||||
@@ -227,27 +233,26 @@ def streamify(arg, mode):
|
||||
|
||||
rc = self.returncode = proc.returncode
|
||||
if fail_on_error and rc != 0 and (rc not in ignore_errors):
|
||||
long_msg = cmd_line_string
|
||||
msg = f"Command {cmd_line_string} exited with status {proc.returncode}."
|
||||
if result:
|
||||
# If the output is not captured in the result, it will have
|
||||
# been stored either in the specified files (e.g. if
|
||||
# 'output' specifies a file) or written to the parent's
|
||||
# stdout/stderr (e.g. if 'output' is not specified)
|
||||
long_msg += "\n" + result
|
||||
msg += "\n" + result
|
||||
|
||||
raise ProcessError("Command exited with status %d:" % proc.returncode, long_msg)
|
||||
raise ProcessError(msg)
|
||||
|
||||
return result
|
||||
|
||||
except OSError as e:
|
||||
raise ProcessError("%s: %s" % (self.exe[0], e.strerror), "Command: " + cmd_line_string)
|
||||
raise ProcessError(f"{self.exe[0]}: {e.strerror}\n Command: '{cmd_line_string}'")
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
if fail_on_error:
|
||||
raise ProcessError(
|
||||
str(e),
|
||||
"\nExit status %d when invoking command: %s"
|
||||
% (proc.returncode, cmd_line_string),
|
||||
f"{str(e)}\n"
|
||||
f" Exit status {proc.returncode} when invoking command: '{cmd_line_string}'"
|
||||
)
|
||||
|
||||
finally:
|
||||
@@ -275,16 +280,31 @@ def __str__(self):
|
||||
|
||||
|
||||
@system_path_filter
|
||||
def which_string(*args, **kwargs):
|
||||
"""Like ``which()``, but return a string instead of an ``Executable``."""
|
||||
path = kwargs.get("path", os.environ.get("PATH", ""))
|
||||
required = kwargs.get("required", False)
|
||||
def which_string(*args: str, path: Optional[Union[List[str], str]] = None, required: bool = False):
|
||||
"""Finds an executable in the path like command-line which.
|
||||
|
||||
If given multiple executables, returns the first one that is found.
|
||||
If no executables are found, returns None.
|
||||
|
||||
Parameters:
|
||||
*args: One or more executables to search for
|
||||
|
||||
Keyword Arguments:
|
||||
path: colon-separated (semicolon-separated on windows) string or list of
|
||||
paths to search. Defaults to ``os.environ["PATH"]``
|
||||
required: If set to ``True``, raise an error if executable not found
|
||||
|
||||
Returns:
|
||||
Absolute path of the first executable found.
|
||||
"""
|
||||
if path is None:
|
||||
path = os.environ.get("PATH") or ""
|
||||
|
||||
if isinstance(path, str):
|
||||
path = path.split(os.pathsep)
|
||||
|
||||
for name in args:
|
||||
win_candidates = []
|
||||
win_candidates: List[str] = []
|
||||
if sys.platform == "win32" and (not name.endswith(".exe") and not name.endswith(".bat")):
|
||||
win_candidates = [name + ext for ext in [".exe", ".bat"]]
|
||||
candidate_names = [name] if not win_candidates else win_candidates
|
||||
@@ -309,19 +329,19 @@ def which_string(*args, **kwargs):
|
||||
return exe
|
||||
|
||||
if required:
|
||||
raise CommandNotFoundError("spack requires '%s'. Make sure it is in your path." % args[0])
|
||||
raise CommandNotFoundError(args[0])
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def which(*args, **kwargs):
|
||||
def which(*args: str, path: Optional[Union[List[str], str]] = None, required: bool = False):
|
||||
"""Finds an executable in the path like command-line which.
|
||||
|
||||
If given multiple executables, returns the first one that is found.
|
||||
If no executables are found, returns None.
|
||||
|
||||
Parameters:
|
||||
*args (str): One or more executables to search for
|
||||
*args: One or more executables to search for
|
||||
|
||||
Keyword Arguments:
|
||||
path (list or str): The path to search. Defaults to ``PATH``
|
||||
@@ -330,13 +350,17 @@ def which(*args, **kwargs):
|
||||
Returns:
|
||||
Executable: The first executable that is found in the path
|
||||
"""
|
||||
exe = which_string(*args, **kwargs)
|
||||
exe = which_string(*args, path=path, required=required)
|
||||
return Executable(shlex.quote(exe)) if exe else None
|
||||
|
||||
|
||||
class ProcessError(spack.error.SpackError):
|
||||
class ProcessError(Exception):
|
||||
"""ProcessErrors are raised when Executables exit with an error code."""
|
||||
|
||||
|
||||
class CommandNotFoundError(spack.error.SpackError):
|
||||
class CommandNotFoundError(Exception):
|
||||
"""Raised when ``which()`` can't find a required executable."""
|
||||
|
||||
def __init__(self, command: str):
|
||||
super().__init__(f"Couldn't find command '{command}'. Make sure it is in your path.")
|
||||
self.command = command
|
@@ -19,12 +19,11 @@
|
||||
from sys import platform as _platform
|
||||
|
||||
from llnl.util import tty
|
||||
from llnl.util.executable import CommandNotFoundError, Executable, which
|
||||
from llnl.util.lang import dedupe, memoized
|
||||
from llnl.util.path import path_to_os_path, system_path_filter
|
||||
from llnl.util.symlink import islink, symlink
|
||||
|
||||
from spack.util.executable import CommandNotFoundError, Executable, which
|
||||
from spack.util.path import path_to_os_path, system_path_filter
|
||||
|
||||
is_windows = _platform == "win32"
|
||||
|
||||
if not is_windows:
|
||||
|
@@ -10,11 +10,10 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
import llnl.util.string
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.lang import pretty_seconds
|
||||
|
||||
import spack.util.string
|
||||
|
||||
if sys.platform != "win32":
|
||||
import fcntl
|
||||
|
||||
@@ -165,7 +164,7 @@ def _attempts_str(wait_time, nattempts):
|
||||
if nattempts <= 1:
|
||||
return ""
|
||||
|
||||
attempts = spack.util.string.plural(nattempts, "attempt")
|
||||
attempts = llnl.util.string.plural(nattempts, "attempt")
|
||||
return " after {} and {}".format(pretty_seconds(wait_time), attempts)
|
||||
|
||||
|
||||
|
159
lib/spack/llnl/util/path.py
Normal file
159
lib/spack/llnl/util/path.py
Normal file
@@ -0,0 +1,159 @@
|
||||
# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
"""Utilities for managing Linux and Windows paths."""
|
||||
|
||||
# TODO: look at using pathlib since we now only support Python 3
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from urllib.parse import urlparse
|
||||
|
||||
is_windows = sys.platform == "win32"
|
||||
|
||||
|
||||
def is_path_url(path):
|
||||
if "\\" in path:
|
||||
return False
|
||||
url_tuple = urlparse(path)
|
||||
return bool(url_tuple.scheme) and len(url_tuple.scheme) > 1
|
||||
|
||||
|
||||
def win_exe_ext():
|
||||
return ".exe"
|
||||
|
||||
|
||||
def path_to_os_path(*pths):
|
||||
"""
|
||||
Takes an arbitrary number of positional parameters
|
||||
converts each arguemnt of type string to use a normalized
|
||||
filepath separator, and returns a list of all values
|
||||
"""
|
||||
ret_pths = []
|
||||
for pth in pths:
|
||||
if isinstance(pth, str) and not is_path_url(pth):
|
||||
pth = convert_to_platform_path(pth)
|
||||
ret_pths.append(pth)
|
||||
return ret_pths
|
||||
|
||||
|
||||
def sanitize_file_path(pth):
|
||||
"""
|
||||
Formats strings to contain only characters that can
|
||||
be used to generate legal file paths.
|
||||
|
||||
Criteria for legal files based on
|
||||
https://en.wikipedia.org/wiki/Filename#Comparison_of_filename_limitations
|
||||
|
||||
Args:
|
||||
pth: string containing path to be created
|
||||
on the host filesystem
|
||||
|
||||
Return:
|
||||
sanitized string that can legally be made into a path
|
||||
"""
|
||||
# on unix, splitting path by seperators will remove
|
||||
# instances of illegal characters on join
|
||||
pth_cmpnts = pth.split(os.path.sep)
|
||||
|
||||
if is_windows:
|
||||
drive_match = r"[a-zA-Z]:"
|
||||
is_abs = bool(re.match(drive_match, pth_cmpnts[0]))
|
||||
drive = pth_cmpnts[0] + os.path.sep if is_abs else ""
|
||||
pth_cmpnts = pth_cmpnts[1:] if drive else pth_cmpnts
|
||||
illegal_chars = r'[<>?:"|*\\]'
|
||||
else:
|
||||
drive = "/" if not pth_cmpnts[0] else ""
|
||||
illegal_chars = r"[/]"
|
||||
|
||||
pth = []
|
||||
for cmp in pth_cmpnts:
|
||||
san_cmp = re.sub(illegal_chars, "", cmp)
|
||||
pth.append(san_cmp)
|
||||
return drive + os.path.join(*pth)
|
||||
|
||||
|
||||
def system_path_filter(_func=None, arg_slice=None):
|
||||
"""
|
||||
Filters function arguments to account for platform path separators.
|
||||
Optional slicing range can be specified to select specific arguments
|
||||
|
||||
This decorator takes all (or a slice) of a method's positional arguments
|
||||
and normalizes usage of filepath separators on a per platform basis.
|
||||
|
||||
Note: **kwargs, urls, and any type that is not a string are ignored
|
||||
so in such cases where path normalization is required, that should be
|
||||
handled by calling path_to_os_path directly as needed.
|
||||
|
||||
Parameters:
|
||||
arg_slice (slice): a slice object specifying the slice of arguments
|
||||
in the decorated method over which filepath separators are
|
||||
normalized
|
||||
"""
|
||||
from functools import wraps
|
||||
|
||||
def holder_func(func):
|
||||
@wraps(func)
|
||||
def path_filter_caller(*args, **kwargs):
|
||||
args = list(args)
|
||||
if arg_slice:
|
||||
args[arg_slice] = path_to_os_path(*args[arg_slice])
|
||||
else:
|
||||
args = path_to_os_path(*args)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return path_filter_caller
|
||||
|
||||
if _func:
|
||||
return holder_func(_func)
|
||||
return holder_func
|
||||
|
||||
|
||||
class Path:
|
||||
"""
|
||||
Describes the filepath separator types
|
||||
in an enum style
|
||||
with a helper attribute
|
||||
exposing the path type of
|
||||
the current platform.
|
||||
"""
|
||||
|
||||
unix = 0
|
||||
windows = 1
|
||||
platform_path = windows if is_windows else unix
|
||||
|
||||
|
||||
def format_os_path(path, mode=Path.unix):
|
||||
"""
|
||||
Format path to use consistent, platform specific
|
||||
separators. Absolute paths are converted between
|
||||
drive letters and a prepended '/' as per platform
|
||||
requirement.
|
||||
|
||||
Parameters:
|
||||
path (str): the path to be normalized, must be a string
|
||||
or expose the replace method.
|
||||
mode (Path): the path filesperator style to normalize the
|
||||
passed path to. Default is unix style, i.e. '/'
|
||||
"""
|
||||
if not path:
|
||||
return path
|
||||
if mode == Path.windows:
|
||||
path = path.replace("/", "\\")
|
||||
else:
|
||||
path = path.replace("\\", "/")
|
||||
return path
|
||||
|
||||
|
||||
def convert_to_posix_path(path):
|
||||
return format_os_path(path, mode=Path.unix)
|
||||
|
||||
|
||||
def convert_to_windows_path(path):
|
||||
return format_os_path(path, mode=Path.windows)
|
||||
|
||||
|
||||
def convert_to_platform_path(path):
|
||||
return format_os_path(path, mode=Path.platform_path)
|
@@ -24,8 +24,7 @@
|
||||
import traceback
|
||||
|
||||
import llnl.util.tty.log as log
|
||||
|
||||
from spack.util.executable import which
|
||||
from llnl.util.executable import which
|
||||
|
||||
termios = None
|
||||
try:
|
||||
|
@@ -5,12 +5,12 @@
|
||||
|
||||
import os
|
||||
|
||||
from llnl.util.executable import Executable, ProcessError
|
||||
from llnl.util.lang import memoized
|
||||
|
||||
import spack.spec
|
||||
from spack.compilers.clang import Clang
|
||||
from spack.spec import CompilerSpec
|
||||
from spack.util.executable import Executable, ProcessError
|
||||
|
||||
|
||||
class ABI(object):
|
||||
|
@@ -28,6 +28,7 @@
|
||||
import llnl.util.filesystem as fsys
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import BaseDirectoryVisitor, mkdirp, visit_directory_tree
|
||||
|
||||
import spack.cmd
|
||||
@@ -42,6 +43,7 @@
|
||||
import spack.store
|
||||
import spack.util.file_cache as file_cache
|
||||
import spack.util.gpg
|
||||
import spack.util.path
|
||||
import spack.util.spack_json as sjson
|
||||
import spack.util.spack_yaml as syaml
|
||||
import spack.util.url as url_util
|
||||
@@ -50,7 +52,6 @@
|
||||
from spack.relocate import utf8_paths_to_single_binary_regex
|
||||
from spack.spec import Spec
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
|
||||
_build_cache_relative_path = "build_cache"
|
||||
_build_cache_keys_relative_path = "_pgp"
|
||||
|
@@ -12,12 +12,12 @@
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.executable
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util import tty
|
||||
|
||||
import spack.store
|
||||
import spack.util.environment
|
||||
import spack.util.executable
|
||||
|
||||
from .config import spec_for_current_python
|
||||
|
||||
@@ -186,11 +186,11 @@ def _executables_in_store(executables, query_spec, query_info=None):
|
||||
if (
|
||||
os.path.exists(bin_dir)
|
||||
and os.path.isdir(bin_dir)
|
||||
and spack.util.executable.which_string(*executables, path=bin_dir)
|
||||
and llnl.util.executable.which_string(*executables, path=bin_dir)
|
||||
):
|
||||
spack.util.environment.path_put_first("PATH", [bin_dir])
|
||||
llnl.util.envmod.path_put_first("PATH", [bin_dir])
|
||||
if query_info is not None:
|
||||
query_info["command"] = spack.util.executable.which(*executables, path=bin_dir)
|
||||
query_info["command"] = llnl.util.executable.which(*executables, path=bin_dir)
|
||||
query_info["spec"] = concrete_spec
|
||||
return True
|
||||
return False
|
||||
|
@@ -31,6 +31,8 @@
|
||||
import uuid
|
||||
from typing import Callable, List, Optional
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.executable
|
||||
from llnl.util import tty
|
||||
from llnl.util.lang import GroupedExceptionHandler
|
||||
|
||||
@@ -46,8 +48,6 @@
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.user_environment
|
||||
import spack.util.environment
|
||||
import spack.util.executable
|
||||
import spack.util.path
|
||||
import spack.util.spack_yaml
|
||||
import spack.util.url
|
||||
@@ -399,7 +399,7 @@ def ensure_module_importable_or_raise(module: str, abstract_spec: Optional[str]
|
||||
def ensure_executables_in_path_or_raise(
|
||||
executables: list,
|
||||
abstract_spec: str,
|
||||
cmd_check: Optional[Callable[[spack.util.executable.Executable], bool]] = None,
|
||||
cmd_check: Optional[Callable[[llnl.util.executable.Executable], bool]] = None,
|
||||
):
|
||||
"""Ensure that some executables are in path or raise.
|
||||
|
||||
@@ -408,7 +408,7 @@ def ensure_executables_in_path_or_raise(
|
||||
in order. The function exits on the first one found.
|
||||
abstract_spec (str): abstract spec that provides the executables
|
||||
cmd_check (object): callable predicate that takes a
|
||||
``spack.util.executable.Executable`` command and validate it. Should return
|
||||
``llnl.util.executable.Executable`` command and validate it. Should return
|
||||
``True`` if the executable is acceptable, ``False`` otherwise.
|
||||
Can be used to, e.g., ensure a suitable version of the command before
|
||||
accepting for bootstrapping.
|
||||
@@ -420,7 +420,7 @@ def ensure_executables_in_path_or_raise(
|
||||
Executable object
|
||||
|
||||
"""
|
||||
cmd = spack.util.executable.which(*executables)
|
||||
cmd = llnl.util.executable.which(*executables)
|
||||
if cmd:
|
||||
if not cmd_check or cmd_check(cmd):
|
||||
return cmd
|
||||
@@ -439,7 +439,7 @@ def ensure_executables_in_path_or_raise(
|
||||
current_bootstrapper.last_search["spec"],
|
||||
current_bootstrapper.last_search["command"],
|
||||
)
|
||||
env_mods = spack.util.environment.EnvironmentModifications()
|
||||
env_mods = llnl.util.envmod.EnvironmentModifications()
|
||||
for dep in concrete_spec.traverse(
|
||||
root=True, order="post", deptype=("link", "run")
|
||||
):
|
||||
@@ -514,7 +514,7 @@ def verify_patchelf(patchelf):
|
||||
|
||||
Arguments:
|
||||
|
||||
patchelf (spack.util.executable.Executable): patchelf executable
|
||||
patchelf (llnl.util.executable.Executable): patchelf executable
|
||||
"""
|
||||
out = patchelf("--version", output=str, error=os.devnull, fail_on_error=False).strip()
|
||||
if patchelf.returncode != 0:
|
||||
|
@@ -12,12 +12,12 @@
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
import llnl.util.executable
|
||||
from llnl.util import tty
|
||||
|
||||
import spack.build_environment
|
||||
import spack.environment
|
||||
import spack.tengine
|
||||
import spack.util.executable
|
||||
|
||||
from ._common import _root_spec
|
||||
from .config import root_path, spec_for_current_python, store_path
|
||||
@@ -120,7 +120,7 @@ def update_syspath_and_environ(self):
|
||||
)
|
||||
|
||||
def _install_with_depfile(self):
|
||||
spackcmd = spack.util.executable.which("spack")
|
||||
spackcmd = llnl.util.executable.which("spack")
|
||||
spackcmd(
|
||||
"-e",
|
||||
str(self.environment_root()),
|
||||
@@ -129,7 +129,7 @@ def _install_with_depfile(self):
|
||||
"-o",
|
||||
str(self.environment_root().joinpath("Makefile")),
|
||||
)
|
||||
make = spack.util.executable.which("make")
|
||||
make = llnl.util.executable.which("make")
|
||||
kwargs = {}
|
||||
if not tty.is_debug():
|
||||
kwargs = {"output": os.devnull, "error": os.devnull}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
"""Query the status of bootstrapping on this machine"""
|
||||
import platform
|
||||
|
||||
import spack.util.executable
|
||||
import llnl.util.executable
|
||||
|
||||
from ._common import _executables_in_store, _python_import, _try_import_from_store
|
||||
from .config import ensure_bootstrap_configuration
|
||||
@@ -24,7 +24,7 @@ def _required_system_executable(exes, msg):
|
||||
"""Search for an executable is the system path only."""
|
||||
if isinstance(exes, str):
|
||||
exes = (exes,)
|
||||
if spack.util.executable.which_string(*exes):
|
||||
if llnl.util.executable.which_string(*exes):
|
||||
return True, None
|
||||
return False, msg
|
||||
|
||||
@@ -33,7 +33,7 @@ def _required_executable(exes, query_spec, msg):
|
||||
"""Search for an executable in the system path or in the bootstrap store."""
|
||||
if isinstance(exes, str):
|
||||
exes = (exes,)
|
||||
if spack.util.executable.which_string(*exes) or _executables_in_store(exes, query_spec):
|
||||
if llnl.util.executable.which_string(*exes) or _executables_in_store(exes, query_spec):
|
||||
return True, None
|
||||
return False, msg
|
||||
|
||||
|
@@ -43,7 +43,19 @@
|
||||
from typing import List, Tuple
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import (
|
||||
EnvironmentModifications,
|
||||
env_flag,
|
||||
filter_system_paths,
|
||||
get_path,
|
||||
inspect_path,
|
||||
is_system_path,
|
||||
system_dirs,
|
||||
validate,
|
||||
)
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.lang import dedupe
|
||||
from llnl.util.string import plural
|
||||
from llnl.util.symlink import symlink
|
||||
from llnl.util.tty.color import cescape, colorize
|
||||
from llnl.util.tty.log import MultiProcessFd
|
||||
@@ -63,25 +75,12 @@
|
||||
import spack.store
|
||||
import spack.subprocess_context
|
||||
import spack.user_environment
|
||||
import spack.util.path
|
||||
import spack.util.pattern
|
||||
from spack.error import NoHeadersError, NoLibrariesError
|
||||
from spack.installer import InstallError
|
||||
from spack.util.cpus import cpus_available
|
||||
from spack.util.environment import (
|
||||
EnvironmentModifications,
|
||||
env_flag,
|
||||
filter_system_paths,
|
||||
get_path,
|
||||
inspect_path,
|
||||
is_system_path,
|
||||
system_dirs,
|
||||
validate,
|
||||
)
|
||||
from spack.util.executable import Executable
|
||||
from spack.util.log_parse import make_log_context, parse_log_events
|
||||
from spack.util.module_cmd import load_module, module, path_from_modules
|
||||
from spack.util.string import plural
|
||||
|
||||
#
|
||||
# This can be set by the user to globally disable parallel builds.
|
||||
@@ -1304,7 +1303,7 @@ class ChildError(InstallError):
|
||||
|
||||
# List of errors considered "build errors", for which we'll show log
|
||||
# context instead of Python context.
|
||||
build_errors = [("spack.util.executable", "ProcessError")]
|
||||
build_errors = [("llnl.util.executable", "ProcessError")]
|
||||
|
||||
def __init__(self, msg, module, classname, traceback_string, log_name, log_type, context):
|
||||
super(ChildError, self).__init__(msg)
|
||||
|
@@ -2,11 +2,11 @@
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import llnl.util.executable
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.directives
|
||||
import spack.package_base
|
||||
import spack.util.executable
|
||||
|
||||
from .autotools import AutotoolsBuilder, AutotoolsPackage
|
||||
|
||||
@@ -22,7 +22,7 @@ def configure(self, pkg, spec, prefix):
|
||||
prezip = spec["aspell"].prefix.bin.prezip
|
||||
destdir = prefix
|
||||
|
||||
sh = spack.util.executable.which("sh")
|
||||
sh = llnl.util.executable.which("sh")
|
||||
sh(
|
||||
"./configure",
|
||||
"--vars",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import Executable
|
||||
|
||||
import spack.build_environment
|
||||
import spack.builder
|
||||
@@ -18,7 +19,6 @@
|
||||
from spack.directives import build_system, conflicts, depends_on
|
||||
from spack.multimethod import when
|
||||
from spack.operating_systems.mac_os import macos_version
|
||||
from spack.util.executable import Executable
|
||||
from spack.version import Version
|
||||
|
||||
from ._checks import (
|
||||
|
@@ -15,7 +15,6 @@
|
||||
import spack.build_environment
|
||||
import spack.builder
|
||||
import spack.package_base
|
||||
import spack.util.path
|
||||
from spack.directives import build_system, depends_on, variant
|
||||
from spack.multimethod import when
|
||||
|
||||
|
@@ -11,6 +11,8 @@
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.filesystem import (
|
||||
HeaderList,
|
||||
LibraryList,
|
||||
@@ -25,8 +27,6 @@
|
||||
import spack.error
|
||||
from spack.build_environment import dso_suffix
|
||||
from spack.package_base import InstallError
|
||||
from spack.util.environment import EnvironmentModifications
|
||||
from spack.util.executable import Executable
|
||||
from spack.util.prefix import Prefix
|
||||
from spack.version import Version, ver
|
||||
|
||||
|
@@ -4,11 +4,11 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import os
|
||||
|
||||
import llnl.util.executable
|
||||
from llnl.util.filesystem import find
|
||||
|
||||
import spack.builder
|
||||
import spack.package_base
|
||||
import spack.util.executable
|
||||
from spack.directives import build_system, depends_on, extends
|
||||
from spack.multimethod import when
|
||||
|
||||
@@ -41,11 +41,11 @@ class LuaPackage(spack.package_base.PackageBase):
|
||||
|
||||
@property
|
||||
def lua(self):
|
||||
return spack.util.executable.Executable(self.spec["lua-lang"].prefix.bin.lua)
|
||||
return llnl.util.executable.Executable(self.spec["lua-lang"].prefix.bin.lua)
|
||||
|
||||
@property
|
||||
def luarocks(self):
|
||||
lr = spack.util.executable.Executable(self.spec["lua-lang"].prefix.bin.luarocks)
|
||||
lr = llnl.util.executable.Executable(self.spec["lua-lang"].prefix.bin.luarocks)
|
||||
return lr
|
||||
|
||||
|
||||
|
@@ -3,12 +3,12 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.executable import which
|
||||
|
||||
import spack.builder
|
||||
import spack.package_base
|
||||
from spack.directives import build_system, depends_on
|
||||
from spack.multimethod import when
|
||||
from spack.util.executable import which
|
||||
|
||||
from ._checks import BaseBuilder
|
||||
|
||||
|
@@ -8,11 +8,11 @@
|
||||
import shutil
|
||||
from os.path import basename, dirname, isdir
|
||||
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.filesystem import find_headers, find_libraries, join_path
|
||||
|
||||
from spack.directives import conflicts, variant
|
||||
from spack.util.environment import EnvironmentModifications
|
||||
from spack.util.executable import Executable
|
||||
|
||||
from .generic import Package
|
||||
|
||||
|
@@ -5,13 +5,13 @@
|
||||
import inspect
|
||||
import os
|
||||
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.filesystem import filter_file
|
||||
|
||||
import spack.builder
|
||||
import spack.package_base
|
||||
from spack.directives import build_system, extends
|
||||
from spack.package_base import PackageBase
|
||||
from spack.util.executable import Executable
|
||||
|
||||
from ._checks import BaseBuilder, execute_build_time_tests
|
||||
|
||||
|
@@ -8,13 +8,13 @@
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lang as lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import env_flag
|
||||
from llnl.util.executable import Executable, ProcessError
|
||||
|
||||
import spack.builder
|
||||
from spack.build_environment import SPACK_NO_PARALLEL_MAKE, determine_number_of_jobs
|
||||
from spack.directives import build_system, extends
|
||||
from spack.package_base import PackageBase
|
||||
from spack.util.environment import env_flag
|
||||
from spack.util.executable import Executable, ProcessError
|
||||
|
||||
|
||||
class RacketPackage(PackageBase):
|
||||
|
@@ -518,7 +518,7 @@ def setup_build_environment(self, env):
|
||||
Spack's store.
|
||||
|
||||
Args:
|
||||
env (spack.util.environment.EnvironmentModifications): environment
|
||||
env (llnl.util.envmod.EnvironmentModifications): environment
|
||||
modifications to be applied when the package is built. Package authors
|
||||
can call methods on it to alter the build environment.
|
||||
"""
|
||||
@@ -546,7 +546,7 @@ def setup_dependent_build_environment(self, env, dependent_spec):
|
||||
variable.
|
||||
|
||||
Args:
|
||||
env (spack.util.environment.EnvironmentModifications): environment
|
||||
env (llnl.util.envmod.EnvironmentModifications): environment
|
||||
modifications to be applied when the dependent package is built.
|
||||
Package authors can call methods on it to alter the build environment.
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
import ruamel.yaml as yaml
|
||||
from ruamel.yaml.error import MarkedYAMLError
|
||||
|
||||
import llnl.util.string
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import join_path
|
||||
from llnl.util.lang import attr_setdefault, index_by
|
||||
@@ -33,7 +34,6 @@
|
||||
import spack.traverse as traverse
|
||||
import spack.user_environment as uenv
|
||||
import spack.util.spack_json as sjson
|
||||
import spack.util.string
|
||||
|
||||
# cmd has a submodule called "list" so preserve the python list module
|
||||
python_list = list
|
||||
@@ -523,7 +523,7 @@ def print_how_many_pkgs(specs, pkg_type=""):
|
||||
category, e.g. if pkg_type is "installed" then the message
|
||||
would be "3 installed packages"
|
||||
"""
|
||||
tty.msg("%s" % spack.util.string.plural(len(specs), pkg_type + " package"))
|
||||
tty.msg("%s" % llnl.util.string.plural(len(specs), pkg_type + " package"))
|
||||
|
||||
|
||||
def spack_is_git_repo():
|
||||
|
@@ -11,6 +11,7 @@
|
||||
import urllib.parse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.string import plural
|
||||
|
||||
import spack.binary_distribution as bindist
|
||||
import spack.cmd
|
||||
@@ -30,7 +31,6 @@
|
||||
from spack.error import SpecError
|
||||
from spack.spec import Spec, save_dependency_specfiles
|
||||
from spack.stage import Stage
|
||||
from spack.util.string import plural
|
||||
|
||||
description = "create, download and install binary packages"
|
||||
section = "packaging"
|
||||
|
@@ -6,11 +6,11 @@
|
||||
import os
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import ProcessError
|
||||
from llnl.util.filesystem import mkdirp, working_dir
|
||||
|
||||
import spack.paths
|
||||
import spack.util.git
|
||||
from spack.util.executable import ProcessError
|
||||
|
||||
_SPACK_UPSTREAM = "https://github.com/spack/spack"
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
import urllib.parse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import ProcessError, which
|
||||
from llnl.util.filesystem import mkdirp
|
||||
|
||||
import spack.repo
|
||||
@@ -23,7 +24,6 @@
|
||||
parse_version,
|
||||
)
|
||||
from spack.util.editor import editor
|
||||
from spack.util.executable import ProcessError, which
|
||||
from spack.util.naming import (
|
||||
mod_to_class,
|
||||
simplify_name,
|
||||
|
@@ -12,6 +12,7 @@
|
||||
from glob import glob
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import working_dir
|
||||
|
||||
import spack.config
|
||||
@@ -19,7 +20,6 @@
|
||||
import spack.platforms
|
||||
import spack.util.git
|
||||
from spack.main import get_version
|
||||
from spack.util.executable import which
|
||||
|
||||
description = "debugging commands for troubleshooting Spack"
|
||||
section = "developer"
|
||||
|
@@ -13,7 +13,6 @@
|
||||
import spack.cmd.common.arguments as arguments
|
||||
import spack.environment as ev
|
||||
import spack.solver.asp as asp
|
||||
import spack.util.environment
|
||||
import spack.util.spack_json as sjson
|
||||
|
||||
description = "compare two specs"
|
||||
|
@@ -11,7 +11,9 @@
|
||||
import tempfile
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.string as string
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
from llnl.util.tty.colify import colify
|
||||
from llnl.util.tty.color import colorize
|
||||
|
||||
@@ -28,8 +30,6 @@
|
||||
import spack.schema.env
|
||||
import spack.tengine
|
||||
import spack.traverse as traverse
|
||||
import spack.util.string as string
|
||||
from spack.util.environment import EnvironmentModifications
|
||||
|
||||
description = "manage virtual environments"
|
||||
section = "environments"
|
||||
|
@@ -18,7 +18,6 @@
|
||||
import spack.cray_manifest as cray_manifest
|
||||
import spack.detection
|
||||
import spack.error
|
||||
import spack.util.environment
|
||||
|
||||
description = "manage external packages in Spack configuration"
|
||||
section = "config"
|
||||
|
@@ -5,13 +5,14 @@
|
||||
|
||||
import sys
|
||||
|
||||
import llnl.util.envmod
|
||||
|
||||
import spack.cmd
|
||||
import spack.cmd.common.arguments as arguments
|
||||
import spack.cmd.find
|
||||
import spack.environment as ev
|
||||
import spack.store
|
||||
import spack.user_environment as uenv
|
||||
import spack.util.environment
|
||||
|
||||
description = "add package to the user environment"
|
||||
section = "user environment"
|
||||
@@ -110,7 +111,7 @@ def load(parser, args):
|
||||
dep for spec in specs for dep in spec.traverse(root=include_roots, order="post")
|
||||
]
|
||||
|
||||
env_mod = spack.util.environment.EnvironmentModifications()
|
||||
env_mod = llnl.util.envmod.EnvironmentModifications()
|
||||
for spec in specs:
|
||||
env_mod.extend(uenv.environment_modifications_for_spec(spec))
|
||||
env_mod.prepend_path(uenv.spack_loaded_hashes_var, spec.dag_hash())
|
||||
|
@@ -6,10 +6,11 @@
|
||||
import posixpath
|
||||
import sys
|
||||
|
||||
import llnl.util.executable
|
||||
from llnl.util.path import convert_to_posix_path
|
||||
|
||||
import spack.paths
|
||||
import spack.util.executable
|
||||
from spack.spec import Spec
|
||||
from spack.util.path import convert_to_posix_path
|
||||
|
||||
description = "generate Windows installer"
|
||||
section = "admin"
|
||||
@@ -100,7 +101,7 @@ def make_installer(parser, args):
|
||||
spack_logo = posixpath.join(posix_root, "share/spack/logo/favicon.ico")
|
||||
|
||||
try:
|
||||
spack.util.executable.Executable(cmake_path)(
|
||||
llnl.util.executable.Executable(cmake_path)(
|
||||
"-S",
|
||||
source_dir,
|
||||
"-B",
|
||||
@@ -111,30 +112,30 @@ def make_installer(parser, args):
|
||||
"-DSPACK_LOGO=%s" % spack_logo,
|
||||
"-DSPACK_GIT_VERBOSITY=%s" % git_verbosity,
|
||||
)
|
||||
except spack.util.executable.ProcessError:
|
||||
except llnl.util.executable.ProcessError:
|
||||
print("Failed to generate installer")
|
||||
return spack.util.executable.ProcessError.returncode
|
||||
return llnl.util.executable.ProcessError.returncode
|
||||
|
||||
try:
|
||||
spack.util.executable.Executable(cpack_path)(
|
||||
llnl.util.executable.Executable(cpack_path)(
|
||||
"--config", "%s/CPackConfig.cmake" % output_dir, "-B", "%s/" % output_dir
|
||||
)
|
||||
except spack.util.executable.ProcessError:
|
||||
except llnl.util.executable.ProcessError:
|
||||
print("Failed to generate installer")
|
||||
return spack.util.executable.ProcessError.returncode
|
||||
return llnl.util.executable.ProcessError.returncode
|
||||
try:
|
||||
spack.util.executable.Executable(os.environ.get("WIX") + "/bin/candle.exe")(
|
||||
llnl.util.executable.Executable(os.environ.get("WIX") + "/bin/candle.exe")(
|
||||
"-ext",
|
||||
"WixBalExtension",
|
||||
"%s/bundle.wxs" % output_dir,
|
||||
"-out",
|
||||
"%s/bundle.wixobj" % output_dir,
|
||||
)
|
||||
except spack.util.executable.ProcessError:
|
||||
except llnl.util.executable.ProcessError:
|
||||
print("Failed to generate installer chain")
|
||||
return spack.util.executable.ProcessError.returncode
|
||||
return llnl.util.executable.ProcessError.returncode
|
||||
try:
|
||||
spack.util.executable.Executable(os.environ.get("WIX") + "/bin/light.exe")(
|
||||
llnl.util.executable.Executable(os.environ.get("WIX") + "/bin/light.exe")(
|
||||
"-sw1134",
|
||||
"-ext",
|
||||
"WixBalExtension",
|
||||
@@ -142,9 +143,9 @@ def make_installer(parser, args):
|
||||
"-out",
|
||||
"%s/Spack.exe" % output_dir,
|
||||
)
|
||||
except spack.util.executable.ProcessError:
|
||||
except llnl.util.executable.ProcessError:
|
||||
print("Failed to generate installer chain")
|
||||
return spack.util.executable.ProcessError.returncode
|
||||
return llnl.util.executable.ProcessError.returncode
|
||||
print("Successfully generated Spack.exe in %s" % (output_dir))
|
||||
else:
|
||||
print("The make-installer command is currently only supported on Windows.")
|
||||
|
@@ -10,6 +10,7 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import llnl.util.executable as exe
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.tty.colify import colify
|
||||
|
||||
@@ -17,7 +18,6 @@
|
||||
import spack.cmd.common.arguments as arguments
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
import spack.util.executable as exe
|
||||
import spack.util.package_hash as ph
|
||||
|
||||
description = "query packages associated with particular git revisions"
|
||||
|
@@ -10,11 +10,11 @@
|
||||
|
||||
import llnl.util.tty as tty
|
||||
import llnl.util.tty.color as color
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import working_dir
|
||||
|
||||
import spack.paths
|
||||
import spack.util.git
|
||||
from spack.util.executable import which
|
||||
|
||||
description = "runs source code style checks on spack"
|
||||
section = "developer"
|
||||
|
@@ -5,6 +5,7 @@
|
||||
import io
|
||||
import sys
|
||||
|
||||
import llnl.util.string
|
||||
import llnl.util.tty as tty
|
||||
import llnl.util.tty.colify as colify
|
||||
|
||||
@@ -24,7 +25,7 @@ def report_tags(category, tags):
|
||||
if isatty:
|
||||
num = len(tags)
|
||||
fmt = "{0} package tag".format(category)
|
||||
buffer.write("{0}:\n".format(spack.util.string.plural(num, fmt)))
|
||||
buffer.write("{0}:\n".format(llnl.util.string.plural(num, fmt)))
|
||||
|
||||
if tags:
|
||||
colify.colify(tags, output=buffer, tty=isatty, indent=4)
|
||||
|
@@ -6,11 +6,12 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
import llnl.util.envmod
|
||||
|
||||
import spack.cmd
|
||||
import spack.cmd.common.arguments as arguments
|
||||
import spack.error
|
||||
import spack.user_environment as uenv
|
||||
import spack.util.environment
|
||||
|
||||
description = "remove package from the user environment"
|
||||
section = "user environment"
|
||||
@@ -82,7 +83,7 @@ def unload(parser, args):
|
||||
)
|
||||
return 1
|
||||
|
||||
env_mod = spack.util.environment.EnvironmentModifications()
|
||||
env_mod = llnl.util.envmod.EnvironmentModifications()
|
||||
for spec in specs:
|
||||
env_mod.extend(uenv.environment_modifications_for_spec(spec).reversed())
|
||||
env_mod.remove_path(uenv.spack_loaded_hashes_var, spec.dag_hash())
|
||||
|
@@ -13,18 +13,18 @@
|
||||
import tempfile
|
||||
from typing import List, Optional, Sequence
|
||||
|
||||
import llnl.util.envmod as envmod
|
||||
import llnl.util.executable
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import path_contains_subdirectory, paths_containing_libs
|
||||
from llnl.util.path import system_path_filter
|
||||
|
||||
import spack.compilers
|
||||
import spack.error
|
||||
import spack.spec
|
||||
import spack.util.executable
|
||||
import spack.util.module_cmd
|
||||
import spack.version
|
||||
from spack.util.environment import filter_system_paths
|
||||
from spack.util.path import system_path_filter
|
||||
|
||||
__all__ = ["Compiler"]
|
||||
|
||||
@@ -40,7 +40,7 @@ def _get_compiler_version_output(compiler_path, version_arg, ignore_errors=()):
|
||||
compiler_path (path): path of the compiler to be invoked
|
||||
version_arg (str): the argument used to extract version information
|
||||
"""
|
||||
compiler = spack.util.executable.Executable(compiler_path)
|
||||
compiler = llnl.util.executable.Executable(compiler_path)
|
||||
if version_arg:
|
||||
output = compiler(version_arg, output=str, error=str, ignore_errors=ignore_errors)
|
||||
else:
|
||||
@@ -54,7 +54,7 @@ def get_compiler_version_output(compiler_path, *args, **kwargs):
|
||||
# not just executable name. If we don't do this, and the path changes
|
||||
# (e.g., during testing), we can get incorrect results.
|
||||
if not os.path.isabs(compiler_path):
|
||||
compiler_path = spack.util.executable.which_string(compiler_path, required=True)
|
||||
compiler_path = llnl.util.executable.which_string(compiler_path, required=True)
|
||||
|
||||
return _get_compiler_version_output(compiler_path, *args, **kwargs)
|
||||
|
||||
@@ -175,7 +175,7 @@ def _parse_non_system_link_dirs(string: str) -> List[str]:
|
||||
# system paths. Note that 'filter_system_paths' only checks for an
|
||||
# exact match, while 'in_system_subdirectory' checks if a path contains
|
||||
# a system directory as a subdirectory
|
||||
link_dirs = filter_system_paths(link_dirs)
|
||||
link_dirs = envmod.filter_system_paths(link_dirs)
|
||||
return list(p for p in link_dirs if not in_system_subdirectory(p))
|
||||
|
||||
|
||||
@@ -339,7 +339,7 @@ def verify_executables(self):
|
||||
def accessible_exe(exe):
|
||||
# compilers may contain executable names (on Cray or user edited)
|
||||
if not os.path.isabs(exe):
|
||||
exe = spack.util.executable.which_string(exe)
|
||||
exe = llnl.util.executable.which_string(exe)
|
||||
if not exe:
|
||||
return False
|
||||
return os.path.isfile(exe) and os.access(exe, os.X_OK)
|
||||
@@ -371,7 +371,7 @@ def real_version(self):
|
||||
if real_version == spack.version.Version("unknown"):
|
||||
return self.version
|
||||
self._real_version = real_version
|
||||
except spack.util.executable.ProcessError:
|
||||
except llnl.util.executable.ProcessError:
|
||||
self._real_version = self.version
|
||||
return self._real_version
|
||||
|
||||
@@ -422,7 +422,7 @@ def _get_compiler_link_paths(self, paths):
|
||||
csource.write(
|
||||
"int main(int argc, char* argv[]) { " "(void)argc; (void)argv; return 0; }\n"
|
||||
)
|
||||
compiler_exe = spack.util.executable.Executable(first_compiler)
|
||||
compiler_exe = llnl.util.executable.Executable(first_compiler)
|
||||
for flag_type in flags:
|
||||
for flag in self.flags.get(flag_type, []):
|
||||
compiler_exe.add_default_arg(flag)
|
||||
@@ -433,7 +433,7 @@ def _get_compiler_link_paths(self, paths):
|
||||
compiler_exe(self.verbose_flag, fin, "-o", fout, output=str, error=str)
|
||||
) # str for py2
|
||||
return _parse_non_system_link_dirs(output)
|
||||
except spack.util.executable.ProcessError as pe:
|
||||
except llnl.util.executable.ProcessError as pe:
|
||||
tty.debug("ProcessError: Command exited with non-zero status: " + pe.long_message)
|
||||
return []
|
||||
finally:
|
||||
@@ -532,7 +532,7 @@ def get_real_version(self):
|
||||
Use the runtime environment of the compiler (modules and environment
|
||||
modifications) to enable the compiler to run properly on any platform.
|
||||
"""
|
||||
cc = spack.util.executable.Executable(self.cc)
|
||||
cc = llnl.util.executable.Executable(self.cc)
|
||||
with self.compiler_environment():
|
||||
output = cc(
|
||||
self.version_argument,
|
||||
@@ -658,7 +658,7 @@ def compiler_environment(self):
|
||||
spack.util.module_cmd.load_module(module)
|
||||
|
||||
# apply other compiler environment changes
|
||||
env = spack.util.environment.EnvironmentModifications()
|
||||
env = llnl.util.envmod.EnvironmentModifications()
|
||||
env.extend(spack.schema.environment.parse(self.environment))
|
||||
env.apply_modifications()
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import get_path
|
||||
|
||||
import spack.compiler
|
||||
import spack.config
|
||||
@@ -24,7 +25,6 @@
|
||||
import spack.paths
|
||||
import spack.platforms
|
||||
import spack.spec
|
||||
from spack.util.environment import get_path
|
||||
from spack.util.naming import mod_to_class
|
||||
|
||||
_path_instance_vars = ["cc", "cxx", "f77", "fc"]
|
||||
@@ -680,7 +680,7 @@ def _default(fn_args):
|
||||
return value, None
|
||||
|
||||
error = "Couldn't get version for compiler {0}".format(path)
|
||||
except spack.util.executable.ProcessError as e:
|
||||
except llnl.util.executable.ProcessError as e:
|
||||
error = "Couldn't get version for compiler {0}\n".format(path) + str(e)
|
||||
except Exception as e:
|
||||
# Catching "Exception" here is fine because it just
|
||||
|
@@ -6,13 +6,13 @@
|
||||
import re
|
||||
import shutil
|
||||
|
||||
import llnl.util.executable
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.symlink import symlink
|
||||
|
||||
import spack.compiler
|
||||
import spack.compilers.clang
|
||||
import spack.util.executable
|
||||
import spack.version
|
||||
|
||||
|
||||
@@ -90,13 +90,13 @@ def setup_custom_environment(self, pkg, env):
|
||||
|
||||
# Use special XCode versions of compiler wrappers when using XCode
|
||||
# Overwrites build_environment's setting of SPACK_CC and SPACK_CXX
|
||||
xcrun = spack.util.executable.Executable("xcrun")
|
||||
xcrun = llnl.util.executable.Executable("xcrun")
|
||||
xcode_clang = xcrun("-f", "clang", output=str).strip()
|
||||
xcode_clangpp = xcrun("-f", "clang++", output=str).strip()
|
||||
env.set("SPACK_CC", xcode_clang, force=True)
|
||||
env.set("SPACK_CXX", xcode_clangpp, force=True)
|
||||
|
||||
xcode_select = spack.util.executable.Executable("xcode-select")
|
||||
xcode_select = llnl.util.executable.Executable("xcode-select")
|
||||
|
||||
# Get the path of the active developer directory
|
||||
real_root = xcode_select("--print-path", output=str).strip()
|
||||
|
@@ -6,11 +6,11 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
import llnl.util.executable
|
||||
from llnl.util.filesystem import ancestor
|
||||
|
||||
import spack.compiler
|
||||
import spack.compilers.apple_clang as apple_clang
|
||||
import spack.util.executable
|
||||
from spack.version import ver
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ def stdcxx_libs(self):
|
||||
def prefix(self):
|
||||
# GCC reports its install prefix when running ``-print-search-dirs``
|
||||
# on the first line ``install: <prefix>``.
|
||||
cc = spack.util.executable.Executable(self.cc)
|
||||
cc = llnl.util.executable.Executable(self.cc)
|
||||
with self.compiler_environment():
|
||||
gcc_output = cc("-print-search-dirs", output=str, error=str)
|
||||
|
||||
|
@@ -10,10 +10,11 @@
|
||||
from distutils.version import StrictVersion
|
||||
from typing import Dict, List, Set
|
||||
|
||||
import llnl.util.executable
|
||||
|
||||
import spack.compiler
|
||||
import spack.operating_systems.windows_os
|
||||
import spack.platforms
|
||||
import spack.util.executable
|
||||
from spack.compiler import Compiler
|
||||
from spack.error import SpackError
|
||||
from spack.version import Version
|
||||
@@ -170,7 +171,7 @@ def fc_version(cls, fc):
|
||||
sps = spack.operating_systems.windows_os.WindowsOs.compiler_search_paths
|
||||
except AttributeError:
|
||||
raise SpackError("Windows compiler search paths not established")
|
||||
clp = spack.util.executable.which_string("cl", path=sps)
|
||||
clp = llnl.util.executable.which_string("cl", path=sps)
|
||||
ver = cls.default_version(clp)
|
||||
else:
|
||||
ver = fc_ver
|
||||
|
@@ -347,7 +347,7 @@ def find_win32_additional_install_paths():
|
||||
windows_search_ext.extend(
|
||||
spack.config.get("config:additional_external_search_paths", default=[])
|
||||
)
|
||||
windows_search_ext.extend(spack.util.environment.get_path("PATH"))
|
||||
windows_search_ext.extend(llnl.util.envmod.get_path("PATH"))
|
||||
return windows_search_ext
|
||||
|
||||
|
||||
|
@@ -12,10 +12,10 @@
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.filesystem
|
||||
import llnl.util.tty
|
||||
|
||||
import spack.util.environment
|
||||
import spack.util.ld_so_conf
|
||||
|
||||
from .common import ( # find_windows_compiler_bundled_packages,
|
||||
@@ -83,9 +83,9 @@ def libraries_in_ld_and_system_library_path(path_hints=None):
|
||||
"""
|
||||
path_hints = (
|
||||
path_hints
|
||||
or spack.util.environment.get_path("LD_LIBRARY_PATH")
|
||||
+ spack.util.environment.get_path("DYLD_LIBRARY_PATH")
|
||||
+ spack.util.environment.get_path("DYLD_FALLBACK_LIBRARY_PATH")
|
||||
or llnl.util.envmod.get_path("LD_LIBRARY_PATH")
|
||||
+ llnl.util.envmod.get_path("DYLD_LIBRARY_PATH")
|
||||
+ llnl.util.envmod.get_path("DYLD_FALLBACK_LIBRARY_PATH")
|
||||
+ spack.util.ld_so_conf.host_dynamic_linker_search_paths()
|
||||
)
|
||||
search_paths = llnl.util.filesystem.search_paths_for_libraries(*path_hints)
|
||||
@@ -93,7 +93,7 @@ def libraries_in_ld_and_system_library_path(path_hints=None):
|
||||
|
||||
|
||||
def libraries_in_windows_paths(path_hints):
|
||||
path_hints.extend(spack.util.environment.get_path("PATH"))
|
||||
path_hints.extend(llnl.util.envmod.get_path("PATH"))
|
||||
search_paths = llnl.util.filesystem.search_paths_for_libraries(*path_hints)
|
||||
# on Windows, some libraries (.dlls) are found in the bin directory or sometimes
|
||||
# at the search root. Add both of those options to the search scheme
|
||||
@@ -236,7 +236,7 @@ def by_executable(packages_to_check, path_hints=None):
|
||||
path_hints (list): list of paths to be searched. If None the list will be
|
||||
constructed based on the PATH environment variable.
|
||||
"""
|
||||
path_hints = spack.util.environment.get_path("PATH") if path_hints is None else path_hints
|
||||
path_hints = llnl.util.envmod.get_path("PATH") if path_hints is None else path_hints
|
||||
exe_pattern_to_pkgs = collections.defaultdict(list)
|
||||
for pkg in packages_to_check:
|
||||
if hasattr(pkg, "executables"):
|
||||
|
@@ -20,6 +20,7 @@
|
||||
import spack.spec
|
||||
import spack.util.spack_json as sjson
|
||||
from spack.error import SpackError
|
||||
from spack.util.environment import get_host_environment_metadata
|
||||
|
||||
is_windows = sys.platform == "win32"
|
||||
# Note: Posixpath is used here as opposed to
|
||||
@@ -120,8 +121,6 @@ def write_host_environment(self, spec):
|
||||
versioning. We use it in the case that an analysis later needs to
|
||||
easily access this information.
|
||||
"""
|
||||
from spack.util.environment import get_host_environment_metadata
|
||||
|
||||
env_file = self.env_metadata_path(spec)
|
||||
environ = get_host_environment_metadata()
|
||||
with open(env_file, "w") as fd:
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
import ruamel.yaml as yaml
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.lang import dedupe
|
||||
@@ -1535,7 +1536,7 @@ def check_views(self):
|
||||
)
|
||||
|
||||
def _env_modifications_for_default_view(self, reverse=False):
|
||||
all_mods = spack.util.environment.EnvironmentModifications()
|
||||
all_mods = llnl.util.envmod.EnvironmentModifications()
|
||||
|
||||
visited = set()
|
||||
|
||||
@@ -1576,7 +1577,7 @@ def add_default_view_to_env(self, env_mod):
|
||||
default view. Removes duplicate paths.
|
||||
|
||||
Args:
|
||||
env_mod (spack.util.environment.EnvironmentModifications): the environment
|
||||
env_mod (llnl.util.envmod.EnvironmentModifications): the environment
|
||||
modifications object that is modified.
|
||||
"""
|
||||
if default_view_name not in self.views:
|
||||
@@ -1603,7 +1604,7 @@ def rm_default_view_from_env(self, env_mod):
|
||||
default view. Reverses the action of ``add_default_view_to_env``.
|
||||
|
||||
Args:
|
||||
env_mod (spack.util.environment.EnvironmentModifications): the environment
|
||||
env_mod (llnl.util.envmod.EnvironmentModifications): the environment
|
||||
modifications object that is modified.
|
||||
"""
|
||||
if default_view_name not in self.views:
|
||||
|
@@ -5,12 +5,12 @@
|
||||
import os
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
from llnl.util.tty.color import colorize
|
||||
|
||||
import spack.environment as ev
|
||||
import spack.repo
|
||||
import spack.store
|
||||
from spack.util.environment import EnvironmentModifications
|
||||
|
||||
|
||||
def activate_header(env, shell, prompt=None):
|
||||
@@ -111,7 +111,7 @@ def activate(env, use_env_repo=False, add_view=True):
|
||||
add_view (bool): generate commands to add view to path variables
|
||||
|
||||
Returns:
|
||||
spack.util.environment.EnvironmentModifications: Environment variables
|
||||
llnl.util.envmod.EnvironmentModifications: Environment variables
|
||||
modifications to activate environment.
|
||||
"""
|
||||
ev.activate(env, use_env_repo=use_env_repo)
|
||||
@@ -150,7 +150,7 @@ def deactivate():
|
||||
after activation are not unloaded.
|
||||
|
||||
Returns:
|
||||
spack.util.environment.EnvironmentModifications: Environment variables
|
||||
llnl.util.envmod.EnvironmentModifications: Environment variables
|
||||
modifications to activate environment.
|
||||
"""
|
||||
env_mods = EnvironmentModifications()
|
||||
|
@@ -35,6 +35,7 @@
|
||||
import llnl.util
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import CommandNotFoundError, which
|
||||
from llnl.util.filesystem import (
|
||||
get_single_file,
|
||||
mkdirp,
|
||||
@@ -42,6 +43,7 @@
|
||||
temp_rename,
|
||||
working_dir,
|
||||
)
|
||||
from llnl.util.string import comma_and, quote
|
||||
from llnl.util.symlink import symlink
|
||||
|
||||
import spack.config
|
||||
@@ -54,8 +56,6 @@
|
||||
import spack.util.web as web_util
|
||||
import spack.version
|
||||
from spack.util.compression import decompressor_for, extension_from_path
|
||||
from spack.util.executable import CommandNotFoundError, which
|
||||
from spack.util.string import comma_and, quote
|
||||
|
||||
#: List of all fetch strategies, created by FetchStrategy metaclass.
|
||||
all_strategies = []
|
||||
|
@@ -6,6 +6,7 @@
|
||||
import os
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.filesystem import BaseDirectoryVisitor, visit_directory_tree
|
||||
from llnl.util.lang import elide_list
|
||||
|
||||
@@ -13,7 +14,6 @@
|
||||
import spack.config
|
||||
import spack.relocate
|
||||
from spack.util.elf import ElfParsingError, parse_elf
|
||||
from spack.util.executable import Executable
|
||||
|
||||
|
||||
def is_shared_library_elf(filepath):
|
||||
|
@@ -6,11 +6,11 @@
|
||||
import os
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import Executable, which
|
||||
from llnl.util.filesystem import mkdirp
|
||||
from llnl.util.symlink import symlink
|
||||
|
||||
from spack.util.editor import editor
|
||||
from spack.util.executable import Executable, which
|
||||
|
||||
|
||||
def pre_install(spec):
|
||||
|
@@ -13,6 +13,7 @@
|
||||
|
||||
import spack.error
|
||||
import spack.paths
|
||||
import spack.util.path
|
||||
import spack.util.prefix
|
||||
import spack.util.spack_json as sjson
|
||||
from spack.spec import Spec
|
||||
|
@@ -40,6 +40,8 @@
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lock as lk
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.lang import pretty_seconds
|
||||
from llnl.util.tty.color import colorize
|
||||
from llnl.util.tty.log import log_output
|
||||
@@ -53,11 +55,9 @@
|
||||
import spack.package_prefs as prefs
|
||||
import spack.repo
|
||||
import spack.store
|
||||
import spack.util.executable
|
||||
import spack.util.path
|
||||
import spack.util.timer as timer
|
||||
from spack.util.environment import EnvironmentModifications, dump_environment
|
||||
from spack.util.executable import which
|
||||
from spack.util.environment import dump_environment
|
||||
|
||||
#: Counter to support unique spec sequencing that is used to ensure packages
|
||||
#: with the same priority are (initially) processed in the order in which they
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
import llnl.util.tty.colify
|
||||
@@ -44,9 +45,7 @@
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.debug
|
||||
import spack.util.environment
|
||||
import spack.util.git
|
||||
import spack.util.path
|
||||
from spack.error import SpackError
|
||||
|
||||
#: names of profile statistics
|
||||
@@ -575,7 +574,7 @@ def setup_main_options(args):
|
||||
if args.debug:
|
||||
spack.util.debug.register_interrupt_handler()
|
||||
spack.config.set("config:debug", True, scope="command_line")
|
||||
spack.util.environment.tracing_enabled = True
|
||||
llnl.util.envmod.tracing_enabled = True
|
||||
|
||||
if args.timestamp:
|
||||
tty.set_timestamp(True)
|
||||
|
@@ -36,6 +36,7 @@
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.filesystem
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.lang import dedupe
|
||||
@@ -51,7 +52,6 @@
|
||||
import spack.schema.environment
|
||||
import spack.store
|
||||
import spack.tengine as tengine
|
||||
import spack.util.environment
|
||||
import spack.util.file_permissions as fp
|
||||
import spack.util.path
|
||||
import spack.util.spack_yaml as syaml
|
||||
@@ -732,8 +732,8 @@ def environment_modifications(self):
|
||||
|
||||
spec.prefix = view.get_projection_for_spec(spec)
|
||||
|
||||
env = spack.util.environment.inspect_path(
|
||||
spec.prefix, prefix_inspections, exclude=spack.util.environment.is_system_path
|
||||
env = llnl.util.envmod.inspect_path(
|
||||
spec.prefix, prefix_inspections, exclude=llnl.util.envmod.is_system_path
|
||||
)
|
||||
|
||||
# Let the extendee/dependency modify their extensions/dependencies
|
||||
|
@@ -9,6 +9,7 @@
|
||||
import posixpath
|
||||
from typing import Any, Dict
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.lang as lang
|
||||
|
||||
import spack.compilers
|
||||
@@ -17,7 +18,6 @@
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.tengine as tengine
|
||||
import spack.util.environment
|
||||
|
||||
from .common import BaseConfiguration, BaseContext, BaseFileLayout, BaseModuleFileWriter
|
||||
|
||||
@@ -71,7 +71,7 @@ def guess_core_compilers(name, store=False):
|
||||
# A compiler is considered to be a core compiler if any of the
|
||||
# C, C++ or Fortran compilers reside in a system directory
|
||||
is_system_compiler = any(
|
||||
os.path.dirname(x) in spack.util.environment.system_dirs
|
||||
os.path.dirname(x) in llnl.util.envmod.system_dirs
|
||||
for x in compiler["paths"].values()
|
||||
if x is not None
|
||||
)
|
||||
|
@@ -10,8 +10,8 @@
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.envmod import get_path
|
||||
|
||||
from spack.util.environment import get_path
|
||||
from spack.util.module_cmd import module
|
||||
|
||||
from .linux_distro import LinuxDistro
|
||||
|
@@ -8,8 +8,8 @@
|
||||
import re
|
||||
|
||||
import llnl.util.lang
|
||||
from llnl.util.executable import Executable
|
||||
|
||||
from spack.util.executable import Executable
|
||||
from spack.version import Version
|
||||
|
||||
from ._operating_system import OperatingSystem
|
||||
@@ -50,7 +50,7 @@ def macos_version():
|
||||
try:
|
||||
output = Executable("sw_vers")(output=str, fail_on_error=False)
|
||||
except Exception:
|
||||
# FileNotFoundError, or spack.util.executable.ProcessError
|
||||
# FileNotFoundError, or llnl.util.executable.ProcessError
|
||||
pass
|
||||
else:
|
||||
match = re.search(r"ProductVersion:\s*([0-9.]+)", output)
|
||||
|
@@ -19,12 +19,12 @@
|
||||
# import most common types used in packages
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import llnl.util.executable
|
||||
import llnl.util.filesystem
|
||||
from llnl.util.executable import *
|
||||
from llnl.util.filesystem import *
|
||||
from llnl.util.symlink import symlink
|
||||
|
||||
import spack.util.executable
|
||||
|
||||
# These props will be overridden when the build env is set up.
|
||||
from spack.build_environment import MakeExecutable
|
||||
from spack.build_systems.aspell_dict import AspellDictPackage
|
||||
@@ -87,7 +87,6 @@
|
||||
on_package_attributes,
|
||||
)
|
||||
from spack.spec import InvalidSpecDetected, Spec
|
||||
from spack.util.executable import *
|
||||
from spack.variant import (
|
||||
any_combination_of,
|
||||
auto_or_any_combination_of,
|
||||
|
@@ -29,8 +29,11 @@
|
||||
import warnings
|
||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.filesystem as fsys
|
||||
import llnl.util.path
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import ProcessError, which
|
||||
from llnl.util.lang import classproperty, memoized, nullcontext
|
||||
from llnl.util.link_tree import LinkTree
|
||||
|
||||
@@ -51,14 +54,12 @@
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.url
|
||||
import spack.util.environment
|
||||
import spack.util.path
|
||||
import spack.util.web
|
||||
from spack.filesystem_view import YamlFilesystemView
|
||||
from spack.install_test import TestFailure, TestSuite
|
||||
from spack.installer import InstallError, PackageInstaller
|
||||
from spack.stage import ResourceStage, Stage, StageComposite, stage_prefix
|
||||
from spack.util.executable import ProcessError, which
|
||||
from spack.util.package_hash import package_hash
|
||||
from spack.util.prefix import Prefix
|
||||
from spack.util.web import FetchError
|
||||
@@ -204,9 +205,9 @@ def __init__(cls, name, bases, attr_dict):
|
||||
def platform_executables(cls):
|
||||
def to_windows_exe(exe):
|
||||
if exe.endswith("$"):
|
||||
exe = exe.replace("$", "%s$" % spack.util.path.win_exe_ext())
|
||||
exe = exe.replace("$", "%s$" % llnl.util.path.win_exe_ext())
|
||||
else:
|
||||
exe += spack.util.path.win_exe_ext()
|
||||
exe += llnl.util.path.win_exe_ext()
|
||||
return exe
|
||||
|
||||
plat_exe = []
|
||||
@@ -1993,7 +1994,7 @@ def run_test(
|
||||
for line in out:
|
||||
print(line.rstrip("\n"))
|
||||
|
||||
if exc_type is spack.util.executable.ProcessError:
|
||||
if exc_type is llnl.util.executable.ProcessError:
|
||||
out = io.StringIO()
|
||||
spack.build_environment.write_log_summary(
|
||||
out, "test", self.test_log_file, last=1
|
||||
@@ -2101,7 +2102,7 @@ def setup_run_environment(self, env):
|
||||
"""Sets up the run environment for a package.
|
||||
|
||||
Args:
|
||||
env (spack.util.environment.EnvironmentModifications): environment
|
||||
env (llnl.util.envmod.EnvironmentModifications): environment
|
||||
modifications to be applied when the package is run. Package authors
|
||||
can call methods on it to alter the run environment.
|
||||
"""
|
||||
@@ -2118,7 +2119,7 @@ def setup_dependent_run_environment(self, env, dependent_spec):
|
||||
for dependencies.
|
||||
|
||||
Args:
|
||||
env (spack.util.environment.EnvironmentModifications): environment
|
||||
env (llnl.util.envmod.EnvironmentModifications): environment
|
||||
modifications to be applied when the dependent package is run.
|
||||
Package authors can call methods on it to alter the build environment.
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
import os
|
||||
|
||||
from spack.util.executable import Executable, which
|
||||
from llnl.util.executable import Executable, which
|
||||
|
||||
|
||||
def compile_c_and_execute(source_file, include_flags, link_flags):
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
import llnl.util.filesystem
|
||||
import llnl.util.lang
|
||||
from llnl.util.executable import which, which_string
|
||||
|
||||
import spack
|
||||
import spack.error
|
||||
@@ -20,19 +21,9 @@
|
||||
import spack.util.spack_json as sjson
|
||||
from spack.util.compression import allowed_archive
|
||||
from spack.util.crypto import Checker, checksum
|
||||
from spack.util.executable import which, which_string
|
||||
|
||||
|
||||
def apply_patch(stage, patch_path, level=1, working_dir="."):
|
||||
"""Apply the patch at patch_path to code in the stage.
|
||||
|
||||
Args:
|
||||
stage (spack.stage.Stage): stage with code that will be patched
|
||||
patch_path (str): filesystem location for the patch to apply
|
||||
level (int or None): patch level (default 1)
|
||||
working_dir (str): relative path *within* the stage to change to
|
||||
(default '.')
|
||||
"""
|
||||
def get_patch_exe():
|
||||
git_utils_path = os.environ.get("PATH", "")
|
||||
if sys.platform == "win32":
|
||||
git = which_string("git", required=True)
|
||||
@@ -46,7 +37,20 @@ def apply_patch(stage, patch_path, level=1, working_dir="."):
|
||||
# Note for future developers: The GNU port of patch to windows
|
||||
# has issues handling CRLF line endings unless the --binary
|
||||
# flag is passed.
|
||||
patch = which("patch", required=True, path=git_utils_path)
|
||||
return which("patch", required=True, path=git_utils_path)
|
||||
|
||||
|
||||
def apply_patch(stage, patch_path, level=1, working_dir="."):
|
||||
"""Apply the patch at patch_path to code in the stage.
|
||||
|
||||
Args:
|
||||
stage (spack.stage.Stage): stage with code that will be patched
|
||||
patch_path (str): filesystem location for the patch to apply
|
||||
level (int or None): patch level (default 1)
|
||||
working_dir (str): relative path *within* the stage to change to
|
||||
(default '.')
|
||||
"""
|
||||
patch = get_patch_exe()
|
||||
with llnl.util.filesystem.working_dir(stage.source_path):
|
||||
patch("-s", "-p", str(level), "-i", patch_path, "-d", working_dir)
|
||||
|
||||
|
@@ -4,10 +4,9 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import contextlib
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.lang
|
||||
|
||||
import spack.util.environment
|
||||
|
||||
from .cray import Cray
|
||||
from .darwin import Darwin
|
||||
from .linux import Linux
|
||||
@@ -64,7 +63,7 @@ def prevent_cray_detection():
|
||||
"""Context manager that prevents the detection of the Cray platform"""
|
||||
reset()
|
||||
try:
|
||||
with spack.util.environment.set_env(MODULEPATH=""):
|
||||
with llnl.util.envmod.set_env(MODULEPATH=""):
|
||||
yield
|
||||
finally:
|
||||
reset()
|
||||
|
@@ -10,13 +10,13 @@
|
||||
import archspec.cpu
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.executable import Executable
|
||||
|
||||
import spack.target
|
||||
import spack.version
|
||||
from spack.operating_systems.cray_backend import CrayBackend
|
||||
from spack.operating_systems.cray_frontend import CrayFrontend
|
||||
from spack.paths import build_env_path
|
||||
from spack.util.executable import Executable
|
||||
from spack.util.module_cmd import module
|
||||
|
||||
from ._platform import NoPlatformError, Platform
|
||||
|
@@ -12,6 +12,7 @@
|
||||
import macholib.mach_o
|
||||
import macholib.MachO
|
||||
|
||||
import llnl.util.executable as executable
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
@@ -24,7 +25,6 @@
|
||||
import spack.spec
|
||||
import spack.store
|
||||
import spack.util.elf as elf
|
||||
import spack.util.executable as executable
|
||||
|
||||
is_macos = str(spack.platforms.real_host()) == "darwin"
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lang
|
||||
import llnl.util.path
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import working_dir
|
||||
|
||||
@@ -563,7 +564,7 @@ def __init__(self, package_checker, namespace, cache):
|
||||
self.checker = package_checker
|
||||
self.packages_path = self.checker.packages_path
|
||||
if sys.platform == "win32":
|
||||
self.packages_path = spack.util.path.convert_to_posix_path(self.packages_path)
|
||||
self.packages_path = llnl.util.path.convert_to_posix_path(self.packages_path)
|
||||
self.namespace = namespace
|
||||
|
||||
self.indexers = {}
|
||||
|
@@ -40,9 +40,9 @@ def parse(config_obj):
|
||||
config_obj: a configuration dictionary conforming to the
|
||||
schema definition for environment modifications
|
||||
"""
|
||||
import spack.util.environment as ev
|
||||
import llnl.util.envmod as envmod
|
||||
|
||||
env = ev.EnvironmentModifications()
|
||||
env = envmod.EnvironmentModifications()
|
||||
for command, variable in config_obj.items():
|
||||
# Distinguish between commands that take only a name as argument
|
||||
# (e.g. unset) and commands that take a name and a value.
|
||||
|
@@ -59,8 +59,11 @@
|
||||
|
||||
import ruamel.yaml as yaml
|
||||
|
||||
import llnl.util.executable
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.lang as lang
|
||||
import llnl.util.path as pth
|
||||
import llnl.util.string
|
||||
import llnl.util.tty as tty
|
||||
import llnl.util.tty.color as clr
|
||||
|
||||
@@ -79,14 +82,11 @@
|
||||
import spack.target
|
||||
import spack.traverse as traverse
|
||||
import spack.util.crypto
|
||||
import spack.util.executable
|
||||
import spack.util.hash
|
||||
import spack.util.module_cmd as md
|
||||
import spack.util.path as pth
|
||||
import spack.util.prefix
|
||||
import spack.util.spack_json as sjson
|
||||
import spack.util.spack_yaml as syaml
|
||||
import spack.util.string
|
||||
import spack.variant as vt
|
||||
import spack.version as vn
|
||||
|
||||
@@ -988,7 +988,7 @@ def _command_default_handler(descriptor, spec, cls):
|
||||
path = os.path.join(home.bin, spec.name)
|
||||
|
||||
if fs.is_exe(path):
|
||||
return spack.util.executable.Executable(path)
|
||||
return llnl.util.executable.Executable(path)
|
||||
else:
|
||||
msg = "Unable to locate {0} command in {1}"
|
||||
raise RuntimeError(msg.format(spec.name, home.bin))
|
||||
@@ -5041,7 +5041,7 @@ class InvalidDependencyError(spack.error.SpecError):
|
||||
def __init__(self, pkg, deps):
|
||||
self.invalid_deps = deps
|
||||
super(InvalidDependencyError, self).__init__(
|
||||
"Package {0} does not depend on {1}".format(pkg, spack.util.string.comma_or(deps))
|
||||
"Package {0} does not depend on {1}".format(pkg, llnl.util.string.comma_or(deps))
|
||||
)
|
||||
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
partition_path,
|
||||
remove_linked_tree,
|
||||
)
|
||||
from llnl.util.path import sanitize_file_path
|
||||
|
||||
import spack.caches
|
||||
import spack.config
|
||||
@@ -378,7 +379,7 @@ def expected_archive_files(self):
|
||||
expanded = True
|
||||
if isinstance(self.default_fetcher, fs.URLFetchStrategy):
|
||||
expanded = self.default_fetcher.expand_archive
|
||||
clean_url = os.path.basename(sup.sanitize_file_path(self.default_fetcher.url))
|
||||
clean_url = os.path.basename(sanitize_file_path(self.default_fetcher.url))
|
||||
fnames.append(clean_url)
|
||||
|
||||
if self.mirror_paths:
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
import llnl.util.executable
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.compiler
|
||||
@@ -161,7 +162,7 @@ def optimization_flags(self, compiler):
|
||||
compiler = spack.compilers.compilers_for_spec(compiler).pop()
|
||||
try:
|
||||
compiler_version = compiler.real_version
|
||||
except spack.util.executable.ProcessError as e:
|
||||
except llnl.util.executable.ProcessError as e:
|
||||
# log this and just return compiler.version instead
|
||||
tty.debug(str(e))
|
||||
|
||||
|
@@ -10,7 +10,10 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.envmod import EnvironmentModifications
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.filesystem import HeaderList, LibraryList
|
||||
from llnl.util.path import Path, convert_to_platform_path
|
||||
|
||||
import spack.build_environment
|
||||
import spack.config
|
||||
@@ -23,9 +26,6 @@
|
||||
dso_suffix,
|
||||
)
|
||||
from spack.paths import build_env_path
|
||||
from spack.util.environment import EnvironmentModifications
|
||||
from spack.util.executable import Executable
|
||||
from spack.util.path import Path, convert_to_platform_path
|
||||
|
||||
|
||||
def os_pathsep_join(path, *pths):
|
||||
|
@@ -7,9 +7,10 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import llnl.util.executable
|
||||
|
||||
import spack.cmd.create
|
||||
import spack.stage
|
||||
import spack.util.executable
|
||||
import spack.util.url as url_util
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
|
||||
@@ -46,7 +47,7 @@ def url_and_build_system(request, tmpdir):
|
||||
the appropriate file name and returns their url along with
|
||||
the correct build-system guess
|
||||
"""
|
||||
tar = spack.util.executable.which("tar")
|
||||
tar = llnl.util.executable.which("tar")
|
||||
orig_dir = tmpdir.chdir()
|
||||
filename, system = request.param
|
||||
tmpdir.ensure("archive", filename)
|
||||
|
@@ -11,6 +11,7 @@
|
||||
import pytest
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.executable import which
|
||||
|
||||
import spack.build_systems.autotools
|
||||
import spack.build_systems.cmake
|
||||
@@ -19,7 +20,6 @@
|
||||
import spack.repo
|
||||
from spack.build_environment import ChildError, setup_package
|
||||
from spack.spec import Spec
|
||||
from spack.util.executable import which
|
||||
|
||||
DATA_PATH = os.path.join(spack.paths.test_path, "data")
|
||||
|
||||
|
@@ -12,12 +12,13 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.envmod import set_env, system_dirs
|
||||
from llnl.util.executable import Executable, ProcessError
|
||||
|
||||
import spack.build_environment
|
||||
import spack.config
|
||||
import spack.spec
|
||||
from spack.paths import build_env_path
|
||||
from spack.util.environment import set_env, system_dirs
|
||||
from spack.util.executable import Executable, ProcessError
|
||||
|
||||
#
|
||||
# Complicated compiler test command
|
||||
|
@@ -7,13 +7,14 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.path import convert_to_posix_path
|
||||
|
||||
import spack.bootstrap
|
||||
import spack.bootstrap.core
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
import spack.main
|
||||
import spack.mirror
|
||||
from spack.util.path import convert_to_posix_path
|
||||
|
||||
_bootstrap = spack.main.SpackCommand("bootstrap")
|
||||
|
||||
|
@@ -7,11 +7,12 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.executable import which
|
||||
|
||||
import spack.cmd.create
|
||||
import spack.util.editor
|
||||
from spack.main import SpackCommand
|
||||
from spack.url import UndetectableNameError
|
||||
from spack.util.executable import which
|
||||
|
||||
create = SpackCommand("create")
|
||||
|
||||
|
@@ -10,10 +10,11 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.executable import which
|
||||
|
||||
import spack.config
|
||||
import spack.platforms
|
||||
from spack.main import SpackCommand, get_version
|
||||
from spack.util.executable import which
|
||||
|
||||
debug = SpackCommand("debug")
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
import spack.environment as ev
|
||||
import spack.spec
|
||||
import spack.util.path
|
||||
from spack.main import SpackCommand
|
||||
|
||||
develop = SpackCommand("develop")
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.link_tree
|
||||
from llnl.util.executable import Executable
|
||||
|
||||
import spack.cmd.env
|
||||
import spack.config
|
||||
@@ -28,7 +29,6 @@
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
from spack.spec import Spec
|
||||
from spack.stage import stage_prefix
|
||||
from spack.util.executable import Executable
|
||||
from spack.util.path import substitute_path_variables
|
||||
from spack.version import Version
|
||||
|
||||
@@ -638,7 +638,7 @@ def test_env_view_external_prefix(tmpdir_factory, mutable_database, mock_package
|
||||
e.install_all()
|
||||
e.write()
|
||||
|
||||
env_mod = spack.util.environment.EnvironmentModifications()
|
||||
env_mod = llnl.util.envmod.EnvironmentModifications()
|
||||
e.add_default_view_to_env(env_mod)
|
||||
env_variables = {}
|
||||
env_mod.apply_modifications(env_variables)
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import llnl.util.path
|
||||
from llnl.util.filesystem import getuid, touch
|
||||
|
||||
import spack
|
||||
@@ -35,7 +36,7 @@ def _platform_executables(monkeypatch):
|
||||
def _win_exe_ext():
|
||||
return ".bat"
|
||||
|
||||
monkeypatch.setattr(spack.util.path, "win_exe_ext", _win_exe_ext)
|
||||
monkeypatch.setattr(llnl.util.path, "win_exe_ext", _win_exe_ext)
|
||||
|
||||
|
||||
def define_plat_exe(exe):
|
||||
|
@@ -9,13 +9,12 @@
|
||||
import pytest
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.executable import ProcessError
|
||||
|
||||
import spack.bootstrap
|
||||
import spack.util.executable
|
||||
import spack.util.gpg
|
||||
from spack.main import SpackCommand
|
||||
from spack.paths import mock_gpg_data_path, mock_gpg_keys_path
|
||||
from spack.util.executable import ProcessError
|
||||
|
||||
#: spack command used by tests below
|
||||
gpg = SpackCommand("gpg")
|
||||
|
@@ -23,7 +23,6 @@
|
||||
import spack.environment as ev
|
||||
import spack.hash_types as ht
|
||||
import spack.package_base
|
||||
import spack.util.executable
|
||||
from spack.error import SpackError
|
||||
from spack.main import SpackCommand
|
||||
from spack.parser import SpecSyntaxError
|
||||
|
@@ -9,13 +9,13 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import FileFilter
|
||||
|
||||
import spack.main
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
from spack.cmd.style import changed_files
|
||||
from spack.util.executable import which
|
||||
|
||||
#: directory with sample style files
|
||||
style_data = os.path.join(spack.paths.test_path, "data", "style")
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
@@ -105,7 +106,7 @@ def test_test_output_on_error(
|
||||
out = spack_test("run", "test-error", fail_on_error=False)
|
||||
|
||||
assert "TestFailure" in out
|
||||
assert "Command exited with status 1" in out
|
||||
assert re.search(r"Command '[^\n]*' exited with status 1", out)
|
||||
|
||||
|
||||
def test_test_output_on_failure(
|
||||
@@ -137,7 +138,7 @@ def test_show_log_on_error(
|
||||
@pytest.mark.parametrize(
|
||||
"pkg_name,msgs",
|
||||
[
|
||||
("test-error", ["FAILED: Command exited", "TestFailure"]),
|
||||
("test-error", ["FAILED: Command '", "TestFailure"]),
|
||||
("test-fail", ["FAILED: Expected", "TestFailure"]),
|
||||
],
|
||||
)
|
||||
@@ -189,7 +190,7 @@ def test_cdash_output_test_error(
|
||||
report_file = report_dir.join("test-error_Testing.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert "FAILED: Command exited with status 1" in content
|
||||
assert re.search(r"FAILED: Command '[^\n]*' exited with status 1", content)
|
||||
|
||||
|
||||
def test_cdash_upload_clean_test(
|
||||
|
@@ -10,14 +10,14 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import llnl.util.envmod
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.executable import ProcessError
|
||||
|
||||
import spack.compiler
|
||||
import spack.compilers as compilers
|
||||
import spack.spec
|
||||
import spack.util.environment
|
||||
from spack.compiler import Compiler
|
||||
from spack.util.executable import ProcessError
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -215,7 +215,7 @@ def call_compiler(exe, *args, **kwargs):
|
||||
def test_get_compiler_link_paths(monkeypatch, exe, flagname):
|
||||
# create fake compiler that emits mock verbose output
|
||||
compiler = MockCompiler()
|
||||
monkeypatch.setattr(spack.util.executable.Executable, "__call__", call_compiler)
|
||||
monkeypatch.setattr(llnl.util.executable.Executable, "__call__", call_compiler)
|
||||
|
||||
# Grab executable path to test
|
||||
paths = [getattr(compiler, exe)]
|
||||
@@ -798,7 +798,7 @@ def module(*args):
|
||||
def _call(*args, **kwargs):
|
||||
raise ProcessError("Failed intentionally")
|
||||
|
||||
monkeypatch.setattr(spack.util.executable.Executable, "__call__", _call)
|
||||
monkeypatch.setattr(llnl.util.executable.Executable, "__call__", _call)
|
||||
|
||||
# Run and no change to environment
|
||||
compilers = spack.compilers.get_compilers([compiler_dict])
|
||||
@@ -868,7 +868,7 @@ class MockPackage(object):
|
||||
"x86_64",
|
||||
["/usr/bin/clang", "/usr/bin/clang++", None, None],
|
||||
)
|
||||
env = spack.util.environment.EnvironmentModifications()
|
||||
env = llnl.util.envmod.EnvironmentModifications()
|
||||
# Check a package that doesn't use xcode and ensure we don't add changes
|
||||
# to the environment
|
||||
pkg = MockPackage()
|
||||
@@ -955,7 +955,7 @@ def test_xcode_not_available(xcode_select_output, mock_executable, monkeypatch):
|
||||
"x86_64",
|
||||
["/usr/bin/clang", "/usr/bin/clang++", None, None],
|
||||
)
|
||||
env = spack.util.environment.EnvironmentModifications()
|
||||
env = llnl.util.envmod.EnvironmentModifications()
|
||||
|
||||
class MockPackage(object):
|
||||
use_xcode = True
|
||||
|
@@ -24,6 +24,7 @@
|
||||
import archspec.cpu.microarchitecture
|
||||
import archspec.cpu.schema
|
||||
|
||||
import llnl.util.executable
|
||||
import llnl.util.lang
|
||||
import llnl.util.lock
|
||||
import llnl.util.tty as tty
|
||||
@@ -45,7 +46,6 @@
|
||||
import spack.store
|
||||
import spack.subprocess_context
|
||||
import spack.test.cray_manifest
|
||||
import spack.util.executable
|
||||
import spack.util.git
|
||||
import spack.util.gpg
|
||||
import spack.util.spack_yaml as syaml
|
||||
@@ -511,7 +511,7 @@ def _skip_if_missing_executables(request):
|
||||
|
||||
if marker:
|
||||
required_execs = marker.args
|
||||
missing_execs = [x for x in required_execs if spack.util.executable.which(x) is None]
|
||||
missing_execs = [x for x in required_execs if llnl.util.executable.which(x) is None]
|
||||
if missing_execs:
|
||||
msg = "could not find executables: {0}"
|
||||
pytest.skip(msg.format(", ".join(missing_execs)))
|
||||
@@ -1108,7 +1108,7 @@ def mock_archive(request, tmpdir_factory):
|
||||
"""Creates a very simple archive directory with a configure script and a
|
||||
makefile that installs to a prefix. Tars it up into an archive.
|
||||
"""
|
||||
tar = spack.util.executable.which("tar")
|
||||
tar = llnl.util.executable.which("tar")
|
||||
if not tar:
|
||||
pytest.skip("requires tar to be installed")
|
||||
|
||||
@@ -1168,7 +1168,7 @@ def _parse_cvs_date(line):
|
||||
@pytest.fixture(scope="session")
|
||||
def mock_cvs_repository(tmpdir_factory):
|
||||
"""Creates a very simple CVS repository with two commits and a branch."""
|
||||
cvs = spack.util.executable.which("cvs", required=True)
|
||||
cvs = llnl.util.executable.which("cvs", required=True)
|
||||
|
||||
tmpdir = tmpdir_factory.mktemp("mock-cvs-repo-dir")
|
||||
tmpdir.ensure(spack.stage._source_path_subdir, dir=True)
|
||||
@@ -1460,7 +1460,7 @@ def mock_git_repository(git, tmpdir_factory):
|
||||
@pytest.fixture(scope="session")
|
||||
def mock_hg_repository(tmpdir_factory):
|
||||
"""Creates a very simple hg repository with two commits."""
|
||||
hg = spack.util.executable.which("hg")
|
||||
hg = llnl.util.executable.which("hg")
|
||||
if not hg:
|
||||
pytest.skip("requires mercurial to be installed")
|
||||
|
||||
@@ -1500,11 +1500,11 @@ def mock_hg_repository(tmpdir_factory):
|
||||
@pytest.fixture(scope="session")
|
||||
def mock_svn_repository(tmpdir_factory):
|
||||
"""Creates a very simple svn repository with two commits."""
|
||||
svn = spack.util.executable.which("svn")
|
||||
svn = llnl.util.executable.which("svn")
|
||||
if not svn:
|
||||
pytest.skip("requires svn to be installed")
|
||||
|
||||
svnadmin = spack.util.executable.which("svnadmin", required=True)
|
||||
svnadmin = llnl.util.executable.which("svnadmin", required=True)
|
||||
|
||||
tmpdir = tmpdir_factory.mktemp("mock-svn-stage")
|
||||
tmpdir.ensure(spack.stage._source_path_subdir, dir=True)
|
||||
@@ -1897,7 +1897,7 @@ def _factory(rpaths, message="Hello world!"):
|
||||
message
|
||||
)
|
||||
)
|
||||
gcc = spack.util.executable.which("gcc")
|
||||
gcc = llnl.util.executable.which("gcc")
|
||||
executable = source.dirpath("main.x")
|
||||
# Encode relative RPATHs using `$ORIGIN` as the root prefix
|
||||
rpaths = [x if os.path.isabs(x) else os.path.join("$ORIGIN", x) for x in rpaths]
|
||||
|
@@ -7,12 +7,12 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import mkdirp, touch, working_dir
|
||||
|
||||
from spack.fetch_strategy import CvsFetchStrategy
|
||||
from spack.spec import Spec
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
from spack.version import ver
|
||||
|
||||
pytestmark = pytest.mark.skipif(not which("cvs"), reason="requires CVS to be installed")
|
||||
|
@@ -10,7 +10,7 @@ import sys
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.build_environment
|
||||
import spack.util.executable
|
||||
import llnl.util.executable
|
||||
from spack.package import *
|
||||
|
||||
|
||||
@@ -378,7 +378,7 @@ class Llvm(CMakePackage, CudaPackage):
|
||||
match = version_regex.search(output)
|
||||
if match:
|
||||
return match.group(match.lastindex)
|
||||
except spack.util.executable.ProcessError:
|
||||
except llnl.util.executable.ProcessError:
|
||||
pass
|
||||
except Exception as e:
|
||||
tty.debug(e)
|
||||
|
@@ -23,6 +23,7 @@
|
||||
from jsonschema import validate
|
||||
|
||||
import llnl.util.lock as lk
|
||||
from llnl.util.executable import Executable
|
||||
from llnl.util.tty.colify import colify
|
||||
|
||||
import spack.database
|
||||
@@ -31,7 +32,6 @@
|
||||
import spack.spec
|
||||
import spack.store
|
||||
from spack.schema.database_index import schema
|
||||
from spack.util.executable import Executable
|
||||
|
||||
is_windows = sys.platform == "win32"
|
||||
|
||||
|
@@ -11,6 +11,8 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.path import path_to_os_path
|
||||
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
from spack.directory_layout import (
|
||||
@@ -18,7 +20,6 @@
|
||||
InvalidDirectoryLayoutParametersError,
|
||||
)
|
||||
from spack.spec import Spec
|
||||
from spack.util.path import path_to_os_path
|
||||
|
||||
# number of packages to test (to reduce test time)
|
||||
max_packages = 10
|
||||
|
@@ -8,18 +8,9 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.util.environment as environment
|
||||
import llnl.util.envmod as envmod
|
||||
|
||||
from spack.paths import spack_root
|
||||
from spack.util.environment import (
|
||||
AppendPath,
|
||||
EnvironmentModifications,
|
||||
PrependPath,
|
||||
RemovePath,
|
||||
SetEnv,
|
||||
UnsetEnv,
|
||||
filter_system_paths,
|
||||
is_system_path,
|
||||
)
|
||||
|
||||
datadir = os.path.join(spack_root, "lib", "spack", "spack", "test", "data")
|
||||
|
||||
@@ -43,7 +34,7 @@ def test_inspect_path(tmpdir):
|
||||
tmpdir.mkdir("lib")
|
||||
tmpdir.mkdir("include")
|
||||
|
||||
env = environment.inspect_path(str(tmpdir), inspections)
|
||||
env = envmod.inspect_path(str(tmpdir), inspections)
|
||||
names = [item.name for item in env]
|
||||
assert "PATH" in names
|
||||
assert "LIBRARY_PATH" in names
|
||||
@@ -58,7 +49,7 @@ def test_exclude_paths_from_inspection():
|
||||
"include": ["CPATH"],
|
||||
}
|
||||
|
||||
env = environment.inspect_path("/usr", inspections, exclude=is_system_path)
|
||||
env = envmod.inspect_path("/usr", inspections, exclude=envmod.is_system_path)
|
||||
|
||||
assert len(env) == 0
|
||||
|
||||
@@ -79,7 +70,7 @@ def prepare_environment_for_tests(working_env):
|
||||
@pytest.fixture
|
||||
def env(prepare_environment_for_tests):
|
||||
"""Returns an empty EnvironmentModifications object."""
|
||||
return EnvironmentModifications()
|
||||
return envmod.EnvironmentModifications()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -162,7 +153,7 @@ def test_unset(env):
|
||||
@pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows (yet)")
|
||||
def test_filter_system_paths(miscellaneous_paths):
|
||||
"""Tests that the filtering of system paths works as expected."""
|
||||
filtered = filter_system_paths(miscellaneous_paths)
|
||||
filtered = envmod.filter_system_paths(miscellaneous_paths)
|
||||
expected = [
|
||||
"/usr/local/Cellar/gcc/5.3.0/lib",
|
||||
"/usr/local/opt/some-package/lib",
|
||||
@@ -246,7 +237,7 @@ def test_extend(env):
|
||||
"""
|
||||
env.set("A", "dummy value")
|
||||
env.set("B", 3)
|
||||
copy_construct = EnvironmentModifications(env)
|
||||
copy_construct = envmod.EnvironmentModifications(env)
|
||||
|
||||
assert len(copy_construct) == 2
|
||||
|
||||
@@ -260,12 +251,12 @@ def test_source_files(files_to_be_sourced):
|
||||
"""Tests the construction of a list of environment modifications that are
|
||||
the result of sourcing a file.
|
||||
"""
|
||||
env = EnvironmentModifications()
|
||||
env = envmod.EnvironmentModifications()
|
||||
for filename in files_to_be_sourced:
|
||||
if filename.endswith("sourceme_parameters.sh"):
|
||||
env.extend(EnvironmentModifications.from_sourcing_file(filename, "intel64"))
|
||||
env.extend(envmod.EnvironmentModifications.from_sourcing_file(filename, "intel64"))
|
||||
else:
|
||||
env.extend(EnvironmentModifications.from_sourcing_file(filename))
|
||||
env.extend(envmod.EnvironmentModifications.from_sourcing_file(filename))
|
||||
|
||||
modifications = env.group_by_name()
|
||||
|
||||
@@ -277,28 +268,28 @@ def test_source_files(files_to_be_sourced):
|
||||
|
||||
# Set new variables
|
||||
assert len(modifications["NEW_VAR"]) == 1
|
||||
assert isinstance(modifications["NEW_VAR"][0], SetEnv)
|
||||
assert isinstance(modifications["NEW_VAR"][0], envmod.SetEnv)
|
||||
assert modifications["NEW_VAR"][0].value == "new"
|
||||
|
||||
assert len(modifications["FOO"]) == 1
|
||||
assert isinstance(modifications["FOO"][0], SetEnv)
|
||||
assert isinstance(modifications["FOO"][0], envmod.SetEnv)
|
||||
assert modifications["FOO"][0].value == "intel64"
|
||||
|
||||
# Unset variables
|
||||
assert len(modifications["EMPTY_PATH_LIST"]) == 1
|
||||
assert isinstance(modifications["EMPTY_PATH_LIST"][0], UnsetEnv)
|
||||
assert isinstance(modifications["EMPTY_PATH_LIST"][0], envmod.UnsetEnv)
|
||||
|
||||
# Modified variables
|
||||
assert len(modifications["UNSET_ME"]) == 1
|
||||
assert isinstance(modifications["UNSET_ME"][0], SetEnv)
|
||||
assert isinstance(modifications["UNSET_ME"][0], envmod.SetEnv)
|
||||
assert modifications["UNSET_ME"][0].value == "overridden"
|
||||
|
||||
assert len(modifications["PATH_LIST"]) == 3
|
||||
assert isinstance(modifications["PATH_LIST"][0], RemovePath)
|
||||
assert isinstance(modifications["PATH_LIST"][0], envmod.RemovePath)
|
||||
assert modifications["PATH_LIST"][0].value == "/path/third"
|
||||
assert isinstance(modifications["PATH_LIST"][1], AppendPath)
|
||||
assert isinstance(modifications["PATH_LIST"][1], envmod.AppendPath)
|
||||
assert modifications["PATH_LIST"][1].value == "/path/fourth"
|
||||
assert isinstance(modifications["PATH_LIST"][2], PrependPath)
|
||||
assert isinstance(modifications["PATH_LIST"][2], envmod.PrependPath)
|
||||
assert modifications["PATH_LIST"][2].value == "/path/first"
|
||||
|
||||
|
||||
@@ -307,7 +298,7 @@ def test_preserve_environment(prepare_environment_for_tests):
|
||||
# UNSET_ME is defined, and will be unset in the context manager,
|
||||
# NOT_SET is not in the environment and will be set within the
|
||||
# context manager, PATH_LIST is set and will be changed.
|
||||
with environment.preserve_environment("UNSET_ME", "NOT_SET", "PATH_LIST"):
|
||||
with envmod.preserve_environment("UNSET_ME", "NOT_SET", "PATH_LIST"):
|
||||
os.environ["NOT_SET"] = "a"
|
||||
assert os.environ["NOT_SET"] == "a"
|
||||
|
||||
@@ -363,7 +354,7 @@ def test_preserve_environment(prepare_environment_for_tests):
|
||||
@pytest.mark.usefixtures("prepare_environment_for_tests")
|
||||
def test_environment_from_sourcing_files(files, expected, deleted):
|
||||
|
||||
env = environment.environment_after_sourcing_files(*files)
|
||||
env = envmod.environment_after_sourcing_files(*files)
|
||||
|
||||
# Test that variables that have been modified are still there and contain
|
||||
# the expected output
|
||||
@@ -394,7 +385,7 @@ def test_clear(env):
|
||||
)
|
||||
def test_sanitize_literals(env, exclude, include):
|
||||
|
||||
after = environment.sanitize(env, exclude, include)
|
||||
after = envmod.sanitize(env, exclude, include)
|
||||
|
||||
# Check that all the included variables are there
|
||||
assert all(x in after for x in include)
|
||||
@@ -431,7 +422,7 @@ def test_sanitize_literals(env, exclude, include):
|
||||
)
|
||||
def test_sanitize_regex(env, exclude, include, expected, deleted):
|
||||
|
||||
after = environment.sanitize(env, exclude, include)
|
||||
after = envmod.sanitize(env, exclude, include)
|
||||
|
||||
assert all(x in after for x in expected)
|
||||
assert all(x not in after for x in deleted)
|
||||
@@ -442,39 +433,39 @@ def test_sanitize_regex(env, exclude, include, expected, deleted):
|
||||
"before,after,search_list",
|
||||
[
|
||||
# Set environment variables
|
||||
({}, {"FOO": "foo"}, [environment.SetEnv("FOO", "foo")]),
|
||||
({}, {"FOO": "foo"}, [envmod.SetEnv("FOO", "foo")]),
|
||||
# Unset environment variables
|
||||
({"FOO": "foo"}, {}, [environment.UnsetEnv("FOO")]),
|
||||
({"FOO": "foo"}, {}, [envmod.UnsetEnv("FOO")]),
|
||||
# Append paths to an environment variable
|
||||
(
|
||||
{"FOO_PATH": "/a/path"},
|
||||
{"FOO_PATH": "/a/path:/b/path"},
|
||||
[environment.AppendPath("FOO_PATH", "/b/path")],
|
||||
[envmod.AppendPath("FOO_PATH", "/b/path")],
|
||||
),
|
||||
(
|
||||
{},
|
||||
{"FOO_PATH": "/a/path" + os.sep + "/b/path"},
|
||||
[environment.AppendPath("FOO_PATH", "/a/path" + os.sep + "/b/path")],
|
||||
[envmod.AppendPath("FOO_PATH", "/a/path" + os.sep + "/b/path")],
|
||||
),
|
||||
(
|
||||
{"FOO_PATH": "/a/path:/b/path"},
|
||||
{"FOO_PATH": "/b/path"},
|
||||
[environment.RemovePath("FOO_PATH", "/a/path")],
|
||||
[envmod.RemovePath("FOO_PATH", "/a/path")],
|
||||
),
|
||||
(
|
||||
{"FOO_PATH": "/a/path:/b/path"},
|
||||
{"FOO_PATH": "/a/path:/c/path"},
|
||||
[
|
||||
environment.RemovePath("FOO_PATH", "/b/path"),
|
||||
environment.AppendPath("FOO_PATH", "/c/path"),
|
||||
envmod.RemovePath("FOO_PATH", "/b/path"),
|
||||
envmod.AppendPath("FOO_PATH", "/c/path"),
|
||||
],
|
||||
),
|
||||
(
|
||||
{"FOO_PATH": "/a/path:/b/path"},
|
||||
{"FOO_PATH": "/c/path:/a/path"},
|
||||
[
|
||||
environment.RemovePath("FOO_PATH", "/b/path"),
|
||||
environment.PrependPath("FOO_PATH", "/c/path"),
|
||||
envmod.RemovePath("FOO_PATH", "/b/path"),
|
||||
envmod.PrependPath("FOO_PATH", "/c/path"),
|
||||
],
|
||||
),
|
||||
# Modify two variables in the same environment
|
||||
@@ -482,15 +473,15 @@ def test_sanitize_regex(env, exclude, include, expected, deleted):
|
||||
{"FOO": "foo", "BAR": "bar"},
|
||||
{"FOO": "baz", "BAR": "baz"},
|
||||
[
|
||||
environment.SetEnv("FOO", "baz"),
|
||||
environment.SetEnv("BAR", "baz"),
|
||||
envmod.SetEnv("FOO", "baz"),
|
||||
envmod.SetEnv("BAR", "baz"),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_from_environment_diff(before, after, search_list):
|
||||
|
||||
mod = environment.EnvironmentModifications.from_environment_diff(before, after)
|
||||
mod = envmod.EnvironmentModifications.from_environment_diff(before, after)
|
||||
|
||||
for item in search_list:
|
||||
assert item in mod
|
||||
@@ -501,7 +492,7 @@ def test_from_environment_diff(before, after, search_list):
|
||||
def test_exclude_lmod_variables():
|
||||
# Construct the list of environment modifications
|
||||
file = os.path.join(datadir, "sourceme_lmod.sh")
|
||||
env = EnvironmentModifications.from_sourcing_file(file)
|
||||
env = envmod.EnvironmentModifications.from_sourcing_file(file)
|
||||
|
||||
# Check that variables related to lmod are not in there
|
||||
modifications = env.group_by_name()
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import mkdirp, touch, working_dir
|
||||
|
||||
import spack.config
|
||||
@@ -15,7 +16,6 @@
|
||||
from spack.fetch_strategy import HgFetchStrategy
|
||||
from spack.spec import Spec
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
from spack.version import ver
|
||||
|
||||
# Test functionality covered is supported on Windows, but currently failing
|
||||
|
@@ -9,13 +9,13 @@
|
||||
import pytest
|
||||
|
||||
import llnl.util.filesystem as fs
|
||||
from llnl.util.executable import Executable
|
||||
|
||||
import spack.platforms
|
||||
from spack.hooks.absolutify_elf_sonames import (
|
||||
SharedLibrariesVisitor,
|
||||
find_and_patch_sonames,
|
||||
)
|
||||
from spack.util.executable import Executable
|
||||
|
||||
|
||||
def skip_unless_linux(f):
|
||||
|
136
lib/spack/spack/test/llnl/util/envmod.py
Normal file
136
lib/spack/spack/test/llnl/util/envmod.py
Normal file
@@ -0,0 +1,136 @@
|
||||
# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
"""Test Spack's environment utility functions."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
import llnl.util.envmod as envmod
|
||||
|
||||
is_windows = sys.platform == "win32"
|
||||
|
||||
|
||||
def test_is_system_path():
|
||||
sys_path = "C:\\Users" if is_windows else "/usr/bin"
|
||||
assert envmod.is_system_path(sys_path)
|
||||
assert not envmod.is_system_path("/nonsense_path/bin")
|
||||
assert not envmod.is_system_path("")
|
||||
assert not envmod.is_system_path(None)
|
||||
|
||||
|
||||
if is_windows:
|
||||
test_paths = [
|
||||
"C:\\Users",
|
||||
"C:\\",
|
||||
"C:\\ProgramData",
|
||||
"C:\\nonsense_path",
|
||||
"C:\\Program Files",
|
||||
"C:\\nonsense_path\\extra\\bin",
|
||||
]
|
||||
else:
|
||||
test_paths = [
|
||||
"/usr/bin",
|
||||
"/nonsense_path/lib",
|
||||
"/usr/local/lib",
|
||||
"/bin",
|
||||
"/nonsense_path/extra/bin",
|
||||
"/usr/lib64",
|
||||
]
|
||||
|
||||
|
||||
def test_filter_system_paths():
|
||||
nonsense_prefix = "C:\\nonsense_path" if is_windows else "/nonsense_path"
|
||||
expected = [p for p in test_paths if p.startswith(nonsense_prefix)]
|
||||
filtered = envmod.filter_system_paths(test_paths)
|
||||
assert expected == filtered
|
||||
|
||||
|
||||
def deprioritize_system_paths():
|
||||
expected = [p for p in test_paths if p.startswith("/nonsense_path")]
|
||||
expected.extend([p for p in test_paths if not p.startswith("/nonsense_path")])
|
||||
filtered = envmod.deprioritize_system_paths(test_paths)
|
||||
assert expected == filtered
|
||||
|
||||
|
||||
def test_prune_duplicate_paths():
|
||||
test_paths = ["/a/b", "/a/c", "/a/b", "/a/a", "/a/c", "/a/a/.."]
|
||||
expected = ["/a/b", "/a/c", "/a/a", "/a/a/.."]
|
||||
assert expected == envmod.prune_duplicate_paths(test_paths)
|
||||
|
||||
|
||||
def test_get_path(working_env):
|
||||
os.environ["TEST_ENV_VAR"] = os.pathsep.join(["/a", "/b", "/c/d"])
|
||||
expected = ["/a", "/b", "/c/d"]
|
||||
assert envmod.get_path("TEST_ENV_VAR") == expected
|
||||
|
||||
|
||||
def test_env_flag(working_env):
|
||||
assert not envmod.env_flag("TEST_NO_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "1"
|
||||
assert envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "TRUE"
|
||||
assert envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "True"
|
||||
assert envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "TRue"
|
||||
assert envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "true"
|
||||
assert envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "27"
|
||||
assert not envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "-2.3"
|
||||
assert not envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "0"
|
||||
assert not envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "False"
|
||||
assert not envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "false"
|
||||
assert not envmod.env_flag("TEST_ENV_VAR")
|
||||
os.environ["TEST_ENV_VAR"] = "garbage"
|
||||
assert not envmod.env_flag("TEST_ENV_VAR")
|
||||
|
||||
|
||||
def test_path_set(working_env):
|
||||
envmod.path_set("TEST_ENV_VAR", ["/a", "/a/b", "/a/a"])
|
||||
assert os.environ["TEST_ENV_VAR"] == "/a" + os.pathsep + "/a/b" + os.pathsep + "/a/a"
|
||||
|
||||
|
||||
def test_path_put_first(working_env):
|
||||
envmod.path_set("TEST_ENV_VAR", test_paths)
|
||||
expected = ["/usr/bin", "/new_nonsense_path/a/b"]
|
||||
expected.extend([p for p in test_paths if p != "/usr/bin"])
|
||||
envmod.path_put_first("TEST_ENV_VAR", expected)
|
||||
assert envmod.get_path("TEST_ENV_VAR") == expected
|
||||
|
||||
|
||||
def test_reverse_environment_modifications(working_env):
|
||||
start_env = {
|
||||
"PREPEND_PATH": os.sep + os.path.join("path", "to", "prepend", "to"),
|
||||
"APPEND_PATH": os.sep + os.path.join("path", "to", "append", "to"),
|
||||
"UNSET": "var_to_unset",
|
||||
"APPEND_FLAGS": "flags to append to",
|
||||
}
|
||||
|
||||
to_reverse = envmod.EnvironmentModifications()
|
||||
|
||||
to_reverse.prepend_path("PREPEND_PATH", "/new/path/prepended")
|
||||
to_reverse.append_path("APPEND_PATH", "/new/path/appended")
|
||||
to_reverse.set_path("SET_PATH", ["/one/set/path", "/two/set/path"])
|
||||
to_reverse.set("SET", "a var")
|
||||
to_reverse.unset("UNSET")
|
||||
to_reverse.append_flags("APPEND_FLAGS", "more_flags")
|
||||
|
||||
reversal = to_reverse.reversed()
|
||||
|
||||
os.environ = start_env.copy()
|
||||
|
||||
print(os.environ)
|
||||
to_reverse.apply_modifications()
|
||||
print(os.environ)
|
||||
reversal.apply_modifications()
|
||||
print(os.environ)
|
||||
|
||||
start_env.pop("UNSET")
|
||||
assert os.environ == start_env
|
20
lib/spack/spack/test/llnl/util/path.py
Normal file
20
lib/spack/spack/test/llnl/util/path.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import llnl.util.path
|
||||
|
||||
|
||||
def test_sanitze_file_path(tmpdir):
|
||||
"""Test filtering illegal characters out of potential file paths"""
|
||||
# *nix illegal files characters are '/' and none others
|
||||
illegal_file_path = str(tmpdir) + "//" + "abcdefghi.txt"
|
||||
if sys.platform == "win32":
|
||||
# Windows has a larger set of illegal characters
|
||||
illegal_file_path = os.path.join(tmpdir, 'a<b>cd?e:f"g|h*i.txt')
|
||||
real_path = llnl.util.path.sanitize_file_path(illegal_file_path)
|
||||
assert real_path == os.path.join(str(tmpdir), "abcdefghi.txt")
|
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
from spack.util.string import plural
|
||||
from llnl.util.string import plural
|
||||
|
||||
|
||||
def test_plural():
|
@@ -19,8 +19,7 @@
|
||||
import llnl.util.lang as lang
|
||||
import llnl.util.tty.log as log
|
||||
import llnl.util.tty.pty as pty
|
||||
|
||||
from spack.util.executable import which
|
||||
from llnl.util.executable import which
|
||||
|
||||
termios: Optional[ModuleType] = None
|
||||
try:
|
||||
|
@@ -7,10 +7,10 @@
|
||||
|
||||
import pytest
|
||||
|
||||
import llnl.util.executable as exe
|
||||
import llnl.util.filesystem as fs
|
||||
|
||||
import spack.paths
|
||||
import spack.util.executable as exe
|
||||
import spack.util.git
|
||||
from spack.main import get_version, main
|
||||
|
||||
|
@@ -16,8 +16,9 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.envmod import path_put_first
|
||||
|
||||
from spack.build_environment import MakeExecutable
|
||||
from spack.util.environment import path_put_first
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
sys.platform == "win32",
|
||||
|
@@ -9,16 +9,15 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from llnl.util.executable import which
|
||||
from llnl.util.filesystem import resolve_link_target_relative_to_the_link
|
||||
|
||||
import spack.mirror
|
||||
import spack.repo
|
||||
import spack.util.executable
|
||||
import spack.util.spack_json as sjson
|
||||
import spack.util.url as url_util
|
||||
from spack.spec import Spec
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
from spack.util.spack_yaml import SpackYAMLError
|
||||
|
||||
pytestmark = [
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user